You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

83 lines
2.7 KiB
C#

using System;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using Haoliang.Core.Services;
using Haoliang.Models.Common;
namespace Haoliang.Api.Middleware
{
public class JwtMiddleware
{
private readonly RequestDelegate _next;
private readonly IAuthService _authService;
private readonly JwtSettings _jwtSettings;
public JwtMiddleware(RequestDelegate next, IAuthService authService, IOptions<JwtSettings> jwtSettings)
{
_next = next;
_authService = authService;
_jwtSettings = jwtSettings.Value;
}
public async Task Invoke(HttpContext context)
{
var token = context.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last();
if (token != null)
await AttachUserToContext(context, token);
await _next(context);
}
private async Task AttachUserToContext(HttpContext context, string token)
{
try
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_jwtSettings.Secret);
tokenHandler.ValidateToken(token, new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false,
ClockSkew = TimeSpan.Zero
}, out SecurityToken validatedToken);
var jwtToken = (JwtSecurityToken)validatedToken;
var userId = int.Parse(jwtToken.Claims.First(x => x.Type == "id").Value);
// Attach user to context on successful jwt validation
context.Items["User"] = await _authService.GetUserByIdAsync(userId);
}
catch (Exception ex)
{
// Token is not valid
// Log the error but don't throw, allow the request to continue
// The authorization filter will handle the authentication failure
}
}
}
public class JwtSettings
{
public string Secret { get; set; }
public string Issuer { get; set; }
public string Audience { get; set; }
public int ExpirationMinutes { get; set; } = 60;
}
public static class JwtMiddlewareExtensions
{
public static IApplicationBuilder UseJwtMiddleware(this IApplicationBuilder builder)
{
return builder.UseMiddleware<JwtMiddleware>();
}
}
}