asp.net core 3.1 自定义中间件实现jwt token认证

话不多讲,也不知道咋讲!直接上代码

认证信息承载对象【user】

/// <summary>
/// 认证用户信息
/// </summary>
public class DyUser
{
/// <summary>
/// 用户ID
/// </summary>
public int UserId { get; set; }
/// <summary>
/// 所属商户ID
/// </summary>
public int? TenantId { get; set; }
}

Jwt配置对象

public class AuthOptions
{
/// <summary>
/// Jwt认证Key
/// </summary>
public string Security { get; set; }
/// <summary>
/// 过期时间【天】
/// </summary>
public int Expiration { get; set; }
}

JWT管理接口

public interface IAuthManage
{
/// <summary>
/// 生成JwtToken
/// </summary>
/// <param name="user">用户信息</param>
/// <returns></returns>
string GenerateJwtToken(DyUser user);
}

JWT管理接口实现

暂时是使用微软提供类库生成,如果有想法可以自己生成

public class MicrosoftJwtAuthManage : IAuthManage
{
private readonly AuthOptions _authOptions;
public MicrosoftJwtAuth(AuthOptions authOptions)
{
_authOptions = authOptions;
} public string GenerateJwtToken(DyUser user)
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_authOptions.Security);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new Claim[]
{
new Claim("user",user.ToJson())
}),
Expires = DateTime.UtcNow.AddDays(_authOptions.Expiration),//一周过期
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
}
}

处理JWT中间件

这里借鉴国外大牛的代码,主要就是验证jwt并且存把解析出来的数据存放到当前上下文

public class JwtMiddleware
{
private readonly RequestDelegate _next;
private readonly AuthOptions _authOptions; public JwtMiddleware(RequestDelegate next, AuthOptions authOptions)
{
_next = next;
_authOptions = authOptions;
} public async Task Invoke(HttpContext context)
{
//获取上传token,可自定义扩展
var token = context.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last()
?? context.Request.Headers["X-Token"].FirstOrDefault()
?? context.Request.Query["Token"].FirstOrDefault()
?? context.Request.Cookies["Token"]; if (token != null)
AttachUserToContext(context, token); await _next(context);
} private void AttachUserToContext(HttpContext context, string token)
{
try
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_authOptions.Security);
tokenHandler.ValidateToken(token, new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false,
// set clockskew to zero so tokens expire exactly at token expiration time (instead of 5 minutes later)
ClockSkew = TimeSpan.Zero
}, out SecurityToken validatedToken); var jwtToken = (JwtSecurityToken)validatedToken;
var user = jwtToken.Claims.First(x => x.Type == "user").Value.ToJsonEntity<DyUser>(); //写入认证信息,方便业务类使用
var claimsIdentity = new ClaimsIdentity(new Claim[] { new Claim("user", jwtToken.Claims.First(x => x.Type == "user").Value) });
Thread.CurrentPrincipal = new ClaimsPrincipal(claimsIdentity); // attach user to context on successful jwt validation
context.Items["User"] = user;
}
catch
{
// do nothing if jwt validation fails
// user is not attached to context so request won't have access to secure routes
throw;
}
}
}

权限过滤器

这个根据刚才中间件的存放的信息判断是否授权成功,支持匿名特性

public class ApiAuthorizeAttribute : Attribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationFilterContext context)
{
var user = context.HttpContext.Items["User"];
//验证是否需要授权和授权信息
if (HasAllowAnonymous(context) == false && user == null)
{
// not logged in
context.Result = new JsonResult(new {message = "Unauthorized"})
{StatusCode = StatusCodes.Status401Unauthorized};
}
} private static bool HasAllowAnonymous(AuthorizationFilterContext context)
{
var filters = context.Filters;
if (filters.OfType<IAllowAnonymousFilter>().Any())
{
return true;
} // When doing endpoint routing, MVC does not add AllowAnonymousFilters for AllowAnonymousAttributes that
// were discovered on controllers and actions. To maintain compat with 2.x,
// we'll check for the presence of IAllowAnonymous in endpoint metadata.
var endpoint = context.HttpContext.GetEndpoint();
return endpoint?.Metadata?.GetMetadata<IAllowAnonymous>() != null;
}
}

扩展IServiceCollection

方便以后管理和维护,主要就是把需要的对象注入到IOC容器里面

public static class AuthServiceExtensions
{
public static void AddAuth(this IServiceCollection services, Action<AuthOptions> configAction)
{
var options = new AuthOptions();
configAction(options);
services.AddSingleton(options);
services.AddSingleton<IAuthManage>(new MicrosoftJwtAuthManage(options));
}
}

