這是第一部:先實現NetFramework上的WebApi使用JWT認證html
一、VS新建一個WebApi項目jquery
二、項目右鍵----管理Nuget程序包----找到JWT,而後安裝web
三、Model文件夾下新建三個類LoginResult,LoginRequest,AuthInfoajax
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 }
四、在Controllers文件夾中的HomeController(沒有就新建一個)中添加一個Post方法,這是生成JWT Token方法的地方,通常應放在登陸的Action下json
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 }
五、項目下添加一個Attributes文件夾,須要寫個權限攔截器,新建一個ApiAuthorizeAttribute類繼承自AuthorizeAttribute類api
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須要加密 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); 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 }
六、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 }
七、而後用PostMan測試服務器
下面是解決接口調用的跨域問題,有兩種,一種是用CORS,另一種就是修改WebConfig添加自定義options謂詞處理模塊cookie
我只用了自定義Options謂詞處理less
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>
本文參考連接:https://www.cnblogs.com/lwhkdash/p/6686999.html