ASP.NET Core - 基于IHttpContextAccessor实现系统级别身份标识

问题引入:

  我们知道当请求通过认证模块时,会给当前的HttpContext赋予当前用户身份标识,我们在需要授权的控制器中打上[Authorize]授权标签,就可以在ControllerBase的User属性获取到基于声明的权限标识(ClaimsPrincipal)。遗憾的是这只是针对Controller层面,很多场景下我们是需要在Service层乃至数据层获直接使用用户信息,这种情况我们就使用不了User了。  


解决方案:

  在Asp.net 4.x时代,我们通常的做法是通过HttpContext.Current获取当前请求的上下文进而获取到当前的User属性,所以问题的切入点在于我们如何获取当前的HttpContext上下文,Aspnet Core是通过注入HttpContext的访问器对象IHttpContextAccessor来获取当前的HttpContext。

  首先我们需要在Startup的ConfigureServices方法中注册IHttpContextAccessor的实例

   有了这个注册,我们封装一个方法从IHttpContextAccessor 的HttpContext中获取对应的ClaimsPrincipal,如下(这里面的原理在后面的认证授权文章将会讲解到,大概的原理是认证通过后,User是具有当前用户的身份标志的ClaimsPrincipal):

640?wx_fmt=png

   在Startup的ConfigureServices方法中,我们一样把这个类也加入注册中

public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddSingleton<IPrincipalAccessor, PrincipalAccessor>();
....
}

   有了以上这些基础架构提供的东西,剩下的是我们该需要如何从ClaimsPrincipal获取到对应的Claims了,在这里我们定义一个ClaimsAccessor类负责从PrincipalAccessor把用户的身份标志信息提取出来,比如用户的角色,Id等业务数据,这些是需要在获取Token时系统所提供过的信息。

 

640?wx_fmt=png

640?wx_fmt=png

   同样我们在Startup的ConfigureServices方法中把IClaimsAccessor注册进来

public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddSingleton<IPrincipalAccessor, PrincipalAccessor>();
services.AddSingleton<IClaimsAccessor, ClaimsAccessor>();
....
}

  这样我们所涉及到的需获取身份标志的基础类都已经定义好,来看看我们该如何使用这些基础类。

  使用

  在有了以上的这些类,我们需要的是在业务中通过依赖注入方式来解析出我们所需的对象,来好的让我们看看该如何具体使用  

640?wx_fmt=png


  当我们的IClaimsAccessor解析出来时,我们就获取到所有的Claims信息,可以基于这些信息提取访问用户的身份标志,这样我们就不仅仅局限于在Controller层面才能获取用户的身份标志了,至此我们的系统级别的标识已经完成,记得在项目的启动项中利用ASP.NET Core的容器把服务注册进来,在需通的地方解析出来即可使用。

  改进

  这时能满足我们的业务吗?能!但是对于我们稍微要求高点的程序员,我们就可以发现,如果每个服务都按照上面的写法的话,明显在实际应用中需要写很多重复的代码,每次都需要手动进行构造注入会比较繁琐,好吧,我们可以利用面向对象的特点,创建基类进行继承进行优雅且可复用的简化和改进

  首先我们先定义一个ServiceProviderInstance类

  public class ServiceProviderInstance
{
public static IServiceProvider Instance { get; set; }
} 

  这个类的作用是保存IServiceProvider的一个实例,为什么需要这样呢?这里的一个设计思想是,我们如何能顺利解析出我们所需的IClaimsAccessor对象进而得到我们所需的信息?在ASP.NET Core的容器中,系统提供了IServiceCollection来注册服务和提供了IServiceProvider这个让我们解析各种注册过的服务(具体可参考ASP.NET Core - 依赖注入文章所讲解的依赖注入),这时我们的目标就是需要获取到当前应用的IServiceProvider实例,所以这个ServiceProviderInstance类的作用时为了获取IServiceProvider所设计出来的静态类。

  如何获取到应用的IServiceProvider实例?

  在应用初始化过程中,WebHostBuilder会利用ServiceCollection来创建新的ServiceProvider来供系统使用,所以我们在Startup类的Configure方法中,通过ApplicationBuilder的ApplicationServices属性就能获取到系统的ServiceProvider实例,在此我们利用ServiceProviderInstance的Instance属性保存当前的IServiceProvider以供系统后面使用  

  public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
...
ServiceProviderInstance.Instance = app.ApplicationServices;
}

  在获取到了系统的IServiceProvider实例后,剩下的就是利用这个实例把我们前面注册的基础服务IClaimsAccessor解析出来了

640?wx_fmt=png


   好的让我们看看改进后在一个实际环境中该如何使用

 

640?wx_fmt=png

  让所有每个子类都继承了ServiceBase,这样在所有的业务层都可以直接获取到用户的身份信息而不用写太多的重复代码。

  总结

  1. 利用ASP.NET Core提供的IHttpContextAccessor来获取HttpContext的User属性

  2. 封装一系列的基础类和利用依赖注入来解析出所有的Claims

  3. 为了避免过多的侵入式代码,优雅且可复用的创建ServiceBase给所有的业务类使用

  让我知道如果你有更好的想法或建议!

原文地址:https://www.cnblogs.com/lex-wu/p/10528109.html

.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com 
640?wx_fmt=jpeg

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/315672.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

怎样学习和阅读技术书籍?

技术的更新换代非常的迅速&#xff0c;作为一个技术人&#xff0c;需要持续不断地学习才能不被淘汰。但是学习没有速成的方法&#xff0c;只可能有一些技巧让我们事半功倍&#xff0c;本文是我对学习和读书的一点思考。学习是一件「逆人性」的事&#xff0c;如果让你选择是学习…

CF653F. Paper task

CF653F. Paper task 简要题面 给定括号序列SSS&#xff0c;求其中本质不同合法括号序列个数。(∣S∣≤5∗105|S|\leq 5*10^5∣S∣≤5∗105) Solution 感觉用了一个很麻烦的方法。 我们可以考虑枚举本质不同串的右端点&#xff0c;每次动态地在SAMSAMSAM里面加入末尾元素&am…

52ABP和ABP的关系

52ABP和ABP的关系本文作者&#xff1a;52ABP开发团队 文章会随着版本进行更新&#xff0c;关注我们获取最新版本 本文出处&#xff1a;https://www.52abp.com/wiki/common/latest 源代码&#xff1a; https://www.github.com/52abp 52ABP和ABP的关系ASP.NET Boilerplate是一个开…

CF1167F. Scalar Queries

CF1167F. Scalar Queries Solution 拆贡献&#xff0c;自身的贡献为bi∗(i−1)∗(n−i)b_i*(i-1)*(n-i)bi​∗(i−1)∗(n−i)&#xff0c;每一个左边比他小的数bjb_jbj​会产生bi∗j∗(n−i)b_i*j*(n-i)bi​∗j∗(n−i)的贡献&#xff0c;需要维护∑j\sum_{j}∑j​&#xff0…

【译】C#9的候选功能

通往C# 9 的漫长道路已经开始了&#xff0c;这是世界上第一篇关于C# 9候选功能的文章。阅读完本文后&#xff0c;你将希望为将来遇到新的C#挑战做好充分准备。 这篇文章基于&#xff1a;C#语言版本计划 9.0 候选功能基于记录和模式匹配的表达式我一直在长时间等待这个功能。记录…

CF641D. Little Artem and Random Variable

CF641D. Little Artem and Random Variable Solution 设给定的两个序列为mx1..n,mn1..nmx_{1..n},mn_{1..n}mx1..n​,mn1..n​。 令第一个骰子投到1..n1..n1..n的概率为p1..np_{1..n}p1..n​ 令第二个骰子投到1..n1..n1..n的概率为q1..nq_{1..n}q1..n​ 显然有 mxi(∑j≤ipj)…

AKS开讲啦! | DevOps with AKS

上周小Phippy搬到了Kube船长船上的Pods里&#xff0c;感觉好极了&#xff0c;那今天我们继续看看Phippy的兴趣爱好哦。探索Kube船上的世界上篇&#xff08;点击回顾&#xff09;小Phippy 搬到了船上的Pods里&#xff0c;感受到了回家般的舒适感&#xff0c;小Phippy希望能发挥一…

CF1157G. Inverse of Rows and Columns

CF1157G. Inverse of Rows and Columns Solution 首先枚举第一行是否变换&#xff0c;再枚举第一行的010101状态&#xff0c;即可确定列变换。 然后对于之后的行变换&#xff0c;从前往后贪心地让111出现得尽可能晚即可。 Code #include <vector> #include <list&…

把文件隐藏在图片中

一、前言有的时候我们需要把文件给隐藏起来&#xff0c;但是Windows自带的隐藏方式还是很容易被发现的。这时候我们可以选择把文件放在网盘&#xff0c;但这毕竟需要网络。不过&#xff0c;我们可以通过Windows自带的功能&#xff0c;把文件隐藏在图片中。是不是有一种大隐隐于…

CF1156F. Card Bag