NullDySession

这里是为了在非控制器类获取用户信息用

/// <summary>
/// 当前会话对象
/// </summary>
public class NullDySession
{
/// <summary>
/// 获取DySession实例
/// </summary>
public static NullDySession Instance { get; } = new NullDySession();
/// <summary>
/// 获取当前用户信息
/// </summary>
public DyUser DyUser
{
get
{
var claimsPrincipal = Thread.CurrentPrincipal as ClaimsPrincipal; var claimsIdentity = claimsPrincipal?.Identity as ClaimsIdentity; var userClaim = claimsIdentity?.Claims.FirstOrDefault(c => c.Type == "user");
if (userClaim == null || string.IsNullOrEmpty(userClaim.Value))
{
return null;
} return userClaim.Value.ToJsonEntity<DyUser>();
}
} private NullDySession()
{
}
}

到这为止准备工作完成,开始用起来吧~

修改【Startup.cs->ConfigureServices】

//添加全局权限认证过滤器
services.AddControllersWithViews(options =>
{
options.Filters.Add<ApiAuthorizeAttribute>();
})
//添加认证配置信息
services.AddAuth(options =>
{
options.Expiration = 7;//天为单位
options.Security = apolloConfig.Get("JwtSecret");
});

添加中间件【Startup.cs->Configure(IApplicationBuilder app, IWebHostEnvironment env)方法中】

注意中间件的位置

//启用jwt认证中间件
app.UseMiddleware<JwtMiddleware>();

api使用案例【使用构造注入IAuthManage】

//生成了JwtToken
var newToken = _authManage.CreateJwtToken(para.Sn); //Controller里面获取用户信息
public DyUser DyUser => (DyUser)this.HttpContext.Items["User"]; //普通class类获取用户信息【如果不是Web应用,需要独立引用Dymg.Core】
NullDySession.Instance.DyUser.UserId; //如果个别不接口不需要认证,可以使用AllowAnonymous特性
[HttpPost, AllowAnonymous]
public string Noauth()
{
return "这个不需要授权";
}

前端调用案例

//token放在请求头里面
Authorization:Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoie1wiVXNlcklkXCI6MTIzNDU2ODcsXCJUZW5hbnRJZFwiOjY1NDMyMSxcIlN0YXRpb25JZFwiOm51bGwsXCJTbWFydEJveFNuXCI6bnVsbH0iLCJuYmYiOjE1OTU5MDAxMzYsImV4cCI6MTU5NjUwNDkzNiwiaWF0IjoxNTk1OTAwMTM2fQ.lkEunspinGeQK9sFoQs2WLpNticqOR4xv_18CQdOE_Y
//自定义key
x-token:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoie1wiVXNlcklkXCI6MTIzNDU2ODcsXCJUZW5hbnRJZFwiOjY1NDMyMSxcIlN0YXRpb25JZFwiOm51bGwsXCJTbWFydEJveFNuXCI6bnVsbH0iLCJuYmYiOjE1OTU5MDAxMzYsImV4cCI6MTU5NjUwNDkzNiwiaWF0IjoxNTk1OTAwMTM2fQ.lkEunspinGeQK9sFoQs2WLpNticqOR4xv_18CQdOE_Y //使用连接字符串方式
https://xxxxx/user/getUser?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoie1wiVXNlcklkXCI6MTIzNDU2ODcsXCJUZW5hbnRJZFwiOjY1NDMyMSxcIlN0YXRpb25JZFwiOm51bGwsXCJTbWFydEJveFNuXCI6bnVsbH0iLCJuYmYiOjE1OTU5MDAxMzYsImV4cCI6MTU5NjUwNDkzNiwiaWF0IjoxNTk1OTAwMTM2fQ.lkEunspinGeQK9sFoQs2WLpNticqOR4xv_18CQdOE_Y

