Files
IM_NEW/IM.Jwt/WebApplicationJwtExtension.cs
T

85 lines
3.8 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using IM.Commons;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using System.Text;
namespace IM.Jwt
{
public static class WebApplicationJwtExtension
{
public static IServiceCollection AddJwt(this IServiceCollection services, JwtOptions jwtOptions)
{
services.AddAuthentication(options =>
{
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = jwtOptions.Issuer,
ValidateAudience = true,
ValidAudience = jwtOptions.Audience,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero,
// 验证签名秘钥(防止 Token 被篡改)
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtOptions.Key)),
};
options.Events = new JwtBearerEvents
{
OnMessageReceived = context =>
{
var accessToken = context.Request.Query["access_token"];
var path = context.HttpContext.Request.Path;
// SignalR WebSocket 握手时 token 通过 query string 传递(不是 Authorization 头)
// Hub 路径为 /chat(见 ConnectorService/Program.cs
if (!string.IsNullOrEmpty(accessToken) && path.StartsWithSegments("/chat"))
{
context.Token = accessToken;
}
return Task.CompletedTask;
},
OnAuthenticationFailed = context =>
{
// 在这里打断点,查看 context.Exception
// 常见的有:SecurityTokenExpiredException (过期)
// 或 SecurityTokenInvalidSignatureException (密钥不对)
Console.WriteLine("验证失败原因: " + context.Exception.Message);
return Task.CompletedTask;
},
OnChallenge = async context =>
{
context.HandleResponse();
context.Response.ContentType = "application/json";
context.Response.StatusCode = StatusCodes.Status200OK;
var result = Result<object>.Fail(ResultCode.AUTH_FAILED);
await context.Response.WriteAsJsonAsync(result);
},
OnForbidden = async context =>
{
context.Response.ContentType = "application/json";
context.Response.StatusCode = StatusCodes.Status200OK;
var result = Result<object>.Fail(ResultCode.PERMISSION_DENIED);
await context.Response.WriteAsJsonAsync(result);
}
};
});
return services;
}
}
}