webapi使用jwt做權限驗證

 考慮到很多公司目前並沒有切換到.netcore,所有本文嘗試使用.netframework下的webapi

 

首先使用Nuget 安裝 jwt包

安裝完成後,創建 jwt的幫助類

public  class JwtToken
    {
        static IJwtAlgorithm algorithm = new HMACSHA256Algorithm();//HMACSHA256加密
        static IJsonSerializer serializer = new JsonNetSerializer();//序列化和反序列
        static IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();//Base64編解碼
        static IDateTimeProvider provider = new UtcDateTimeProvider();//UTC時間獲取
        const string secret = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4aKpVo2OHXPwb1R7duLgg";//服務端
        /// <summary>
        /// 創建token
        /// </summary>
        /// <param name="payload">字典對象</param>
        /// <returns></returns>
        public static string CreateJWT(Dictionary<string, object> payload)
        {
            IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);
            return encoder.Encode(payload, secret);
        }
        /// <summary>
        /// 驗證token
        /// </summary>
        /// <param name="token">token值</param>
        /// <param name="payload">token還原後的字典</param>
        /// <param name="message">驗證結果</param>
        /// <returns></returns>
        public static bool ValidateJWT(string token, out string payload, out string message)
        {
            bool isValidted = false;
            payload = "";
            try
            {
                IJwtValidator validator = new JwtValidator(serializer, provider);//用於驗證JWT的類
              //  IJwtAlgorithm algorithm= new HMACSHA256Algorithm();
                IJwtDecoder decoder = new JwtDecoder(serializer, validator, urlEncoder,algorithm);//用於解析JWT的類
                payload = decoder.Decode(token, secret, verify: true);

                isValidted = true;

                message = "驗證成功";
            }
            catch (TokenExpiredException)//當前時間大於負載過期時間(負荷中的exp),會引發Token過期異常
            {
                message = "過期了!";
            }
            catch (SignatureVerificationException)//如果簽名不匹配,引發簽名驗證異常
            {
                message = "簽名錯誤!";
            }
            return isValidted;
        }
    }

然後創建相關的Model

 public class LoginResult
    {
        public bool Success { get; set; }

        public string Token { get; set; }

        public string Message { get; set; }
    }

創建獲取token的api

        public LoginResult Post([FromBody]LoginRequest request)
        {

            LoginResult rs = new LoginResult();
            //這是是獲取用戶名和密碼的,這裏只是爲了模擬
            if (request.UserName == "admin" && request.Password == "123456")
            {

           
                try
                {
                    var payload = new Dictionary<string, object>
            {
                { "username","admin"},//發行人
                { "exp", DateTimeOffset.UtcNow.AddSeconds(100).ToUnixTimeSeconds() },//到期時間
     
            };
                    rs.Token = JwtToken.CreateJWT(payload);
                    rs.Success = true;
                }
                catch (Exception ex)
                {
                    rs.Message = ex.Message;
                    rs.Success = false;
                }
            }
            else
            {
                rs.Message = "fail";
                rs.Success = false;
            }
            return rs;
        }

創建驗證token的filter

 public class ApiAuthorizeAttribute : AuthorizationFilterAttribute
    {
        public override void OnAuthorization(HttpActionContext actionContext)
        {
            var attr = actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().OfType<AllowAnonymousAttribute>();
            bool isAnonymous = attr.Any(a => a is AllowAnonymousAttribute);
            if (!isAnonymous)
            {
               var rq= actionContext.Request.Properties;
               
                var authorization = actionContext.Request.Headers.Authorization;
                 if (authorization==null)
                {
                    actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
                }
                else
                {
                    string ResultMessage;//需要解析的消息
                    string Payload;//獲取負載
                    var result = JwtToken.ValidateJWT(authorization.Scheme, out Payload, out ResultMessage); //TokenManager.ValidateToken(authorization.Scheme);
                    if (!result)
                    {
                        actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
                    }
                }
             
            }
        }

最後把特性加到需要需要驗證的Action上

     // GET: User
        [ApiAuthorize]
        public string Get()
        {
      
                return $"獲取到了";
           
        }

然後進行測試,首先獲取token

 

 調用接口,並傳入token值

 

 如果不傳入token值,那麼會報401錯誤

 

 當然了,那個401錯誤其實是在filter裏自己定義的,你改成別的狀態碼也是可以的,不過儘量還是要遵循國際慣例了

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章