asp.net core 3.1 自定义中间件实现jwt token认证的更多相关文章

  1. Asp.Net Core入门之自定义中间件

    什么是中间件? 这里引用官方解释: 中间件是用于组成应用程序管道来处理请求和响应的组件.管道内的每一个组件都可以选择是否将请求交给下一个组件.并在管道中调用下一个组件之前和之后执行某些操作.请求委托被 ...

  2. asp.net core中写入自定义中间件

    首先要明确什么是中间件?微软官方解释:https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/middleware/?tabs=aspnet ...

  3. WebAPI调用笔记 ASP.NET CORE 学习之自定义异常处理 MySQL数据库查询优化建议 .NET操作XML文件之泛型集合的序列化与反序列化 Asp.Net Core 轻松学-多线程之Task快速上手 Asp.Net Core 轻松学-多线程之Task(补充)

    WebAPI调用笔记   前言 即时通信项目中初次调用OA接口遇到了一些问题,因为本人从业后几乎一直做CS端项目,一个简单的WebAPI调用居然浪费了不少时间,特此记录. 接口描述 首先说明一下,基于 ...

  4. asp.net core mvc 管道之中间件

    asp.net core mvc 管道之中间件 http请求处理管道通过注册中间件来实现各种功能,松耦合并且很灵活 此文简单介绍asp.net core mvc中间件的注册以及运行过程 通过理解中间件 ...

  5. ASP.NET Core中显示自定义错误页面-增强版

    之前的博文 ASP.NET Core中显示自定义错误页面 中的方法是在项目中硬编码实现的,当有多个项目时,就会造成不同项目之间的重复代码,不可取. 在这篇博文中改用middleware实现,并且放在独 ...

  6. 在ASP.NET Core 中使用Cookie中间件

    在ASP.NET Core 中使用Cookie中间件 ASP.NET Core 提供了Cookie中间件来序列化用户主题到一个加密的Cookie中并且在后来的请求中校验这个Cookie,再现用户并且分 ...

  7. asp.net core 2.0 web api基于JWT自定义策略授权

    JWT(json web token)是一种基于json的身份验证机制,流程如下: 通过登录,来获取Token,再在之后每次请求的Header中追加Authorization为Token的凭据,服务端 ...

  8. 在ASP.NET Core 中使用Cookie中间件 (.net core 1.x适用)

    在ASP.NET Core 中使用Cookie中间件 ASP.NET Core 提供了Cookie中间件来序列化用户主题到一个加密的Cookie中并且在后来的请求中校验这个Cookie,再现用户并且分 ...

  9. asp.net core 实现支持自定义 Content-Type

    asp.net core 实现支持自定义 Content-Type Intro 我们最近有一个原本是内网的服务要上公网,在公网上有一层 Cloudflare 作为网站的公网流量提供者,CloudFla ...

随机推荐

  1. 创建虚拟机和安装centos7 & install oracle

    win7 x64位+VMware12+centos7 x64位+oracle 11g R2安装详解(一) 一.虚拟机安装oracle11g R2的安装环境: 1.win7 x64位          ...

  2. 复杂链表的复制(剑指offer-25)

    题目描述 输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针random指向一个随机节点),请对此链表进行深拷贝,并返回拷贝后的头结点.(注意,输出结果中请不要返回 ...

  3. alert(1) to win Part Ⅰ

    alert(1) to win Adobe: function escape(s) { s = s.replace(/"/g, '\\"'); return '<script ...

  4. MCU 51-1概述

    Microcontroller Unit 单片机:将微处理器CPU.存储器(RAM.ROM) .基本输入/输出(I/O) 接口电路和总线接口等组装在一块主机板(即微机主板). 微型计算机:将微处理器C ...

  5. Scala 面向对象(六):面向对象的特征二:继承 (一)

    1 Scala继承的基本语法 class 子类名 extends 父类名 { 类体 } class Person { var name : String = _ var age : Int = _ d ...

  6. Maven 专题(九):后记

    尚硅谷视频链接:https://www.bilibili.com/video/av84877781/看视频的时候,根据自己的需要,访问量多的不一定是好的,适合自己的才是最好的,总的来说,尚硅谷的视频质 ...

  7. flask 源码专题(一):app.run()的背后

    当我们用Flask写好一个app后, 运行app.run()表示监听指定的端口, 对收到的request运行app生成response并返回. 现在分析一下, 运行app.run()后具体发生了什么事 ...

  8. Django之 url组件

    本节内容 路由系统 models模型 admin views视图 template模板 路由系统 我们已知,用户从浏览器发出的请求会首先打到django url的路由分发系统这里,然后再到views视 ...

  9. 从JDK源码理解java引用

    目录 java中的引用 引用队列 虚引用.弱引用.软引用的实现 ReferenceHandler线程 引用队列的实现 总结 参考资料 java中的引用 JDK 1.2之后,把对象的引用分为了四种类型, ...

  10. Cyber Security - Palo Alto Security Policies(2)

    Task 3 The SOC(Security Operation Center) monitoring team dashboard reported more 1,000 requests to ...