天天看點

webapi token、參數簽名是如何生成的

一個問題

在這裡我想問大家一句,如果你向一個剛剛接觸.net web後端程式開發的同學(别人剛剛也就學了webform的request,response,會送出表單的這種剛接觸不久的同學),你怎麼去解釋标題“webapi token驗證”。

簡單的來說我的答案是:“要對用戶端(浏覽器,app)發的請求(送出表單)加限制,這個限制就是不要随随便便就去接收個請求就出查詢資料庫,最基本的判斷要證明此請求是”誰發出的。

API接口保障安全性原則:1.有調用者身份2.請求的唯一性3.請求的參數不能被篡改4.請求的有效時間

在我剛接觸背景程式的開發時,腦子裡壓根就沒有這個接口調用安全性的原則,随着寫代碼的增加,經驗的增加,每一個請求都應該有原則地保障安全性。

例如這個接口  http://127.0.0.1/api/user/list?type=value 這個擷取使用者資訊的請求總不能在位址欄一輸入就直接顯示資訊(雖然有點誇張,不至于阿貓阿狗的資訊這麼容易get吧),在寫webapi接口原則性的基本要求必須得保證資料的安全性和請求的有效性

在這裡我就使用Token+參數簽名+時間戳  這三個系統參數來辦證請求的有效性(即時100%請求有效,也不能說100%也安全了)。

參數名 必選 類型 作用
token string 調用方辨別,保障其身份是來自本系統認證過的,有效識别使用者身份
sign 接口參數的key,value的記錄,防止參數值被篡改,防止僞裝請求
timestamp int 時間戳,防止重播攻擊

那麼問題來

1.token 如何生成?作用是什麼?

2.參數簽名如何生成?作用是什麼?

3.時間戳的作用是什麼?

看了這篇文章你就知道了。這三個系統參數是如何保證請求的有效性,一定程度上提高資料的安全性

1.token如何生成的?作用是什麼?

token生成:(簡單通俗做法)使用者登入輸入使用者名、密碼,通路api,驗證資料庫成功。這個時候可以産生token,失敗直接傳回。問題又來了!

1.token生成的方式是什麼?2.token存在哪裡?3.token如何驗證是否正确

在驗證資料成功之後可以擷取唯一使用者辨別(使用者名也行),就以username:zhanglin為例吧,對這個辨別進行加密(des,MD5、其他的也行,關鍵資料必須得加密),這個加密之後的字元串就可以做為一個Token了。

2.token每次請求都需要進行傳遞,推薦存在cookie,也可以持久化到用戶端。現在有這樣一個api接口http://127.0.0.1/api/user/list?token=encryptUsernameStr

這個encryptZhanglinStr就是登入成功後加密的username傳回的cookie值字元串,到了伺服器端方法驗證的時候再進行解密,擷取到字元串zhanglin,然後将這個zhanglin與系統使用者(可采用緩存資料庫、緩存token的值)對比,如果對比存在,則說明有權限去通路api,反之非法的請求。

還是代碼來實作一下吧。代碼比較容易了解,就是為了把這個原理說清楚一點

[Route("login")]
        public bool login(string account, string pwd)
        {
            var obj = Db.dbUsers.FirstOrDefault(f => f.Account == account && f.Pwd == pwd);
            if (obj != null)
            {
                string token = account.DESEncrypt(desKey);//加密産生token,
                HttpCookie cookie = new HttpCookie(cookieToken,token);
                HttpContext.Current.Response.Cookies.Add(cookie);//儲存cookie
                return true;
            }
            else
            {
                return false;
            }
        }      

token的産生就是登陸之後根據使用者辨別儲存在cookie裡,這樣在用戶端每次發送請求的時候都會帶上token這個參數,如下:

[Route("list"), HttpGet]
        public List<string> List(string  type,string token)
        {
            var obj = Db.dbUsers.FirstOrDefault(p => p.Account == token.DESDecrypt(desKey));
            //驗證token
            if (obj != null)
            {
                //傳回資料集
            }
            else
            {
                //非法請求
            }
        }      

3.這樣就可以驗證token是否正确,一般都是用緩存。

