现在是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