部分内容转载自: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(); } } }
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; } } }
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; } } }