Furion 15. 安全鉴权

Furion 15. 安全鉴权15 1 什么是鉴权鉴权实际上就是一种身份认证 由用户提供凭据 然后将其与存储在操作系统 数据库 应用或资源中的凭据进行比较 在授权过程中 如果凭据匹配 则用户身份验证成功 可执行已向其授权的操作 授权指判断允许用户执行的操作的过程 也可以将身份验证理解为进入空间 例如服务器 数据库 应用或资源 的一种方式 而授权是用户可以对该空间 服务器 数据库或应用 内的哪些对象执行哪些操作 15 1 1 常见的鉴权方式 HTTPBasicAut 这是 HTTP 协议实现的基本

15.1 什么是鉴权

鉴权实际上就是一种身份认证

15.1.1 常见的鉴权方式

  • HTTP Basic Authentication

这是 HTTP 协议实现的基本认证方式,我们在浏览网页时,从浏览器正上方弹出的对话框要求我们输入账号密码,正是使用了这种认证方式

  • Session + Cookie

利用服务器端的 session(会话)和浏览器端的 cookie 来实现前后端的认证,由于 http 请求时是无状态的,服务器正常情况下是不知道当前请求之前有没有来过,这个时候我们如果要记录状态,就需要在服务器端创建一个会话(session),将同一个客户端的请求都维护在各自的会话中,每当请求到达服务器端的时候,先去查一下该客户端有没有在服务器端创建 session,如果有则已经认证成功了,否则就没有认证。

  • Token

客户端在首次登陆以后,服务端再次接收 HTTP 请求的时候,就只认 Token 了,请求只要每次把 Token 带上就行了,服务器端会拦截所有的请求,然后校验 Token 的合法性,合法就放行,不合法就返回 401(鉴权失败)

Token验证比较灵活,适用于大部分场景。常用的 Token 鉴权方式的解决方案是 JWTJWT 是通过对带有相关用户信息的进行加密,加密的方式比较灵活,可以根据需求具体设计。

  • OAuth

OAuth(开放授权)是一个开放标准,允许用户授权第三方网站访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方网站或分享他们数据的所有内容,为了保护用户数据的安全和隐私,第三方网站访问用户数据前都需要显式的向用户征求授权。我们常见的提供 OAuth 认证服务的厂商有支付宝、 和微信。

OAuth 协议又有 1.0 和 2.0 两个版本。相比较 1.0 版,2.0 版整个授权验证流程更简单更安全,也是目前最主要的用户身份验证和授权方式。

15.2 如何使用

配置之前

在添加授权服务之前,请先确保 Startup.csConfigure 是否添加了以下两个中间件:

app.UseAuthentication(); app.UseAuthorization(); 

15.2.1 添加 Cookie 身份验证

// Cookies单独身份验证 services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, b => { 
    b.LoginPath = "/Home/Login"; }); 

15.2.2 添加 Jwt 身份验证

services.AddJwt(); 

特别注意

JWT 鉴权并未包含在 Furion 框架中,需要安装 Furion 框架提供的 Furion.Extras.Authentication.JwtBearer 拓展包。

  • 自定义 Jwt 配置(默认无需配置)
{ 
    "JWTSettings": { 
    "ValidateIssuerSigningKey": true, // 是否验证密钥,bool 类型,默认true "IssuerSigningKey": "你的密钥", // 密钥,string 类型,必须是复杂密钥,长度大于16 "ValidateIssuer": true, // 是否验证签发方,bool 类型,默认true "ValidIssuer": "签发方", // 签发方,string 类型 "ValidateAudience": true, // 是否验证签收方,bool 类型,默认true "ValidAudience": "签收方", // 签收方,string 类型 "ValidateLifetime": true, // 是否验证过期时间,bool 类型,默认true,建议true "ExpiredTime": 20, // 过期时间,long 类型,单位分钟,默认20分钟 "ClockSkew": 5, // 过期时间容错值,long 类型,单位秒,默认 5秒 "Algorithm": "HS256" // 加密算法,string 类型,默认 SecurityAlgorithms.HmacSha256 } } 

系统安全注意事项

Furion 框架为了方便开发,已经自动添加了 Jwt 默认配置。建议每个项目都应该单独配置 IssuerSigningKeyValidIssuerValidAudience 这三个。否则同样用了 Furion 框架生成的 Token 可能存在相互访问各自系统的风险。

温馨提示

目前支持的加密算法,详情请查阅SecurityAlgorithms

  • 生成 Token
// 生成 token var accessToken = JWTEncryption.Encrypt(new Dictionary<string, object>() { 
    { 
    "UserId", user.Id }, // 存储Id { 
    "Account",user.Account }, // 存储用户名 }); 

15.2.3 混合身份验证

// JWT 和 Cookies 混合身份验证 services.AddJwt(options => { 
    options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme; }) .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options => { 
    options.LoginPath = "/Home/Login"; }); 

