MVC WebApi 实现Token验证

我们知道WEB网站的身份验证一般通过session或者cookie完成的,登录成功后客户端发送的任何请求都带上cookie,服务端根据客户端发送来的cookie来识别用户。
WEB API使用这样的方法不是很适合,于是就有了基于令牌的认证,使用令牌认证有几个好处:可扩展性、松散耦合、移动终端调用比较简单等等。

需要安装的NuGet包

JWT
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
namespace HrApi.App_Start
{
    /// <summary>  
    /// HTTP消息拦截器  
    /// </summary>
    public class RequestHandler : DelegatingHandler
    {
        /// <summary>  
        /// 拦截请求  
        /// </summary>  
        /// <param name="request">请求</param>  
        /// <param name="cancellationToken">用于发送取消操作信号</param>  
        /// <returns></returns>  
        protected async override Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
        {
            //获取URL参数  
            NameValueCollection query = HttpUtility.ParseQueryString(request.RequestUri.Query);

            JavaScriptSerializer serializer = new JavaScriptSerializer();
            //获取请求头信息
            if (request.Method.ToString().ToUpper() == "POST" && request.Headers != null)
            {
                var obj = request.Headers.Authorization;
                if (obj != null && obj.Scheme != null && obj.Parameter != null)
                {
                    ServerResult ret = new ServerResult();
                    var scheme = obj.Scheme;
                    var token = obj.Parameter;//token
                    var userInfo = JwtToken.ValidateJwtToken(token);
                    if (userInfo == "expired")
                    {
                        ret.code = "401";
                        ret.msg = "Token过期,请重新登录";
                        return SendError(serializer.Serialize(ret), HttpStatusCode.OK);
                        //过期
                    }
                    else if (userInfo == "invalid")
                    {
                        ret.msg = "Token验证不通过,请重新登录";
                        ret.code = "401";
                        return SendError(serializer.Serialize(ret), HttpStatusCode.OK);
                        //验证失败
                    }
                    else if (userInfo == "error")
                    {
                        ret.msg = "Token验证出错,请重新登录";
                        ret.code = "401";
                        return SendError(serializer.Serialize(ret), HttpStatusCode.OK);
                        //验证出错
                    }
                    else
                    {
                        //string ss = tokenInfo;
                        Dictionary<string, object> user = (Dictionary<string, object>)serializer.DeserializeObject(userInfo);
                        string username = user["username"].ToString();
                        string Id = user["userId"].ToString();
                        double exp = Convert.ToDouble(user["exp"].ToString());
                        string companyId = user["companyId"].ToString();
                        //获取Post正文数据,比如json文本  
                        //string fRequesContent = request.Content.ReadAsStringAsync().Result;
                        调用内部处理接口,并获取HTTP响应消息
                        double now_exp = (DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds;
                        double exp2 = exp - now_exp;
                        if (now_exp < exp && exp - now_exp < 9000)
                        {//两个半小时后 再次刷新token
                            HttpResponseMessage response2 = await base.SendAsync(request, cancellationToken);
                            if (response2.Content != null)//向前端返回402  刷新token
                            {
                                string fResponseContent = response2.Content.ReadAsStringAsync().Result;
                                Dictionary<string, object> dic = (Dictionary<string, object>)serializer.DeserializeObject(fResponseContent);
                                string newNoken = JwtToken.CreateToken(Id, username, companyId);
                                dic["code"] = 402;
                                dic.Add("token", newNoken);
                                string responseResultStr = serializer.Serialize(dic);
                                response2.Content = new StringContent(responseResultStr);
                            }
                            return response2;
                        }
                        //}
                    }

                }
            }
            //请求处理耗时跟踪  
            Stopwatch sw = new Stopwatch();
            sw.Start();
            //调用内部处理接口,并获取HTTP响应消息  
            HttpResponseMessage response = await base.SendAsync(request, cancellationToken);
            //篡改HTTP响应消息正文  
            //response.Content = new StringContent(response.Content.ReadAsStringAsync().Result.Replace(@"\\", @"\"));
            if (response.Content != null)
            {
                string fResponseContent = response.Content.ReadAsStringAsync().Result;
            }
            sw.Stop();
            //记录处理耗时  
            long exeMs = sw.ElapsedMilliseconds;
            return response;
        }

        /// <summary>  
        /// 构造自定义HTTP响应消息  
        /// </summary>  
        /// <param name="error"></param>  
        /// <param name="code"></param>  
        /// <returns></returns>  
        private HttpResponseMessage SendError(string error, HttpStatusCode code)
        {
            var response = new HttpResponseMessage();
            try
            {

                response.Content = new StringContent(error);
                response.StatusCode = code;
                //response.Headers.Add("Content-Type", "application/json");
                response.Headers.Add("Connection", "close");
                response.Headers.Add("Access-Control-Allow-Origin", "*");
                return response;
            }
            catch (Exception ex)
            {
                string ss = ex.Message;
                return new HttpResponseMessage(); ;
            }
        }
    }
}

在项目中添加JwtToken 类,来解析 token

using System;
using System.Collections.Generic;
using JWT;
using JWT.Algorithms;
using JWT.Serializers;
using JWT.Exceptions;
using System.Web.Script.Serialization;
using System.Collections;
using System.Web;

namespace BLL_API
{
    public class JwtToken
    {
        private static string secret = "XXXwwww4564qqq";
        /// <summary>
        /// 创建token
        /// </summary>
        /// <returns></returns>
        public static string CreateJwtToken(IDictionary<string, object> payload, string secret, IDictionary<string, object> extraHeaders = null)
        {
            IJwtAlgorithm algorithm = new HMACSHA256Algorithm();
            IJsonSerializer serializer = new JsonNetSerializer();
            IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
            IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);
            var token = encoder.Encode(payload, secret);
            return token;
        }
        /// <summary>
        /// 校验解析token
        /// </summary>
        /// <returns></returns>
        public static string ValidateJwtToken(string token)
        {
            try
            {
                IJsonSerializer serializer = new JsonNetSerializer();
                IDateTimeProvider provider = new UtcDateTimeProvider();
                IJwtValidator validator = new JwtValidator(serializer, provider);
                IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
                IJwtAlgorithm alg = new HMACSHA256Algorithm();
                IJwtDecoder decoder = new JwtDecoder(serializer, validator, urlEncoder, alg);
                var json = decoder.Decode(token, secret, true);
                //校验通过,返回解密后的字符串
                return json;
            }
            catch (TokenExpiredException)
            {
                //表示过期
                return "expired";
            }
            catch (SignatureVerificationException)
            {
                //表示验证不通过
                return "invalid";
            }
            catch (Exception)
            {
                return "error";
            }
        }
        /// <summary>
        /// 通过参数生成Token
        /// </summary>
        /// <returns></returns>
        public static string CreateToken(object userId,string username, object companyId)
        {
            #region 生成Token
            double exp = (DateTime.UtcNow.AddHours(3) - new DateTime(1970, 1, 1)).TotalSeconds;
            var payload = new Dictionary<string, object>
                         {
                             { "userId", userId },
                             { "username", username },
                             { "companyId", companyId },
                             { "exp",exp }
                          };
            var token = JwtToken.CreateJwtToken(payload, secret);
            return token;
            #endregion
        }
        /// <summary>
        /// Token验证,和刷新token
        /// </summary>
        /// <returns></returns>
        public static string  ValidateAndGetCompanyID()
        {
            ServerResult serverResult = BLL_API.ServerResult.GetAnNoDataResult("200", "success");
            string Authorization = HttpContext.Current.Request.Headers["Authorization"].ToString();
            string company_id ="0";
            if (Authorization.Length > 0)
            {
                string tokenInfo = ValidateJwtToken(Authorization.Replace("Bearer ", ""));
                if (tokenInfo == "expired")
                {
                    serverResult.code = "401";
                    serverResult.msg = "Token超时了,请重新登录";
                    //过期
                }
                else if (tokenInfo == "invalid")
                {
                    serverResult.code = "401";
                    serverResult.msg = "Token验证失败,请重新登录";
                    //验证失败
                }
                else if (tokenInfo == "error")
                {
                    serverResult.code = "401";
                    serverResult.msg = "Token验证出错,请重新登录";
                    //验证出错
                }
                else
                {
                    //刷新token
                    JavaScriptSerializer serializer = new JavaScriptSerializer();
                    Dictionary<string, object> obj = (Dictionary<string, object>)serializer.DeserializeObject(tokenInfo);
                    string username = obj["username"].ToString();
                    string userId = obj["userId"].ToString();
                    string companyId = obj["companyId"].ToString();
                    double exp = Convert.ToDouble(obj["exp"].ToString());
                    double nowTime = (DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds;
                    Hashtable hs = new Hashtable();
                    hs.Add("username", username);
                    hs.Add("userId", userId);
                    hs.Add("companyId", companyId);
                    double now_exp = (DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds;
                    double exp2 = exp - now_exp;
                    if (now_exp < exp && exp - now_exp < 9000)
                        //if (nowTime < exp)
                    {
                        #region 刷新Token
                        string newToken = CreateToken(userId, username,companyId);
                        hs.Add("token", newToken);
                        serverResult.code = "402";//刷新token
                        #endregion
                    }
                    serverResult.data = hs;
                    if(!string.IsNullOrEmpty(companyId))
                    {
                        company_id = companyId;
                    }

                }
            }
            return company_id;
        }
    }
}

这样就可以通过 Jwt生成需要的token了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值