using ERP.Framework.Cache;
using ERP.Framework.Config;
using ERP.Framework.Constants;
using ERP.Framework.Security;
using ERP.Framework.Utils;
using ERP.Framework.WebApi;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using System.IdentityModel.Tokens.Jwt;
using System.Net;
using System.Security.Claims;
namespace ERP.Framework.Middleware
{
///
/// 验证 (解签 header附带用户id) useJwt
///
public class AuthenticationMiddleware : IMiddleware
{
private readonly IConfiguration _configuration;
public AuthenticationMiddleware(IConfiguration configuration)
{
this._configuration = configuration;
}
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
var path = context.Request.Path.ToString();
var securityConfig = _configuration.GetSection(FrameworkConstant.SECURITY_CONFIG).Get() ?? new SecurityConfig();
{
if (securityConfig.WhiteList != null && securityConfig.WhiteList.Any(w => UrlUtil.Match(w, path)))
await next(context);
return;
}
var token = context.Request.Headers[AuthConstant.HEADER].ToString().Replace(FrameworkConstant.TOKEN_PREFIX, "").TrimStart();
var isValid = TokenHelper.ValidateToken(token, securityConfig.JwtSecurityKey);
if (!isValid)
{
// 返回401状态码和自定义错误信息
context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
context.Response.ContentType = "application/json";
var errorJson = JsonConvert.SerializeObject(new Result()
{
Code = 1000001,
//Message = AuthI18N.TokenValidate
});
await context.Response.WriteAsync(errorJson);
return;
}
var claims = TokenHelper.GetClaims(token);
var tokenId = claims.FirstOrDefault(t => t.Type == JwtRegisteredClaimNames.UniqueName)!.Value;
var userId = claims.FirstOrDefault(t => t.Type == JwtRegisteredClaimNames.NameId)!.Value;
//var userName = claims.FirstOrDefault(t => t.Type == ClaimTypes.Name)!.Value;
var checkLastActivityResult = CheckLastActivity(tokenId, securityConfig.ActivityTimeOut);
if (checkLastActivityResult != null)
{
context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
context.Response.ContentType = "application/json";
await context.Response.WriteAsync(JsonConvert.SerializeObject(checkLastActivityResult));
return;
}
context.Items["TokenId"] = tokenId;
context.Items["UserID"] = userId;
await next(context);
return;
}
private static Result CheckLastActivity(string tokenId, int activityTimeOut)
{
DateTime date;
var result = new Result();
var key = AuthConstant.LAST_ACTIVITY + tokenId;
var lastActivity = RedisHelper.GetWithExpire(key);
var value = lastActivity.Value.ToString();
var expireTime = lastActivity.Expiry;
if (value.IsNullOrEmpty())
{
result.Code = 1000001;
//result.Message = AuthI18N.TokenValidate;
return result;
}
if (value == "-1")
{
result.Code = 1000002;
//result.Message = AuthI18N.KickedOut;
return result;
}
if (value == "-2")
{
result.Code = 1000003;
//result.Message = AuthI18N.ConcurrentLogin;
return result;
}
if (DateTime.TryParse(value, out date))
{
var isOnline = DateTime.Now <= date;
if (isOnline)
{
SetLastActivityCache(tokenId, activityTimeOut, expireTime);
}
else
{
result.Code = 1000004;
//result.Message = AuthI18N.IdleTimeOut;
return result;
}
}
return null;
}
///
/// 刷新last Activity
///
///
///
private static void SetLastActivityCache(
string tokenId
, int activityTimeOut
, TimeSpan? expireTime)
{
var key = AuthConstant.LAST_ACTIVITY + tokenId;
var val = DateTime.Now.AddMinutes(activityTimeOut).ToDateLongString();
RedisHelper.SaveExpire(key, val, expireTime);
}
}
public static class AuthenticationMiddlewareExtensions
{
public static IApplicationBuilder UseAuthenticationMiddleware(this IApplicationBuilder builder)
{
return builder.UseMiddleware();
}
}
}