在ASP.NET Core中实现一个Token base的身份认证
以前在web端的身份認證都是基于Cookie | Session的身份認證, 在沒有更多的終端出現之前,這樣做也沒有什么問題,
但在Web API時代,你所需要面對的就不止是瀏覽器了,還有各種客戶端,這樣就有了一個問題,這些客戶端是不知道cookie是什么鬼的。 (cookie其實是瀏覽器搞出來的小貓膩,用來保持會話的,但HTTP本身是無狀態的, 各種客戶端能提供的無非也就是HTTP操作的API)
而基于Token的身份認證就是應對這種變化而生的,它更開放,安全性也更高。
基于Token的身份認證有很多種實現方式,但我們這里只使用微軟提供的API。
接下來的例子將帶領大家完成一個使用微軟JwtSecurityTokenHandler完成一個基于beare token的身份認證。
注意:這種文章屬于Step by step教程,跟著做才不至于看暈,下載完整代碼分析代碼結構才有意義。
前期準備
推薦使用VS2015 Update3作為你的IDE,下載地址:www.visualstudio.com
你需要安裝.NET Core的運行環境以及開發工具,這里提供VS版:www.microsoft.com/net/core
創建項目
在VS中新建項目,項目類型選擇ASP.NET Core Web Application(.NET Core), 輸入項目名稱為CSTokenBaseAuth
Coding
創建一些輔助類
在項目根目錄下創建一個文件夾Auth,并添加RSAKeyHelper.cs以及TokenAuthOption.cs兩個文件
在RSAKeyHelper.cs中
using System.Security.Cryptography;
namespace CSTokenBaseAuth.Auth
{
? ? public class RSAKeyHelper
? ? {
? ? ? ? public static RSAParameters GenerateKey()
? ? ? ? {
? ? ? ? ? ? using (var key = new RSACryptoServiceProvider(2048))
? ? ? ? ? ? {
? ? ? ? ? ? ? ? return key.ExportParameters(true);
? ? ? ? ? ? }
? ? ? ? }
? ? }
}
在TokenAuthOption.cs中
using System;
using Microsoft.IdentityModel.Tokens;
namespace CSTokenBaseAuth.Auth
{
? ? public class TokenAuthOption
? ? {
? ? ? ? public static string Audience { get; } = "ExampleAudience";
? ? ? ? public static string Issuer { get; } = "ExampleIssuer";
? ? ? ? public static RsaSecurityKey Key { get; } = new RsaSecurityKey(RSAKeyHelper.GenerateKey());
? ? ? ? public static SigningCredentials SigningCredentials { get; } = new SigningCredentials(Key, SecurityAlgorithms.RsaSha256Signature);
? ? ? ? public static TimeSpan ExpiresSpan { get; } = TimeSpan.FromMinutes(20);
? ? }
}
Startup.cs
在ConfigureServices中添加如下代碼:
- services.AddAuthorization(auth =>{auth.AddPolicy("Bearer", new AuthorizationPolicyBuilder().AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme?).RequireAuthenticatedUser().Build()); });
完整的代碼應該是這樣
- public void ConfigureServices(IServiceCollection services) { ? ?// Add framework services. ? ?services.AddApplicationInsightsTelemetry(Configuration); ? ?// Enable the use of an [Authorize("Bearer")] attribute on methods and classes to protect.services.AddAuthorization(auth =>{auth.AddPolicy("Bearer", new AuthorizationPolicyBuilder().AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme?).RequireAuthenticatedUser().Build());});services.AddMvc(); }
在Configure方法中添加如下代碼
這段代碼主要是Handle Error用的,比如當身份認證失敗的時候會拋出異常,而這里就是處理這個異常的。
接下來在相同的方法中添加如下代碼,
應用JwtBearerAuthentication
- app.UseJwtBearerAuthentication(new JwtBearerOptions {TokenValidationParameters = new TokenValidationParameters {IssuerSigningKey = TokenAuthOption.Key,ValidAudience = TokenAuthOption.Audience,ValidIssuer = TokenAuthOption.Issuer,ValidateIssuerSigningKey = true,ValidateLifetime = true,ClockSkew = TimeSpan.FromMinutes(0)} });
完整的代碼應該是這樣
在Controllers中新建一個Web API Controller Class,命名為TokenAuthController.cs。我們將在這里完成登錄授權
在同文件下添加兩個類,分別用來模擬用戶模型,以及用戶存儲,代碼應該是這樣
- public class User { ?
- ? public Guid ID { get; set; } ?
- ?public string Username { get; set; } ?
?public string Password { get; set; } }
public static class UserStorage { ? - ?public static List<User> Users { get; set; } = new List<User> { ? ? ? ?new User {ID=Guid.NewGuid(),Username="user1",Password = "user1psd" }, ? ? ? ?new User {ID=Guid.NewGuid(),Username="user2",Password = "user2psd" }, ? ? ? ?new User {ID=Guid.NewGuid(),Username="user3",Password = "user3psd" }}; }
接下來在TokenAuthController.cs中添加如下方法
- private string GenerateToken(User user, DateTime expires)
{ ?
- ? ?var handler = new JwtSecurityTokenHandler();ClaimsIdentity identity = new ClaimsIdentity( ? ? ? ?new GenericIdentity(user.Username, "TokenAuth"), ? ? ? ?new[] { ? ? ? ? ? ?new Claim("ID", user.ID.ToString())}); ? ?var securityToken = handler.CreateToken(new SecurityTokenDescriptor{Issuer = TokenAuthOption.Issuer,Audience = TokenAuthOption.Audience,SigningCredentials = TokenAuthOption.SigningCredentials,Subject = identity,Expires = expires}); ? ?return handler.WriteToken(securityToken); }
該方法僅僅只是生成一個Auth Token,接下來我們來添加另外一個方法來調用它
在相同文件中添加如下代碼
- [HttpPost]public string GetAuthToken(User user)
{ ? ?var existUser = UserStorage.Users.FirstOrDefault(u => u.Username == user.Username && u.Password == user.Password); ? ?if (existUser != null){ ? ? ? ?var requestAt = DateTime.Now; ? ? ?
- ?var expiresIn = requestAt + TokenAuthOption.ExpiresSpan; ? ? ?
- ?var token = GenerateToken(existUser, expiresIn); ? ? ? ?return JsonConvert.SerializeObject(new {stateCode = 1,requertAt = requestAt,expiresIn = TokenAuthOption.ExpiresSpan.TotalSeconds,accessToken = token});} ? ?else{ ? ? ? ?return JsonConvert.SerializeObject(new { stateCode = -1, errors = "Username or password is invalid" });} }
接下來我們來完成授權驗證部分
在Controllers中新建一個Web API Controller Class,命名為ValuesController.cs
在其中添加如下代碼
public string Get() { ?
- ?var claimsIdentity = User.Identity as ClaimsIdentity; ?
- var id = claimsIdentity.Claims.FirstOrDefault(c => c.Type == "ID").Value; ? ?return $"Hello! {HttpContext.User.Identity.Name}, your ID is:{id}"; }
為方法添加裝飾屬性
[HttpGet] [Authorize("Bearer")]完整的文件代碼應該是這樣
- using System.Linq; ?using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Authorization;
- using System.Security.Claims;
- namespace CSTokenBaseAuth.Controllers
- {[Route("api/[controller]")] ?
- ?public class ValuesController : Controller{[HttpGet][Authorize("Bearer")] ? ? ?
- ? ? ? ?public string Get(){ ? ? ? ?
- ? ? ??var claimsIdentity = User.Identity as ClaimsIdentity; ?
- ? ?var id = claimsIdentity.Claims.FirstOrDefault(c => c.Type == "ID").Value; ? ? ? ?
- ? ?? ?return $"Hello! {HttpContext.User.Identity.Name}, your ID is:{id}";}} }
最后讓我們來添加視圖
在Controllers中新建一個Web Controller Class,命名為LoginController.cs
其中的代碼應該是這樣
- using Microsoft.AspNetCore.Mvc; namespace CSTokenBaseAuth.Controllers
{[Route("[controller]/[action]")] ?
? ?public class LoginController : Controller{ ? - ?public IActionResult Index()
- ? ? ? ?{ ? ? ? ? ? ?return View();}} }
在項目Views目錄下新建一個名為Login的目錄,并在其中新建一個Index.cshtml文件。
代碼應該是這個樣子
- <html xmlns="http://www.w3.org/1999/xhtml"><head><title></title></head><body><button id="getToken">getToken</button><button id="requestAPI">requestAPI</button><script src="https://code.jquery.com/jquery-3.1.1.min.js"></script><script>$(function () { ? ? ? ? ? ?var accessToken = undefined;$("#getToken").click(function () {$.post( ? ? ? ? ? ? ? ? ? ?"/api/TokenAuth",{ Username: "user1", Password: "user1psd" }, ? ? ? ? ? ? ? ? ? ?function (data) {console.log(data); ? ? ? ? ? ? ? ? ? ? ? ?if (data.stateCode == 1){accessToken = data.accessToken;$.ajaxSetup({headers: { "Authorization": "Bearer " + accessToken }});}}, ? ? ? ? ? ? ? ? ? ?"json");})$("#requestAPI").click(function () {$.get("/api/Values", {}, function (data) {alert(data);}, "text");})}) ? ?</script></body></html>
最后:完整的代碼Sample以及運行手冊,請訪問:How to achieve a bearer token authentication and authorization in ASP.NET Core
原文地址:http://www.cnblogs.com/onecodeonescript/p/6061714.html
.NET社區新聞,深度好文,微信中搜索dotNET跨平臺或掃描二維碼關注
總結
以上是生活随笔為你收集整理的在ASP.NET Core中实现一个Token base的身份认证的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何用TypeScript开发微信小程序
- 下一篇: .NET Standard 2.0:整齐