asp.net core 自定义认证方式--请求头认证

Intro

最近开始真正的实践了一些网关的东西,最近写几篇文章分享一下我的实践以及遇到的问题。

本文主要介绍网关后面的服务如何进行认证。

解决思路

网关可以做一部分的认证和授权,服务内部有时候也会需要用户的信息,这时该怎么办呢,我们使用的是 JWT 认证,有一个 identity server去颁发,验证 token,一种简单方式可以把 token 直接往后传,传递给后面的具体某个服务,后面的服务可以去 identity server 拿到公钥信息去验证 token 的合法性,依然可以拿到用户的一些基本信息,但又觉得这样后面的服务还是要依赖 identityserver 不是太好,因为认证已经在网关做掉了,后面不应该再去做认证的事情了,而且解析 JWT token 也是有一定的性能损耗,于是想把用户的基本信息在网关认证完成之后放到请求头中。

我们网关用的Ocelot,开源的原生 .NET 项目方便自己扩展,Ocelot 中有一个 Claims2Headers 可以把 Claims 中的信息转换为请求头,详细使用参见文档,但是实现有个bug,如果有多个值他只会取第一个,详见issue,可以自己扩展一个 ocelot 的中间件替换掉原有的中间件。

把用户信息放到请求头中,后面的服务从请求头中就可以拿到用户的基本信息了,为了后面的服务不做过多的改动,我做了一个自定义的认证,从请求头中拿用户的基本信息进行认证,这样后面的服务还是可以直接使用 User.Identity.IsAuthenticatedUser.Identity.Name 等,不需要做什么改动。于是就有了这一根据请求头认证的项目

实现效果

下载示例项目,在 TestWebApplication 目录下运行 dotnet run

在浏览器中访问 http://localhost:5000/api/values

使用 postman 或 fiddler (或其它你喜欢的工具)带上 header 访问 http://localhost:5000/api/values

使用方式

使用方式可以参考示例项目

使用自定义的 HeaderAuthentication 来替代之前的认证方式,默认配置了用户名,用户id以及用户角色,如果不能满足可以在 options 中的 AdditionalHeaderToClaims 中添加更多转换

        services.AddAuthentication(HeaderAuthenticationDefaults.AuthenticationSchema)
.AddHeader(HeaderAuthenticationDefaults.AuthenticationSchema, options => { options.AdditionalHeaderToClaims.Add("UserEmail", ClaimTypes.Email); })
;

这样就可以了,你可以下载示例项目,快速体验,你可以直接添加下面几个请求头

UserId 用户id

UserName 用户名称