Token的作用的就是判斷請求是否是系統使用者發出的,這樣能有效識别請求使用者的身份資訊

2..參數簽名如何生成?作用是什麼?

參數簽名sign:為了提高傳參過程中,防止參數被惡意修改,在請求接口的時候加上sign可以有效防止參數被篡改,那麼sign是如何起作用的呢?

看看它的生成方法就明白了

比如有這樣一個接口http:127.0.0.1/api/product?&type=zl&p1=value1&p2=value2&p3=&sign=signValue

第一步:拼接參數字元串,除去sign參數本身和為空值的p3,那麼剩下的就是字元串type=zl&p1=value1&p2=value2,然後按參數名字元升(降)序,得到字元串

p1=value1&p2=value2&type=zl

第二步:然後做參數名和值的拼接,得到字元串p1value1p2value2type=zl,注意編碼,不能出現這種&quot; ,要轉碼後“後拼接

第三步:将字元串進行DES加密,假設p1value1p2value2type=zl進行des加密後的結果是abc123,最終得到的字元串abc123就是參數sign的值signValue

第四步:在接口中我們會接收到參數名sign的參數值abc123,然後解密得到字元串p1value1p2value2type=zl,再與接口中參數拼接排序後進行比較,如果不一樣則說明參數的循序不一樣,參數的值就一定是被修改過了。

總結:

1.接口的調用方和接口的提供方統一約定參數加密算法

2.參數簽名就是對參數key ,value的一個記錄。參數如果被修改肯定對不上參數簽名,就不會調用請求

3.時間戳的作用?

在api請求的接口,用戶端請求的發生時間便是時間戳,這個參數到了伺服器,與伺服器端時間對比,如果時間間隔較長則無效。

在asp.net mvc的開發webapi接口時,可以使用mvc的過濾器進行以上三個關鍵參數的攔截過濾。以下代碼是在.net core中實作的,方法還是一樣的,都是在進入方法前進行攔截,這是一個登入的api。

傳回api結果是一個類ApiResult.cs,序列化成json對象,該類包含兩個泛型方法請求成功的Ok方法,請求失敗的Error方法

public class MyFilterAttribute : Microsoft.AspNetCore.Mvc.Filters.ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            var request_param = context.ActionArguments.Values;
            var  queryCollection = context.HttpContext.Request.Query;
            string account = string.Empty;
            string password = string.Empty;
            long timespan = 0;
            string signature = string.Empty;
            try
            {
                account = queryCollection.Where(p => p.Key == "account").Select(f => f.Value).FirstOrDefault().ToString();
                password = queryCollection.Where(p => p.Key == "password").Select(f => f.Value).FirstOrDefault().ToString();
                timespan = long.Parse(queryCollection.Where(p => p.Key == "timespan").Select(f => f.Value).FirstOrDefault().ToString());
                signature = queryCollection.Where(p => p.Key == "signature").Select(f => f.Value).FirstOrDefault().ToString();
            }
            catch (Exception ex)
            {
                var apiresult = ApiResult<bool>.Error("參數異常"+ex.ToString());
                context.Result = new JsonResult(apiresult);
            }
            //var accountName = context.RouteData.Values["accountName"].ToString()
            var expires_minute = (timespan - DateTime.Now.Ticks) / 60000000000;
            if (expires_minute> 10||expires_minute<-10)
            {
                var apimodel = ApiResult<bool>.Error("請求逾時"+expires_minute);
                //var json = JsonConvert.SerializeObject(apimodel);
                JsonResult ret = new JsonResult(apimodel);
                context.Result =ret;
            }
            var ok = ("account" + account + "password" + password).Contains(signature);//ToDO 加密解密
            if (ok == false)
            {
                var apimodel = ApiResult<bool>.Error("非法請求");
                var json = JsonConvert.SerializeObject(apimodel);
                JsonResult ret = new JsonResult(apimodel);
                context.Result = ret;
            }
            base.OnActionExecuting(context);
        }

    }      

作者:張林

原文标題:

 webapi

token、參數簽名是如何生成的

原文連結:http://blog.csdn.net/kebi007/article/details/72861532

轉載随意注明出處