C# WebApi Token 實戰


部分內容轉載自:https://www.cnblogs.com/chenwolong/p/Token.html

首先引入JWT.dll(之前的博主沒有說要下載哪個版本的,我自己親測了一下,應該是2.3.2版本的JWT包)

-------------------------------------------------------

WebApi正式開始

1、我們自定義一個繼承自System.Web.Http 命名空間下的AuthorizeAttribute 屬性來解析並驗證TOKEN

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Web;
using System.Web.Http;
using System.Web.Http.Controllers;
using TestForToken.CommonCS;

namespace TestForToken.Auth2._0
{
    public class ApiActionAuth : AuthorizeAttribute
    {
        public override void OnAuthorization(HttpActionContext context)
        {
            var authHeader = context.Request.Headers.FirstOrDefault(a => a.Key == "ApiAuthorization");//獲取接收的Token

            if (context.Request.Headers == null || !context.Request.Headers.Any() || authHeader.Key == null || string.IsNullOrEmpty(authHeader.Value.FirstOrDefault()))
            {
                Throw401Exception(context, "NoToken");
                return;
            }
           
            var sendToken = authHeader.Value.FirstOrDefault();

            //url獲取token 
            var now = Math.Round((DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds + 5);//當前的時間戳
            var dictPayload = DecodeToken(sendToken);

            if (dictPayload == null)
            {
                Throw401Exception(context, "InvalidToken");
            }
            double iat = dictPayload["iat"];
            double exp = dictPayload["exp"];
            //檢查令牌的有效期
            if (!(iat < now && now < exp))//如果當前時間戳不再Token聲明周期范圍內,則返回Token過期
            {
                Throw401Exception(context, "TokenTimeout");
            }
            //獲取Token的自定義鍵值對
            int UserId = dictPayload["UserId"];
            string UserName = dictPayload["UserName"];
            string UserPwd = dictPayload["UserPwd"];
            string UserRole = dictPayload["UserRole"];

            //把toke用戶數據放到 HttpContext.Current.User 里
            ClientUserData clientUserData = new ClientUserData()
            {
                UserId = UserId,
                UserName = UserName,
                UserPwd = UserPwd,
                UserRole = UserRole

            };
            if (HttpContext.Current != null)
            {
                HttpContext.Current.User = new UserPrincipal(clientUserData);
            }

        }

        private static IDictionary<string, dynamic> DecodeToken(string token)
        {
            try
            {
                var dictPayload = JWT.JsonWebToken.DecodeToObject(token, CommonToken.SecretKey) as IDictionary<string, dynamic>;
                return dictPayload;
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        private static void Throw401Exception(HttpActionContext actionContext, string exceptionString)
        {
            var response = HttpContext.Current.Response;
            throw new HttpResponseException(
           actionContext.Request.CreateErrorResponse(System.Net.HttpStatusCode.Unauthorized, exceptionString ?? "Unauthorized"));
        }
        private static string RequestToString(HttpRequestMessage request)
        {
            var message = new StringBuilder();
            if (request.Method != null)
                message.Append(request.Method);

            if (request.RequestUri != null)
                message.Append(" ").Append(request.RequestUri);
            return message.ToString();
        }
    }
}
View Code

2、新增一個存儲解析Token結果的類,命名為SysHelper.cs,代碼如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Principal;
using System.Web;

namespace TestForToken.Auth2._0
{
    public class SysHelper
    {
        public static UserPrincipal CurrentPrincipal
        {
            get
            {
                return HttpContext.Current.User as UserPrincipal;
            }
        }
    }

    public class UserPrincipal : ClientUserData, IPrincipal
    {
        public IIdentity Identity { get; private set; }
        public string[] Roles { get; set; }

        public UserPrincipal(ClientUserData clientUserData)
        {
            this.Identity = new GenericIdentity(string.Format("{0}", clientUserData.UserId));
            this.UserId = clientUserData.UserId;
            this.UserName = clientUserData.UserName;
            this.UserPwd = clientUserData.UserPwd;
            this.UserRole = clientUserData.UserRole;
        }

        public bool IsInRole(string role)
        {
            if (Roles.Any(r => r == role))
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }

    public class ClientUserData
    {
        public int UserId { get; set; }

        public string UserName { get; set; }

        public string UserPwd { get; set; }

        public string UserRole { get; set; }
    }
}
View Code

3、公共Token生成方法修改如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
/*----------------------------------------------------------------
    Copyright (C) 2017 陳卧龍
    
    文件名:TestForToken.CommonCS
    文件功能描述:Token相關操作
----------------------------------------------------------------*/
namespace TestForToken.CommonCS
{
    public class CommonToken
    {
        public static string SecretKey = "This is a private key for Server";//這個服務端加密秘鑰 屬於私鑰

        public static string GetToken(TokenInfo M)
        {
            var jwtcreated =
               Math.Round((DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds + 5);
            var jwtcreatedOver =
            Math.Round((DateTime.UtcNow.AddHours(2) - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds + 5);//TOKEN聲明周期二小時
            var payload = new Dictionary<string, dynamic>
                {
                    {"iss", M.iss},//非必須。issuer 請求實體,可以是發起請求的用戶的信息,也可是jwt的簽發者。
                    {"iat", jwtcreated},//非必須。issued at。 token創建時間,unix時間戳格式
                    {"exp", jwtcreatedOver},//非必須。expire 指定token的生命周期。unix時間戳格式
                    {"aud", M.aud},//非必須。接收該JWT的一方。
                    {"sub", M.sub},//非必須。該JWT所面向的用戶
                    {"jti", M.jti},//非必須。JWT ID。針對當前token的唯一標識
                    {"UserId", M.UserId},//自定義字段 用於存放當前登錄人賬戶信息
                    {"UserName", M.UserName},//自定義字段 用於存放當前登錄人賬戶信息
                    {"UserPwd", M.UserPwd},//自定義字段 用於存放當前登錄人登錄密碼信息
                    {"UserRole", M.UserRole},//自定義字段 用於存放當前登錄人登錄權限信息
                };
            return JWT.JsonWebToken.Encode(payload, SecretKey,
                JWT.JwtHashAlgorithm.HS256);
        }
    }

    public class TokenInfo
    {
        public TokenInfo()
        {
            iss = "簽發者信息";
            aud = "http://example.com";
            sub = "HomeCare.VIP";
            jti = DateTime.Now.ToString("yyyyMMddhhmmss");
            UserId = 1;
            UserName = "jack.chen";
            UserPwd = "jack123456";
            UserRole = "HomeCare.Administrator";
        }
        //
        public string iss { get; set; }
        public string aud { get; set; }
        public string sub { get; set; }
        public string jti { get; set; }
        public int UserId { get; set; }
        public string UserName { get; set; }
        public string UserPwd { get; set; }
        public string UserRole { get; set; }
    }
}
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM