.net 下的身份认证与授权的实现

背景

任何一个系统,都需要对于底层访问的页面和接口进行安全的处理,其中核心就是认证和授权。

另外一个问题就是在实际编程过程中,我们的代码有不同的模式,不同的分层或者在不同的项目之中,如何在不同的地方取得用户信息,特别是业务系统,根据操作员的id来处理不同的业务权限逻辑,这是很多业务应用所关心的。

微软在不同的版本都有各自的实现,现在以>= .net6的版本为准。

基本概念

这里所说的基本概念,是微软框架下的技术概念,对于一些通识的概念,比如以下内容,假定对这些都是熟悉的,

还有对于基本的微软技术概念,也假定大家都是熟悉的,比如 管道,特别是httpcontext的属性

.net 授权

.net 提供了简单授权、基于角色的授权、基于策略的授权,多样的授权方式在通过简单的Attribute修饰就能满足大部分应用场景。授权中重要的两个Attribute就是AuthorizeAttribute和AllowAnonymousAttribute,所有的授权配置都离不开这两个Attribute。同时,.net 对授权方案的扩展也非常方便,在本节的最后会介绍如何自定义授权处理程序来实现自定义授权逻辑。授权有这三种类型简单授权:只要登录就能访问,在Controller或者Action上加个Authorize就行基于角色的授权:特定角色能访问基于策略的授权:顾名思义基于角色的授权.

app.UseAuthentication()

  1. services.AddAuthentication(options =>) 如果需要个性化,可以在这里展开,一些规则,比如 DefaultAuthenticateScheme DefaultChallengeScheme
  2. AddJwtBearer Token个性化验证参数
  3. AuthenticationService, AuthenticationHandlerProvider, AuthenticationSchemeProvider 是的,是通过这三个服务,核心是 AuthenticationMiddleware 逻辑都在这里面
  4. Scheme 就是用什么标准规定认证,比如用jwt,bearer, 不同的scheme,就有不同的options,就有不同的handler

所以核心就是使用或者重载这些内容

httpcontext.user

  1. publicabstract System.Security.Claims.ClaimsPrincipal User 这是标准定义

身份认证通过后,身份认证处理程序会返回身份认证票根,即AuthenticationTicket。

AuthenticationTicket是ASP.NET Core封装认证信息的类。

AuthenticationTicket又包含了ClaimsPrincipal,ClaimsPrincipal可以理解为用户主体,由一组ClaimIdentity组成。

ClaimsIdentity可以理解为身份证明,一个用户主体可以有多个身份证明,就好比身份证、驾驶证都可以代表唯一具体的人一样。

ClaimsIdentity包含了一组Claim,Claim就是好比身份证上的姓名、性别、籍贯等信息。一个用户通过身份认证后,就会用以上类来组织用户信息。后续的授权等其他中间件就可以使用这些信息来进行功能设计。

结构示例如下:

  • AuthenticationTicket (身份认证票根,其中封装了认证信息)
    • ClaimsPrincipal (用户主体)
      • ClaimIdentity (身份证明)
        • Claim
        • Claim
        • Claim
      • ClaimIdentity
      • ClaimIdentity

IHttpContextAccessor

我们知道当请求通过认证模块时,会给当前的HttpContext赋予当前用户身份标识,我们在需要授权的控制器中打上Authorize授权标签,就可以在ControllerBase的User属性获取到基于声明的权限标识(ClaimsPrincipal)。

  遗憾的是这只是针对Controller层面,很多场景下我们是需要在Service层乃至数据层获直接使用用户信息,这种情况我们就使用不了User了。

解决办法就是通过这个接口来注入一个服务,在业务层面来拉取用户相关信息。可以在登录的时候把userid写进来,另外就是通过token为key,使用redis存放用户信息。

实现基本思路

使用微软安全框架

  1. 使用微软数据库一套
  2. builder.Services.AddIdentity<ApplicationUser, ApplicationRole> 构建自己个性化身份 public partial class ApplicationUser : IdentityUser

namespace Microsoft.AspNetCore.Identity;

/// <summary>

/// The default implementation of <see cref="IdentityUser{TKey}"/> which uses a string as a primary key.

/// </summary>

public class IdentityUser : IdentityUser<string>

  1. public abstract class AuthenticationStateProvider ApplicationAuthenticationStateProvider 自己实现微软的认证,builder.Services.AddScoped<AuthenticationStateProvider, ApplicationAuthenticationStateProvider>();

基于类库个性化认证和授权

清楚了逻辑,后面就是体力活了,不过有一坨的工作要做,需要用户表,应用表,角色表等等

  1. Services.ConfigureOptions<ConfigureJwtBearerOptions>();

Services.ConfigureOptions<ValidateIdentityTokenOptions>();

var authBuilder = Services

.AddAuthentication(MultiScheme)

.AddPolicyScheme(MultiScheme, MultiScheme, options =>

{

options.ForwardDefaultSelector = context =>

{

return context.Request.Headers.Authorization.Any(x => x!.Contains(ApiKeyDefaults.AuthenticationScheme))

? ApiKeyDefaults.AuthenticationScheme

: JwtBearerDefaults.AuthenticationScheme;

};

})

.AddJwtBearer();

_configureApiKeyAuthorization(authBuilder);

Services.AddSingleton<IAuthorizationHandler, yourhandler>();

Services.AddSingleton<IAuthorizationHandler, yourhandler>();

Services.AddSingleton(ApiKeyProviderType);

Services.AddSingleton<IApiKeyProvider>(sp => (IApiKeyProvider)sp.GetRequiredService(ApiKeyProviderType));

Services.AddAuthorization(options => options.AddPolicy(IdentityPolicyNames.SecurityRoot, policy => policy.AddRequirements(new ())));

这是最终都要有的,围绕这些内容展开。

整个项目挺多,就不展开细节了,代码是.net 7 .net8 环境下跑的。

相关推荐
哥是强混21 小时前
Means:基于 .NET 10 打造的开源自部署 S3 兼容对象存储服务
网络·数据库·.net
公子小六1 天前
基于.NET的Windows窗体编程之WinForms图像控件
windows·microsoft·c#·.net·winforms
界面开发小八哥1 天前
界面控件DevExpress WPF v26.1新版亮点 - TreeView、Spreadsheet控件功能升级
.net·wpf·界面控件·devexpress·ui开发
脚后跟法1 天前
.NET热门ORM真实的性能测试总结
jvm·php·.net
无风听海2 天前
深入理解 .NET 中的 ToLowerInvariant:从字符串小写转换看文化敏感性陷阱
.net
带娃的IT创业者2 天前
深度解析:当 .NET 遇上 AI Agent,dotnet/skills 如何重塑软件开发方法论
人工智能·大模型·.net·软件开发·ai agent·dotnet/skills
娇气的红酒2 天前
关于.NET VS JavaEE平台争论的沉思录
java·java-ee·.net
单薄的衬衫2 天前
前一篇:详解 .NET 异步
.net
君无忧≈2 天前
.NET生态下Native AOT兼容的Cron任务调度框架
.net
步步为营DotNet2 天前
运用.NET Aspire 和 Native AOT 打造极致性能的云原生微服务
微服务·云原生·.net