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