UserRoles 用户角色(多个角色以 , 分割,可以在 options 里自定义多个值的分隔符

直接访问需要授权才能访问的资源了

现在只是初步的设想与实现,并已经验证确实可行,代码还有一些业务逻辑比如 UserId 现在是必须的,可以根据自己需要自行修改,最近有点忙,找时间再修改重构一下再发布 nuget 包。如果有什么需求或问题,欢迎一起探讨。

源码

自定义认证源码

提供了 HeaderAuthetication 和 QueryAuthentication 两种实现,一种使用请求头信息认证,一种使用 QueryString 信息认证。

HeaderAuthetication 主要实现在 HeaderAuthenticationHandler

核心代码,重写 Authenticate 方法:

        protected override Task<AuthenticateResult> HandleAuthenticateAsync()
{
if (!Request.Headers.ContainsKey(Options.UserIdHeaderName) || !Request.Headers.ContainsKey(Options.UserNameHeaderName))
{
return Task.FromResult(AuthenticateResult.NoResult());
}
var userId = Request.Headers[Options.UserIdHeaderName].ToString();
var userName = Request.Headers[Options.UserNameHeaderName].ToString();
var userRoles = new string[0];
if (Request.Headers.ContainsKey(Options.UserRolesHeaderName))
{
userRoles = Request.Headers[Options.UserRolesHeaderName].ToString()
.Split(new[] { Options.Delimiter }, StringSplitOptions.RemoveEmptyEntries);
}
var claims = new List<Claim>()
{
new Claim(ClaimTypes.NameIdentifier, userId),
new Claim(ClaimTypes.Name, userName),
}; if (userRoles.Length > 0)
{
claims.AddRange(userRoles.Select(r => new Claim(ClaimTypes.Role, r)));
}
if (Options.AdditionalHeaderToClaims.Count > 0)
{
foreach (var headerToClaim in Options.AdditionalHeaderToClaims)
{
if (Request.Headers.ContainsKey(headerToClaim.Key))
{
foreach (var val in Request.Headers[headerToClaim.Key].ToString().Split(new[] { Options.Delimiter }, StringSplitOptions.RemoveEmptyEntries))
{
claims.Add(new Claim(headerToClaim.Value, val));
}
}
}
}
// claims identity 's authentication type can not be null https://stackoverflow.com/questions/45261732/user-identity-isauthenticated-always-false-in-net-core-custom-authentication
var principal = new ClaimsPrincipal(new ClaimsIdentity(claims, Scheme.Name));
var ticket = new AuthenticationTicket(
principal,
Scheme.Name
);
return Task.FromResult(AuthenticateResult.Success(ticket));
}

注意

请注意,如果使用这种方式,请确保你的服务不会被外界直接访问,请求只能从网关或者本地调试发起。需要保证安全性,不能直接暴露到公网,才能使用这种方式。

Memo

如果有什么问题或者意见,欢迎与我联系。

asp.net core 自定义认证方式--请求头认证的更多相关文章

  1. 使用请求头认证来测试需要授权的 API 接口

    使用请求头认证来测试需要授权的 API 接口 Intro 有一些需要认证授权的接口在写测试用例的时候一般会先获取一个 token,然后再去调用接口,其实这样做的话很不灵活,一方面是存在着一定的安全性问 ...

  2. ASP.NET Core自定义中间件的方式

    ASP.NET Core应用本质上,其实就是由若干个中间件构建成的请求处理管道.管道相当于一个故事的框架,而中间件就相当于故事中的某些情节.同一个故事框架采用不同的情节拼凑,最终会体现出不同风格的故事 ...

  3. ASP.NET Core 防止跨站请求伪造(XSRF/CSRF)攻击 (转载)

    什么是反伪造攻击? 跨站点请求伪造(也称为XSRF或CSRF,发音为see-surf)是对Web托管应用程序的攻击,因为恶意网站可能会影响客户端浏览器和浏览器信任网站之间的交互.这种攻击是完全有可能的 ...

  4. 如何在ASP.NET Core自定义中间件中读取Request.Body和Response.Body的内容?

    原文:如何在ASP.NET Core自定义中间件中读取Request.Body和Response.Body的内容? 文章名称: 如何在ASP.NET Core自定义中间件读取Request.Body和 ...

  5. ASP.NET Core[源码分析篇] - Authentication认证

    原文:ASP.NET Core[源码分析篇] - Authentication认证 追本溯源,从使用开始 首先看一下我们通常是如何使用微软自带的认证,一般在Startup里面配置我们所需的依赖认证服务 ...

  6. asp.net core 使用中间件拦截请求和返回数据,并对数据进行加密解密。

    原文:asp.net core 使用中间件拦截请求和返回数据,并对数据进行加密解密. GitHub demo https://github.com/zhanglilong23/Asp.NetCore. ...

  7. asp.net core 自定义基于 HttpContext 的 Serilog Enricher

    asp.net core 自定义基于 HttpContext 的 Serilog Enricher Intro 通过 HttpContext 我们可以拿到很多有用的信息,比如 Path/QuerySt ...

  8. ASP.NET Core 如何记录每次请求的Request信息 - sky 胡萝卜星星 - CSDN博客

    原文:ASP.NET Core 如何记录每次请求的Request信息 - sky 胡萝卜星星 - CSDN博客 版权声明:本文为starfd原创文章,转载请标明出处. https://blog.csd ...

  9. asp.net core 自定义异常处理中间件

    asp.net core 自定义异常处理中间件 Intro 在 asp.net core 中全局异常处理,有时候可能不能满足我们的需要,可能就需要自己自定义一个中间件处理了,最近遇到一个问题,有一些异 ...

随机推荐

  1. 基于.NET的APP开发和Windows开发,异步回调差别

    在Smobiler的开发中,控件或组件及客户端功能都是通过事件或委托来进行处理的. Smobiler是基于异步非阻塞的方式来运行的 下面我们分别对Windows的和Smobiler的MessageBo ...

  2. JS常用正则表达式备忘录

    摘要: 玩转正则表达式. 原文:JS常用正则表达式备忘录 作者:前端小智 Fundebug经授权转载,版权归原作者所有. 正则表达式或"regex"用于匹配字符串的各个部分 下面是 ...

  3. Cesium 实现粒子效果贴地(伪)

    有时我们面对这样的需求,需要在地面上放一个周期性放大缩小的标记,可以使用粒子效果实现,但是粒子效果图片很难贴地(如果你知道怎么做,欢迎分享,期待有人打我脸),我只能变通实现一个看似贴地但实际没有贴地的 ...

  4. Android 上传图片到服务器二--------调用相机7.0以上权限问题

    [目录] (一)上传图片到服务器一 ---------------------------------Android代码 (二)上传图片到服务器二--------------------------- ...

  5. alter session set current_schema=Schema

    使用CURRENT_SCHEMA之后,当前会话所参考的默认SCHEMA变为设置的用户,而不再是当前的用户:其实需要稍微理解一下user和schema的区别先:user即oracle中的用户,和所有系统 ...

  6. VIVADO时序约束及STA基础

    一.前言 无论是FPGA应用开发还是数字IC设计,时序约束和静态时序分析(STA)都是十分重要的设计环节.在FPGA设计中,可以在综合后和实现后进行STA来查看设计是否能满足时序上的要求.本文阐述基本 ...

  7. 阿里云SLB出现502 Bad Gateway 错误排查解决方法

    502 Bad Gateway The proxy server received an invalid response from an upstream server. 原本系统是通过一个SLB转 ...

  8. kafka集群broker频繁挂掉问题解决方案

    现象:kafka集群频繁挂掉 排查日志:查看日志文件[kafkaServer.out],发现错误日志:ERROR Shutdown broker because all log dirs in /tm ...

  9. GROUP BY你都不会!ROLLUP,CUBE,GROUPPING详解

    Group By Group By 谁不会啊?这不是最简单的吗?越是简单的东西,我们越会忽略掉他,因为我们不愿意再去深入了解它. 1 小时 SQL 极速入门(一) 1 小时 SQL 极速入门(二) 1 ...

  10. spring mvc多个请求的影响 和使用全局变量

    对于那些会以多线程运行的单例类(比如spring mvc中的controller,dao,service): 局部变量不会受多线程影响 成员变量会受到多线程影响 如果方法里有成员变量,只有读操作,不受 ...