特别注意

如果启用了混合身份验证后,WebApi 需在控制器/Action 中指定 Scheme 类型为 JwtBearerDefaults.AuthenticationScheme,如:

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] public class ApiServices : IDynamicApiController { 
    } 

如果不设置 Scheme 那么在混合授权的 Swagger 中将默认采用 Cookie 方式,也就是授权失败会将整个 登录页面 内容返回。

15.3 高级自定义授权

Furion 框架提供了非常灵活的高级策略鉴权和授权方式,通过该策略授权方式可以实现任何自定义授权。

15.3.1 AppAuthorizeHandler

Furion 框架提供了 AppAuthorizeHandler 策略授权处理程序提供基类,只需要创建自己的 Handler 继承它即可。如:JwtHandler

using Furion.Authorization; using Furion.Core; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.IdentityModel.JsonWebTokens; namespace Furion.Web.Core { 
    ///  /// JWT 授权自定义处理程序 ///  public class JwtHandler : AppAuthorizeHandler { 
    ///  /// 请求管道 ///  ///  ///  /// 
    public override Task<bool> PipelineAsync(AuthorizationHandlerContext context, DefaultHttpContext httpContext) { 
    // 此处已经自动验证 Jwt token的有效性了,无需手动验证 // 检查权限,如果方法是异步的就不用 Task.FromResult 包裹,直接使用 async/await 即可 return Task.FromResult(CheckAuthorzie(httpContext)); } ///  /// 检查权限 ///  ///  /// 
    private static bool CheckAuthorzie(DefaultHttpContext httpContext) { 
    // 获取权限特性 var securityDefineAttribute = httpContext.GetMetadata<SecurityDefineAttribute>(); if (securityDefineAttribute == null) return true; return "查询数据库返回是否有权限"; } } } 

之后注册 JwtHandler 即可:

services.AddJwt<JwtHandler>(); 

15.3.2 完全自定义授权

有些时候可能针对不同的平台采用不一样的授权方式,比如合作信任的第三方机构可以免授权,这时候我们只需要重写 HandleAsync 方法即可。如:

using Furion.Authorization; using Furion.Core; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using System.Threading.Tasks; namespace Furion.Web.Core { 
    public class JwtHandler : AppAuthorizeHandler { 
    public override async Task HandleAsync(AuthorizationHandlerContext context) { 
    // 常规授权(可以判断不是第三方) var isAuthenticated = context.User.Identity.IsAuthenticated; // 第三方授权自定义 if(是第三方){ 
    foreach (var requirement in pendingRequirements) { 
    // 授权成功 context.Succeed(requirement); } } // 授权失败 else context.Fail(); } } } 

15.4 授权特性及全局授权

默认情况下,所有的路由都是允许匿名访问的,所以如果需要对某个 ActionController 设定授权访问,只需要在 ActionController[AppAuthorize][Authorize] 特性即可。

如果需要对特定的 ActionController 允许匿名访问,则贴 [AllowAnonymous] 即可。

15.4.1 全局授权

services.AddJwt<JwtHandler>(enableGlobalAuthorize:true); 

15.4.2 匿名访问

如果需要对特定的 ActionController 允许匿名访问,则贴 [AllowAnonymous] 即可。

15.5 自动刷新 Token

15.5.1 后端登录部分

当用户登录成功之后,返回 accessToken 字符串,之后通过 JWTEncryption.GenerateRefreshToken() 获取 刷新Token,并通过响应报文头返回,如:

// token var accessToken = JWTEncryption.Encrypt(new Dictionary<string, object>() { 
    { 
    "UserId", user.Id }, // 存储Id { 
    "Account",user.Account }, // 存储用户名 }); // 获取刷新 token var refreshToken = JWTEncryption.GenerateRefreshToken(accessToken, 30); // 第二个参数是刷新 token 的有效期,默认三十天 // 设置请求报文头 httpContextAccessor.HttpContext.Response.Headers["access-token"] = accessToken; httpContextAccessor.HttpContext.Response.Headers["x-access-token"] = refreshToken; 

用户登录成功之后把 accessTokenrefreshToken 一起返回给客户端存储起来。

15.5.2 后端授权 Handler 部分

using Furion.Authorization; using Furion.Core; using Furion.DataEncryption; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; using System.Threading.Tasks; namespace Furion.Web.Core { 
    ///  /// JWT 授权自定义处理程序 ///  public class JwtHandler : AppAuthorizeHandler { 
    ///  /// 重写 Handler 添加自动刷新收取逻辑 ///  ///  /// 
    public override async Task HandleAsync(AuthorizationHandlerContext context) { 
    // 自动刷新 token if (JWTEncryption.AutoRefreshToken(context, context.GetCurrentHttpContext())) { 
    await AuthorizeHandleAsync(context); } else context.Fail(); // 授权失败 } ///  /// 验证管道,也就是验证核心代码 ///  ///  ///  /// 
    public override Task<bool> PipelineAsync(AuthorizationHandlerContext context, DefaultHttpContext httpContext) { 
    // 检查权限,如果方法时异步的就不用 Task.FromResult 包裹,直接使用 async/await 即可 return Task.FromResult(true); } } } 

15.5.3 客户端部分

客户端每次请求需将 accessTokenrefreshToken 放到请求报文头中传送到服务端,格式为:

Authorization: Bearer 你的token X-Authorization: Bearer 你的刷新token 

特别注意

在正常开发中,refreshToken 无需每次请求携带,而是 accessToken 即将过期之后携带即可。可以在客户端自行判断 accessToken 是否即将过期。

如果 Token 过期,那么 Furion 将自动根据有效期内的 refreshToken 自动生成新的 AceessToken,并在 响应报文头 中返回,如:

access-token: 新的token x-access-token: 新的刷新token 

存储新的 Token

前端需要获取 响应报文头 新的 token 和刷新 token 替换之前在客户处存储旧的 token 和刷新 token。

15.6 获取 Jwt 存储的信息

// 获取 `Jwt` 存储的信息 var userId = App.User?.FindFirstValue("键"); 

注意引入 System.Security.Claims 命名空间

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/206283.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月19日 下午4:02
下一篇 2026年3月19日 下午4:02


相关推荐

  • html中table样式_table样式设置

    html中table样式_table样式设置如果想在网页中建一个如下table表格应该怎么做呢?首先建一个表<table><table>/*table标签就是建一个表格*/ <tr>/*tr标签就是tablerow,即为表格中的一行*/ <th>学号</th>/*th标签即tablehead,就是表头*/ <th>姓名</th> <th>手机号</th> <th>家庭地址</th&

    2026年1月31日
    3
  • Ubuntu 16.04安装Java JDK8

    Ubuntu 16.04安装Java JDK8JavaJDK在linux系统有两个版本,一个开源版本Openjdk,还有一个oracle官方版本jdk,oracleJDK既可以通过添加ppa源命令行安装,也可以去官网下载jdk压缩包安装。下面分别记录一下这三种安装方式的步骤。安装openjdk1、更新软件包列表:sudoapt-getupdate2、安装openjdk-8-jdk:sudoapt-getinstall

    2022年7月12日
    17
  • Linux日志管理工具 journalctl「建议收藏」

    Linux日志管理工具 journalctl「建议收藏」日志Linux日志管理基本概念journalctl查询所有系统服务日志内容journalctlmaybeusedtoquerythecontentsofthesystemd(1)journalaswrittenbysystemd-journald.service(8).CentOS7及以后版本,利用Systemd统一管理所有Unit的启动日志。带来的好处就是,可以只用journalctl一个命令,查看所有系统日志查看内容包括内核日志

    2022年5月23日
    36
  • mysql一个汉字是几个字节_mysql里一个中文汉字占多少字节数?

    mysql一个汉字是几个字节_mysql里一个中文汉字占多少字节数?在 mysql 中 如果是 latin1 字符集下 一个中文汉字占 2 个字节数 如果是 utf8 字符集下 一个中文汉字占 3 个字节数 如果是 gbk 字符集下 一个中文汉字占 2 个字节数 mysql 各字符集下汉字和字母占字节数 varchar N 这里的 是指字符数 并不是字节数 占用的字节数与编码有关在 mysql5 1 5 alpha 下测试得出如下结论 latin1 1character 1byte 1 汉字 2

    2026年3月17日
    2
  • 设备管理器里“SM总线控制器”、“其它PCI桥设备”驱动有问题[通俗易懂]

    设备管理器里“SM总线控制器”、“其它PCI桥设备”驱动有问题[通俗易懂]WinXP重装系统后设备管理器里面出现黄色问号。各自是“SM总线控制器”和“其它PCI桥设备“,主板是七彩虹的,芯片组是geForce7025的,南桥是nForce630a,用七彩虹官网的主板驱动装了没用。用驱动人生先备份还有一个相同主板的机器的驱动。得到 NVIDIAnForcePCISystemManagement_*.zip, NVIDIANetworkBus…

    2022年5月3日
    80
  • 排序算法:归并排序、快速排序

    排序算法:归并排序、快速排序

    2021年10月5日
    49

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号