zoukankan      html  css  js  c++  java
  • .Net webapi使用JWT实现安全验证

     

    JSON Web Token(缩写 JWT)是目前最流行的跨域认证解决方案,本文介绍它的用法。

    jwt原理请看这里

     

    1、nuget中安装jwt

    2、新建3个实体

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    
    namespace Web.Models
    {
        /// <summary>
        /// 登录后的口令信息
        /// </summary>
        public class LoginResult
        {
            /// <summary>
            /// 是否成功
            /// </summary>
            public bool Success { get; set; }
    
            /// <summary>
            /// 令牌
            /// </summary>
            public string Token { get; set; }
    
            /// <summary>
            /// 错误信息
            /// </summary>
            public string Message { get; set; }
        }
        public class LoginRequest
        {
            public string UserName { get; set; }
    
            public string Password { get; set; }
        }
        /// <summary>
        /// 身份验证信息(模拟JWT的payload)
        /// </summary>
        public class AuthInfo
        {
            /// <summary>
            /// 用户名
            /// </summary>
            public string UserName { get; set; }
            /// <summary>
            /// 角色
            /// </summary>
            public List<string> Roles { get; set; }
            /// <summary>
            /// 是否管理员
            /// </summary>
            public bool IsAdmin { get; set; }
            /// <summary>
            /// 过期时间
            /// </summary>
            public DateTime? ExpiryDateTime { get; set; }
        }
    }

    3、新建过滤器

    using JWT;
    using JWT.Serializers;
    using Model;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Net.Http;
    using System.Web;
    using System.Web.Http;
    using System.Web.Http.Controllers;
    using Web.Models;
    
    namespace Web.Filter
    {
        /// <summary>
        /// webapi权限验证(jwt)
        /// </summary>
        public class ApiAuthorizeAttribute : AuthorizeAttribute
        {
            /// <summary>
            /// 指示指定的控件是否已获得授权
            /// </summary>
            /// <param name="actionContext"></param>
            /// <returns></returns>
            protected override bool IsAuthorized(HttpActionContext actionContext)
            {
                var authHeader = from t in actionContext.Request.Headers where t.Key == "auth" select t.Value.FirstOrDefault();
                if (authHeader != null)
                {
                    string token = authHeader.FirstOrDefault();
                    if (!string.IsNullOrEmpty(token))
                    {
                        try
                        {
                            //string secureKey = System.Configuration.ConfigurationManager.AppSettings["SecureKey"];
                            const string secret = "webapi";//随意设置,或者放入web.config中
                            //secret需要加密
                            IJsonSerializer serializer = new JsonNetSerializer();
                            IDateTimeProvider provider = new UtcDateTimeProvider();
                            IJwtValidator validator = new JwtValidator(serializer, provider);
                            IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
                            IJwtDecoder decoder = new JwtDecoder(serializer, validator, urlEncoder);
    
                            var json = decoder.DecodeToObject<AuthInfo>(token, secret, verify: true);
                            if (json != null)
                            {
                                //判断口令过期时间
                                if (json.ExpiryDateTime < DateTime.Now)
                                {
                                    return false;
                                }
                                //供controller调用:
                                //AuthInfo authInfo = this.RequestContext.RouteData.Values["auth"] as AuthInfo;
                                //authInfo.Roles
                                actionContext.RequestContext.RouteData.Values.Add("auth", json);
    
                                return true;
                            }
                            return false;
                        }
                        catch (Exception ex)
                        {
                            return false;
                        }
                    }
                }
                return false;
            }
            /// <summary>
            /// 处理授权失败的请求
            /// </summary>
            /// <param name="actionContext"></param>
            protected override void HandleUnauthorizedRequest(HttpActionContext actionContext)
            {
                //var erModel = new
                //{
                //    Success = "false",
                //    ErrorCode = "401"
                //};
                ResponseMessage res = new ResponseMessage(401, "无访问权限");
                actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.OK, res, "application/json");
            }
            
        }
    }

    4、登录api

    public LoginResult Login([FromBody]LoginRequest request)
            {
                LoginResult rs = new LoginResult();
                //这是是获取用户名和密码的,这里只是为了模拟
                if (request.UserName == "zhangsan" && request.Password == "123456")
                {
                    AuthInfo info = new AuthInfo
                    {
                        UserName = "zhangsan",
                        Roles = new List<string> { "Admin", "Manage" },
                        IsAdmin = true,
                        ExpiryDateTime = DateTime.Now.AddHours(2)
                    };
                    try
                    {
                        const string secret = "webapi";//口令加密秘钥
                        //secret需要加密
                        IJwtAlgorithm algorithm = new HMACSHA256Algorithm();//加密方式
                        IJsonSerializer serializer = new JsonNetSerializer();//序列化Json
                        IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();//base64加解密
                        IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);//JWT编码
                        var token = encoder.Encode(info, secret);//生成令牌
                        rs.Message = "成功";
                        rs.Token = token;
                        rs.Success = true;
                    }
                    catch (Exception ex)
                    {
                        rs.Message = ex.Message;
                        rs.Success = false;
                    }
                }
                else
                {
                    rs.Message = "用户信息为空";
                    rs.Success = false;
                }
                return rs;
            }

    5、获取数据api

         [HttpGet]
            [ApiAuthorize]
            public ResponseMessage GetData(int id)
            {
                //do
            }

    6、前端登录

    //login
                $("#btn_login").click(function () {
                    $.ajax({
                        url: '/api/Users/login',
                        type: "post",
                        data: { UserName: "zhangsan", Password: "123456"},
                        success: function (data) {
                            console.log(data)
                            if (data.Success) {
                                //演示,将token保存在全局变量中。
                                //实现项目中应该保存在cookie或者webStorage中
                                window.token = data.Token;
                                alert("登录成功");
                            } else {
                                alert("登录失败:" + data.Message);
                            }
                        },
                        error: function () {
                            alert("程序错误");
                        }
                    })
                    return false;
                })

    7、前端调用api获取数据

    //get
                $("#btn_get").click(function () {
                    $.ajax({
                        url: '/api/Users/getData/1',
                        type: "get",
                        headers: { "auth": window.token },//通过请求头来发送token
                        success: function (res) {
                            console.log(res)
                            if (res.code == 0) {
                                alert("操作成功");
                            } else {
                                alert("操作失败:"+res.msg);
                            }
                        },
                        error: function (res) {
                            alert("程序错误");
                        }
                    })
                    return false;
                })

    //over


    //成功一定有方法,失败一定有原因。
  • 相关阅读:
    Server Tomcat v8.0 Server at localhost was unable to start within 45 seconds. If the server requires more time, try increasing the timeout in the server editor.
    用户画像——“打标签”
    python replace函数替换无效问题
    python向mysql插入数据一直报TypeError: must be real number,not str
    《亿级用户下的新浪微博平台架构》读后感
    【2-10】标准 2 维表问题
    【2-8】集合划分问题(给定要分成几个集合)
    【2-7】集合划分问题
    【2-6】排列的字典序问题
    【2-5】有重复元素的排列问题
  • 原文地址:https://www.cnblogs.com/webapi/p/15471867.html
Copyright © 2011-2022 走看看