Intro
最近开始真正的实践了一些网关的东西,最近写几篇文章分享一下我的实践以及遇到的问题。
本文主要介绍网关后面的服务如何进行认证。
解决思路
网关可以做一部分的认证和授权,服务内部有时候也会需要用户的信息,这时该怎么办呢,我们使用的是 JWT 认证,有一个 identity server去颁发,验证 token,一种简单方式可以把 token 直接往后传,传递给后面的具体某个服务,后面的服务可以去 identity server 拿到公钥信息去验证 token 的合法性,依然可以拿到用户的一些基本信息,但又觉得这样后面的服务还是要依赖 identityserver 不是太好,因为认证已经在网关做掉了,后面不应该再去做认证的事情了,而且解析 JWT token 也是有一定的性能损耗,于是想把用户的基本信息在网关认证完成之后放到请求头中。
我们网关用的Ocelot,开源的原生 .NET 项目方便自己扩展,Ocelot 中有一个 Claims2Headers 可以把 Claims 中的信息转换为请求头,详细使用参见文档,但是实现有个bug,如果有多个值他只会取第一个,详见issue,可以自己扩展一个 ocelot 的中间件替换掉原有的中间件。
把用户信息放到请求头中,后面的服务从请求头中就可以拿到用户的基本信息了,为了后面的服务不做过多的改动,我做了一个自定义的认证,从请求头中拿用户的基本信息进行认证,这样后面的服务还是可以直接使用 User.Identity.IsAuthenticated
和 User.Identity.Name
等,不需要做什么改动。于是就有了这一根据请求头认证的项目
实现效果
下载示例项目,在 TestWebApplication 目录下运行 dotnet run
在浏览器中访问 http://localhost:5000/api/values
使用 postman 或 fiddler (或其它你喜欢的工具)带上 header 访问 http://localhost:5000/api/values
使用方式
使用方式可以参考示例项目
使用自定义的 HeaderAuthentication 来替代之前的认证方式,默认配置了用户名,用户id以及用户角色,如果不能满足可以在 options 中的 AdditionalHeaderToClaims
中添加更多转换
这样就可以了,你可以下载示例项目,快速体验,你可以直接添加下面几个请求头
UserId 用户id
UserName 用户名称
UserRoles 用户角色(多个角色以 , 分割,可以在 options 里自定义多个值的分隔符
直接访问需要授权才能访问的资源了
现在只是初步的设想与实现,并已经验证确实可行,代码还有一些业务逻辑比如 UserId 现在是必须的,可以根据自己需要自行修改,最近有点忙,找时间再修改重构一下再发布 nuget 包。如果有什么需求或问题,欢迎一起探讨。
源码
自定义认证源码
提供了 HeaderAuthetication 和 QueryAuthentication 两种实现,一种使用请求头信息认证,一种使用 QueryString 信息认证。
HeaderAuthetication 主要实现在 HeaderAuthenticationHandler
核心代码,重写 Authenticate 方法:
注意
请注意,如果使用这种方式,请确保你的服务不会被外界直接访问,请求只能从网关或者本地调试发起。需要保证安全性,不能直接暴露到公网,才能使用这种方式。
原文地址:https://www.cnblogs.com/weihanli/p/10464507.html
.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com