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


    //成功一定有方法,失败一定有原因。
  • 相关阅读:
    常用排序算法及java语言实现
    机器学习实战笔记(python3实现)01--概述
    笔试错题--(字符串常量池和JVM运行时数据区)
    笔试错题(典型题)
    java进阶--java网络编程
    01_Java基础_第1天(Java概述、环境变量、注释、关键字、标识符、常量)
    数据库3(DBUtils)
    数据库2(JDBC、DBUtils)
    数据库1(数据库、表及表数据、SQL语句)
    Linux的基本命令
  • 原文地址:https://www.cnblogs.com/webapi/p/15471867.html
Copyright © 2011-2022 走看看