現在是WebAPI的時代,你所需要面對的不止是瀏覽器了,通常會使用Web, WebApp, NativeApp等多種呈現方式。其中諸如Ember,Angular,Backbone之類的前端框架類庫正隨着更加精細的Web應用而日益壯大。服務器端的組件也正在從傳統的任務中解脫轉而變的更像API。API使得傳統的前端和后端的概念解耦。開發者可以脫離前端,獨立的開發后端,在測試上獲得更大的便利。這種途徑也使得一個移動應用和網頁應用可以使用相同的后端。當使用一個API時,認證(authentication)成了一個大問題。以前在Web端的身份認證都是基於Cookie或Session的身份認證,在沒有更多的終端出現之前,這樣做也沒有什么問題。但是多客戶端環境下,有些客戶端並不存在Cookie。另外后端也由以前的Razor渲染HTML,轉變為Stateless的RESTFulAPI,因此,我們需要一種標准的,通用的,無狀態的,與語言無關的認證方式,這就是令牌認證(Token Authentication),極少的服務端數據管理、可擴展性、可以使用單獨的認證服務器和應用服務器分離。令牌認證已經成為單頁應用(SPA)和移動應用事實上的標准。即使是傳統的B/S應用也能利用其優點。
(1)生成token
public virtual AccessToken Authenticate(Guid id, DateTime expiresTime, string audience, string issuer, string securityKey)
{
var key = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(securityKey));
var tokenHandler = new JwtSecurityTokenHandler();
var identity = new ClaimsIdentity(new[] { new Claim("Id", id.ToString()) });
var tokenDescriptor = new SecurityTokenDescriptor
{
Audience = audience,
Issuer = issuer,
Subject = identity,
Expires = expiresTime,
SigningCredentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
var tokenString = tokenHandler.WriteToken(token);
return new JwtBearerToken() { Token = tokenString, Scheme = JwtBearerDefaults.AuthenticationScheme };
}
(2)配置token驗證
services.AddAuthentication(x =>
{
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(o =>
{
o.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
RequireExpirationTime = true,
ClockSkew = TimeSpan.FromSeconds(0),
ValidAudiences = AppConfig.Audiences,
ValidIssuers = AppConfig.Issuers,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(AppConfig.SecurityKey))
};
});
(3)啟用認證
[Authorize]
public class TestController : ControllerBase