CF1156F. Card Bag Solution 概率DPDPDP。 记cnticnt_icnti​表示有多少个ajia_jiaj​i&#xff0c;再把aia_iai​离散化。 令fi,jf_{i,j}fi,j​表示当前取过iii个数&#xff0c;当前取到了aja_jaj​的概率。 fi,jfi−1,k∗cntain−i1f_{i,j}f_{i-1,k}*\frac{cnt_{a_i}}{n-i1…

.NetCore下使用Polly结合IHttpClientFactory实现聚合服务

在使用微服务的过程中经常会遇到这样的情况&#xff0c;就目前我遇到的问题做下分析情况一&#xff1a;这里服务对于前后端分离情况来说&#xff0c;多使用查询服务&#xff0c;前端直接获取不同服务的数据展示&#xff0c;如果出现其中的服务失败&#xff0c;对业务数据无影响…

CF1342E. Placing Rooks

CF1342E. Placing Rooks Solution 有一个显然的性质&#xff1a; 要么每行都有至少一个&#xff0c;要么每列至少有一个。 只看每行有至少一个的情况&#xff1a; 显然必有n−kn-kn−k列有棋子。 考虑容斥&#xff0c;枚举空列的数量iii。 Ans∑(−1)i∗(n−ki)∗(n−k−i)n…

你需要了解的有关.NET日期时间的必要信息

引言DateTime数据类型是一个复杂的问题&#xff0c;复杂到足以让你在编写【将日期从Web服务器返回到浏览器】简单代码时感到困惑。ASP.NET MVC 5和 Web API 2/ASP.NETCore 以不同方式序列化日期&#xff0c;这可能会给在一个Web应用程序中同时使用这两个序列化的开发人员带来更…

CF750F. New Year and Finding Roots

CF750F. New Year and Finding Roots Solution 设当前节点为xxx&#xff0c; 若当前节点为叶子节点&#xff0c;则向它的邻居跑。 若当前节点为根&#xff0c;则找到答案。 否则&#xff0c;每次从xxx向两个方向找&#xff0c;每次只走一个没有走过的邻居&#xff0c;显然可以…

只需3步,即可将你的Chromium Edge 浏览器设置成中文

最近&#xff0c;Chromium Edge 浏览器推出了添加语言包的功能&#xff0c;于是我们可以轻松将其界面设置成中文的。第1步: 升级浏览器到最新版在Chromium Edge 浏览器的地址栏中输入:edge://settings/help稍等片刻&#xff0c;浏览器会自行升级到最新版。第2步: 将Language se…

CF730F. Ber Patio

CF730F. Ber Patio Solution 由于∑ai\sum{a_i}∑ai​只有10510^5105&#xff0c;即除掉原有的bbb&#xff0c;代金券最多为10410^4104&#xff0c;因此我们令f[i][j]f[i][j]f[i][j]表示到了第iii天&#xff0c;靠现金获得的代金券共为jjj的最小现金和。 转移时枚举第i1i1i1…

【北京】线下活动 | Azure SQL Database Managed Instance发布会

6/12/2019 | 8.30 AM - 1.30 PM微软大厦一号楼一层故宫会议室N丹棱街5号 海淀区 北京市S尊敬的客户感谢您一直以来对微软的支持&#xff01;诚挚地邀请您参加微软Azure SQL Database Managed Instance &#xff08;SQL Database托管实例&#xff09;在中国北京的发布会。SQL Da…

CF768F. Barrels and boxes

CF768F. Barrels and boxes Solution 又一道据说是套路题。 核心在于枚举WWW的连续段个数为xxx。 然后就能知道FFF的连续段个数为x−1,x,x1x-1,x,x1x−1,x,x1&#xff0c;可以用插板法求出任意把WWW分xxx段的方案数&#xff0c;分xxx段每段WWW至少HHH个的方案数&#xff0c;…

ASP.Net Core MVC 发生二次请求

Bug回忆录昨天搭建新框架的时候&#xff0c;遇到一个很奇怪的“Bug”&#xff0c;每次请求都会触发两次Aciton&#xff0c;举例子吧&#xff0c;Demo&#xff1a;_Layout.cshtmlHomeControllerIndex.cshtml<h1>Hi, Im index page.</h1>最简单不过的代码&#xff0c…

CF1354F. Summoning Minions

CF1354F. Summoning Minions Solution VPVPVP结束十分钟后AC,qwqAC,qwqAC,qwq。 首先因为ai,bi≥0a_i,b_i \geq 0ai​,bi​≥0&#xff0c;所以所有东西全用一次答案不会变劣&#xff0c;留到最后的集合大小一定为kkk。 如果我们知道留到最后的集合Sx1,x2...xkS{x_1,x_2...x…