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. POJ3040贪心

    题意:作为创纪录的牛奶生产的奖励,农场主约翰决定开始给Bessie奶牛一个小的每周津贴.FJ有一套硬币N种(1≤N≤20)不同的面额,每枚硬币是所有比他小的硬币面值的倍数,例如1美分硬币.5美分硬币. ...

  2. CVE-2020-5902 F5 BIG-IP 远程代码执行RCE

    cve-2020-5902 : RCE:curl -v -k 'https://[F5 Host]/tmui/login.jsp/..;/tmui/locallb/workspace/tmshCmd. ...

  3. 我终于弄懂了Python的装饰器(一)

    此系列文档: 1. 我终于弄懂了Python的装饰器(一) 2. 我终于弄懂了Python的装饰器(二) 3. 我终于弄懂了Python的装饰器(三) 4. 我终于弄懂了Python的装饰器(四) 一 ...

  4. 包含min函数的栈(剑指offer-20)

    题目描述 定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1)). 注意:保证测试中不会当栈为空的时候,对栈调用pop()或者min()或者top()方法 ...

  5. TB6560电机驱动器参数设置

    TB6560电机驱动器参数设置 最近接触了一些步进电机的开发,整理了一些参数设置的经验,希望能帮助到有需要的人儿~ 步进电机主要按一定的给电规律,给对应的绕组响应的电信号,电机将按一定的方向运行,而且 ...

  6. python 爬虫由于网络或代理不能用导致的问题处理方法

    平时在爬取某些网页的时候,可能是由于网络不好或者代理池中的代理不能用导致请求失败.此时有们需要重复多次去请求,python中有现成的,相应的包供我们使用: 我们可以利用retry模块进行多次请求,如果 ...

  7. java 数据结构(七):Collection接口

    1.单列集合框架结构|----Collection接口:单列集合,用来存储一个一个的对象* |----List接口:存储序的.可重复的数据. -->“动态”数组* |----ArrayList. ...

  8. javascript基础(六): 获取节点实例 jquery获取当前节点的前一个节点

    jquery获取当前节点的前一个节点步骤如下: 1.打开html开发工具,新建一来个html代码页面. 2.在html页面创建三个p标签,然后给这三个p标签设置不同的2113内容. 3.引入jquer ...

  9. 机器学习实战基础(十二):sklearn中的数据预处理和特征工程(五) 数据预处理 Preprocessing & Impute 之 处理分类特征:处理连续性特征 二值化与分段

    处理连续性特征 二值化与分段 sklearn.preprocessing.Binarizer根据阈值将数据二值化(将特征值设置为0或1),用于处理连续型变量.大于阈值的值映射为1,而小于或等于阈值的值 ...

  10. 循序渐进VUE+Element 前端应用开发(17)--- 菜单资源管理

    在权限管理系统中,菜单也属于权限控制的一个资源,应该直接应用于角色,和权限功能点一样,属于角色控制的一环.不同角色用户,登录系统后,出现的系统菜单是不同的.在VUE+Element 前端中,我们菜单结 ...