在现代的Web API开发中,JWT(JSON Web Tokens)是一种非常流行的认证方式。它允许客户端和服务端之间进行无状态的认证,这意味着每次请求都包含所有必要的信息,而不需要依赖于服务器端的会话状态。这种机制使得JWT非常适合分布式系统和微服务架构。
要实现JWT认证,首先需要在ASP.NET Core项目中配置JWT认证服务。这涉及到设置Issuer、Audience和Signing Key等参数,以确保只有合法的Token才能通过验证。
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = "Fiver.Security.Bearer",
ValidAudience = "Fiver.Security.Bearer",
IssuerSigningKey = JwtSecurityKey.Create("fiversecret")
};
});
services.AddMvc();
}
在上述代码中,首先添加了JWT认证服务,然后设置了Token验证参数。这些参数包括Issuer、Audience和Signing Key。Issuer和Audience用于标识Token的发行者和预期的接收者,而Signing Key用于验证Token的签名。
接下来,需要在项目的启动配置中启用认证中间件。
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseAuthentication();
app.UseMvcWithDefaultRoute();
}
在上述代码中,通过调用app.UseAuthentication();
启用了认证中间件。这将确保每个请求都会经过JWT认证。
为了生成JWT Token,需要创建一个Signing Key。这可以通过创建一个静态类来实现。
public static class JwtSecurityKey
{
public static SymmetricSecurityKey Create(string secret)
{
return new SymmetricSecurityKey(Encoding.ASCII.GetBytes(secret));
}
}
在上述代码中,定义了一个静态方法Create
,它接受一个密钥字符串,并返回一个SymmetricSecurityKey对象。这个对象将用于生成JWT Token。
接下来,需要创建一个API控制器,并使用[Authorize]属性来保护它。只有拥有有效JWT Token的用户才能访问这个控制器。
[Authorize]
[Route("movies")]
public class MoviesController : Controller
{
[HttpGet]
public IActionResult Get()
{
var dict = new Dictionary();
HttpContext.User.Claims.ToList().ForEach(item => dict.Add(item.Type, item.Value));
return Ok(dict);
}
}
在上述代码中,创建了一个名为MoviesController的API控制器,并使用[Authorize]属性来保护它。这意味着只有拥有有效JWT Token的用户才能访问这个控制器。
在客户端,需要使用Authorization header来发送JWT Token。这可以通过在HTTP请求中添加一个名为"Authorization"的header来实现,其值为"Bearer [token]",其中[token]是JWT Token的值。
在服务器端,需要配置JWT认证服务,以验证传入的Token。这涉及到设置Issuer、Audience和Signing Key等参数。在验证过程中,如果Token无效,可以在事件处理器中捕获这些错误。
options.Events = new JwtBearerEvents
{
OnAuthenticationFailed = context =>
{
Console.WriteLine("OnAuthenticationFailed: " + context.Exception.Message);
return Task.CompletedTask;
},
OnTokenValidated = context =>
{
Console.WriteLine("OnTokenValidated: " + context.SecurityToken);
return Task.CompletedTask;
}
};
在上述代码中,定义了两个事件处理器:OnAuthenticationFailed和OnTokenValidated。这些处理器会在认证失败和Token验证成功时被调用。
最后,需要创建一个Token生成器,以便在需要时生成JWT Token。这可以通过使用OAuth框架(如IdentityServer 4)或在应用程序中创建一个端点来实现。
public JwtToken Build()
{
EnsureArguments();
var claims = new List
{
new Claim(JwtRegisteredClaimNames.Sub, this.subject),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
}
.Union(this.claims.Select(item => new Claim(item.Key, item.Value)));
var token = new JwtSecurityToken(
issuer: this.issuer,
audience: this.audience,
claims: claims,
expires: DateTime.UtcNow.AddMinutes(expiryInMinutes),
signingCredentials: new SigningCredentials(this.securityKey, SecurityAlgorithms.HmacSha256));
return new JwtToken(token);
}
在上述代码中,定义了一个名为Build的方法,它接受Issuer、Audience、Claims和Signing Key等参数,并生成一个JWT Token。
在客户端,可以使用jQuery来获取Token并访问受保护的资源。这涉及到在HTTP请求中添加一个名为"Authorization"的header,其值为"Bearer [token]"。
$(function() {
$("#GetToken").click(function() {
$.ajax({
type: 'POST',
url: '@Url.Action("Create", "Token")',
data: JSON.stringify({
"Username": "james",
"Password": "bond"
}),
contentType: "application/json"
}).done(function(data, statusText, xhdr) {
$("#token").text(data);
}).fail(function(xhdr, statusText, errorText) {
$("#token").text(errorText);
});
});
$("#UseToken").click(function() {
$.ajax({
method: 'GET',
url: '@Url.Action("Get", "Movies")',
beforeSend: function(xhdr) {
xhdr.setRequestHeader("Authorization", "Bearer " + $("#token").text());
}
}).done(function(data, statusText, xhdr) {
$("#result").text(JSON.stringify(data));
}).fail(function(xhdr, statusText, errorText) {
$("#result").text(JSON.stringify(xhdr));
});
});
});