zoukankan      html  css  js  c++  java
  • WebApi使用JWT认证(一)

    这是第一部:先实现NetFramework上的WebApi使用JWT认证

    1、VS新建一个WebApi项目

    2、项目右键----管理Nuget程序包----找到JWT,然后安装

    3、Model文件夹下新建三个类LoginResult,LoginRequest,AuthInfo

    复制代码
     1 namespace JwtWebApi.Models
     2 {
     3     public class LoginResult
     4     {
     5         public bool Success { get; set; }
     6 
     7         public string Token { get; set; }
     8 
     9         public string Message { get; set; }
    10     }
    11 }
    复制代码
    复制代码
    1 namespace JwtWebApi.Models
    2 {
    3     public class LoginRequest
    4     {
    5         public string UserName { get; set; }
    6 
    7         public string Password { get; set; }
    8     }
    9 }
    复制代码
    复制代码
     1 using System.Collections.Generic;
     2 
     3 namespace JwtWebApi.Models
     4 {
     5     public class AuthInfo
     6     {
     7         //模拟JWT的payload
     8         public string UserName { get; set; }
     9 
    10         public List<string> Roles { get; set; }
    11 
    12         public bool IsAdmin { get; set; }
    13     }
    14 }
    复制代码

    4、在Controllers文件夹中的HomeController(没有就新建一个)中添加一个Post方法,这是生成JWT Token方法的地方,一般应放在登录的Action下

    复制代码
     1 using JWT;
     2 using JWT.Algorithms;
     3 using JWT.Serializers;
     4 using JwtWebApi.Models;
     5 using System;
     6 using System.Collections.Generic;
     7 using System.Web.Http;
     8 
     9 namespace JwtWebApi.Controllers
    10 {
    11     public class HomeController : ApiController
    12     {
    13         public LoginResult Post([FromBody]LoginRequest request)
    14         {
    15             LoginResult rs = new LoginResult();
    16             //这是是获取用户名和密码的,这里只是为了模拟
    17             if (request.UserName == "wangshibang" && request.Password == "123456")
    18             {
    19                 AuthInfo info = new AuthInfo { UserName = "wangshibang", Roles = new List<string> { "Admin", "Manage" }, IsAdmin = true };
    20                 try
    21                 {
    22                     const string secret = "To Live is to change the world";
    23                     //secret需要加密
    24                     IJwtAlgorithm algorithm = new HMACSHA256Algorithm();
    25                     IJsonSerializer serializer = new JsonNetSerializer();
    26                     IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
    27                     IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);
    28                     var token = encoder.Encode(info, secret);
    29                     rs.Message = "XXXXX";
    30                     rs.Token = token;
    31                     rs.Success = true;
    32                 }
    33                 catch (Exception ex)
    34                 {
    35                     rs.Message = ex.Message;
    36                     rs.Success = false;
    37                 }
    38             }
    39             else
    40             {
    41                 rs.Message = "fail";
    42                 rs.Success = false;
    43             }
    44             return rs;
    45         }
    46     }
    47 }
    复制代码

    5、项目下添加一个Attributes文件夹,需要写个权限拦截器,新建一个ApiAuthorizeAttribute类继承自AuthorizeAttribute类

    复制代码
     1 using JWT;
     2 using JWT.Serializers;
     3 using JwtWebApi.Models;
     4 using System;
     5 using System.Linq;
     6 using System.Web.Http;
     7 using System.Web.Http.Controllers;
     8 
     9 namespace JwtWebApi.Attributes
    10 {
    11     public class ApiAuthorizeAttribute : AuthorizeAttribute
    12     {
    13         protected override bool IsAuthorized(HttpActionContext actionContext)
    14         {
    15             var authHeader = from t in actionContext.Request.Headers where t.Key == "auth" select t.Value.FirstOrDefault();
    16             if (authHeader != null)
    17             {
    18                 string token = authHeader.FirstOrDefault();
    19                 if (!string.IsNullOrEmpty(token))
    20                 {
    21                     try
    22                     {
    23                         const string secret = "To Live is to change the world";
    24                         //secret需要加密
                    IJwtAlgorithm algorithm = new HMACSHA256Algorithm(); 25 IJsonSerializer serializer = new JsonNetSerializer(); 26 IDateTimeProvider provider = new UtcDateTimeProvider(); 27 IJwtValidator validator = new JwtValidator(serializer, provider); 28 IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder(); 29 IJwtDecoder decoder = new JwtDecoder(serializer, validator, urlEncoder,algorithm); 30 31 var json = decoder.DecodeToObject<AuthInfo>(token, secret, verify: true); 32 if (json != null) 33 { 34 actionContext.RequestContext.RouteData.Values.Add("auth", json); 35 return true; 36 } 37 return false; 38 } 39 catch (Exception ex) 40 { 41 return false; 42 } 43 } 44 } 45 return false; 46 } 47 } 48 }
    复制代码

    6、Controllers文件夹中新建一个UserController,新建一个Get的Action,需要加上ApiAuthorize特性

    复制代码
     1 using JwtWebApi.Attributes;
     2 using JwtWebApi.Models;
     3 using System.Web.Http;
     4 
     5 namespace JwtWebApi.Controllers
     6 {
     7     public class UserController : ApiController
     8     {
     9         // GET: User
    10         [ApiAuthorize]
    11         public string Get()
    12         {
    13             AuthInfo info = RequestContext.RouteData.Values["auth"] as AuthInfo;
    14             if (info == null)
    15             {
    16                 return "获取不到,失败";
    17             }
    18             else
    19             {
    20                 return $"获取到了,Auth的Name是 {info.UserName}";
    21             }
    22         }
    23     }
    24 }
    复制代码

    7、然后用PostMan测试

    下面是解决接口调用的跨域问题,有两种,一种是用CORS,另外一种就是修改WebConfig添加自定义options谓词处理模块

    我只用了自定义Options谓词处理

    复制代码
     1 <system.webServer>
     2     <handlers>
     3       <!--开启options谓词处理模块-->
     4       <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
     5       <!--<remove name="OPTIONSVerbHandler" />-->
     6       <remove name="TRACEVerbHandler" />
     7       <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
     8     </handlers>
     9     <httpProtocol>
    10       <customHeaders>
    11         <!--添加自定义options谓词处理模块-->
    12         <add name="Access-Control-Allow-Origin" value="http://localhost:8057"/>
    13         <add name="Access-Control-Allow-Headers" value="accept, auth"/>
    14         <add name="Access-Control-Allow-Methods" value="GET, OPTIONS"/>
    15       </customHeaders>
    16     </httpProtocol>
    17     <validation validateIntegratedModeConfiguration="false" />
    18     <modules>
    19       <remove name="ApplicationInsightsWebTracking" />
    20       <add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web" preCondition="managedHandler" />
    21     </modules>
    22   </system.webServer>
    复制代码

    好了,现在把你的WebApi部署到服务器上,然后用另一个跨域页面调取接口访问吧

    复制代码
     1 <!DOCTYPE html>
     2 <html>
     3 <head>
     4     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
     5     <title></title>
     6     <meta charset="utf-8" />
     7     <script src="jquery-3.3.1.min.js"></script>
     8 </head>
     9 <body>
    10     <fieldset>
    11         <legend>身份验证</legend>
    12         <form>
    13             <label for="UserName">用户名:</label><input type="text" name="userName" id="userName" value="admin" />
    14             <br />
    15             <br />
    16             <label for="Password">密码:</label><input type="password" name="password" id="password" value="123" />
    17             <br />
    18             <br />
    19         </form>
    20         <button id="login">登录</button>
    21     </fieldset>
    22     <br />
    23 
    24     <fieldset>
    25         <legend>调用接口</legend>
    26         <button id="invoke">调用接口</button>
    27     </fieldset>
    28     <script>
    29         $(function () {
    30             //调用api站点的登录接口,接口在登录成功后返回一个token。
    31             $("#login").on("click", function () {
    32                 $.ajax({
    33                     url: "http://localhost:8056/api/home",
    34                     data: $("form").serialize(),
    35                     method: "post",
    36                     success: function (data) {
    37                         if (data.Success) {
    38                             //为简单起见,将token保存在全局变量中。
    39                             window.token = data.Token;
    40                             alert("登录成功");
    41                         } else {
    42                             alert("登录失败:" + data.Message);
    43                         }
    44                     }
    45                 });
    46             });
    47 
    48             //调用api站点的获取数据的接口,该接口要求身份验证。
    49             $("#invoke").on("click", function () {
    50                 console.log(window.token);
    51                 $.ajax({
    52                     url: "http://localhost:8056/api/user",
    53                     method: "get",
    54                     headers: { "auth": window.token },//通过请求头来发送token,放弃了通过cookie的发送方式
    55                     complete: function (jqXHR,textStatus) {
    56                         alert(jqXHR.responseText);
    57                     },
    58                     
    59                 });
    60             });
    61         });
    62     </script>
    63 </body>
    64 </html>
    复制代码
  • 相关阅读:
    poj 2187 Beauty Contest(旋转卡壳)
    poj 2540 Hotter Colder(极角计算半平面交)
    poj 1279 Art Gallery(利用极角计算半平面交)
    poj 3384 Feng Shui(半平面交的联机算法)
    poj 1151 Atlantis(矩形面积并)
    zoj 1659 Mobile Phone Coverage(矩形面积并)
    uva 10213 How Many Pieces of Land (欧拉公式计算多面体)
    uva 190 Circle Through Three Points(三点求外心)
    zoj 1280 Intersecting Lines(两直线交点)
    poj 1041 John's trip(欧拉回路)
  • 原文地址:https://www.cnblogs.com/bruce1992/p/14033313.html
Copyright © 2011-2022 走看看