【IdentityServer4】基础
简介
IdentityServer4
是为ASP.NET Core
量身打造的,实现了OpenID Connect
和OAuth 2.0
协议的认证授权中间件。
IdentityServer4中文文档:http://www.identityserver.com.cn/Home/
中文文档:https://github.com/thinksjay/IdentityServer4
IdentityServer4英文文档:http://docs.identityserver.io/en/latest/intro/terminology.html
源码:https://gitee.com/core-demo/identity-server4
OpenId Connect
- OpenId
OpenID的认证非常简单,当你访问需要认证的A网站时,A网站要求你输入你的OpenID用户名,然后会跳转你的OpenID服务网站,输入用户名密码验证通过后,再跳回A网站,而些时已经显示认证成功。
OAuth关注的是第三方应用访问其受保护资源的能力,而OpenID关注的是第三方应用获取用户身份的能力。 - OpenID Connect
OpenID Connect是OpenID的升级版,简称OIDC,并完全兼容OAuth2
术语
- 用户(User)
拥有资源的人 - 客户端(Client)
客户端就是从identityserver请求令牌的软件,既可以通过身份认证令牌来验证识别用户身份,又可以通过授权令牌来访问服务端的资源。但是客户端首先必须在申请令牌前已经在identityserver服务中注册过。
客户端不仅可以是Web应用程序,app或桌面应用程序,SPA等。 - 资源(Resource)
资源就是你想用identityserver保护的东东,可以是用户的身份数据或者api资源。
每一个资源都有一个唯一的名称,客户端使用这个唯一的名称来确定想访问哪一个资源。在访问之前,identityserver服务端已经配置好了哪个客户端可以访问哪个资源- 用户的身份信息
用户的身份信息实际由一组claim组成,例如姓名或者邮件都会包含在身份信息中(将来通过identityserver校验后都会返回给被调用的客户端)。 - API资源
API资源就是客户端想要调用的功能,通常以json或xml的格式返回给客户端,通常通过webapi来建立模型。
- 用户的身份信息
- 身份令牌(IDToken)
顾名思义用于做身份认证,例如sso其实主要就是用于身份认证
一个身份令牌指的就是对认证过程的描述。它至少要标识某个用户(Called the sub aka subject claim)的主身份信息,和该用户的认证时间和认证方式。但是身份令牌可以包含额外的身份数据,具体开发者可以自行设定。 - 访问令牌(AccessToken)
访问令牌允许客户端访问某个 API 资源。客户端请求到访问令牌,然后使用这个令牌来访问 API资源。访问令牌包含了客户端和用户(如果有的话)的相关信息,API通过这些令牌信息来授予客户端的数据访问权限。
访问令牌是短期的,可撤回的,具有一定范围 - 刷新令牌(RefreshToken)
用来获取AccessToken,可以随时控制访问权限,因为生成新的AccessToken。
Access Token 是客户端访问资源服务器的令牌。拥有这个令牌代表着得到用户的授权。然而,这个授权应该是临时的,有一定有效期。这是因为,Access Token 在使用的过程中可能会泄露。
然而引入了有效期之后,客户端使用起来就不那么方便了。每当 Access Token 过期,客户端就必须重新向用户索要授权。这样用户可能每隔几天,甚至每天都需要进行授权操作。这是一件非常影响用户体验的事情。希望有一种方法,可以避免这种情况。
于是 Oauth2.0 引入了 Refresh Token 机制。Refresh Token 的作用是用来刷新 Access Token,Refresh Token 的有效期非常长。鉴权服务器提供一个刷新接口,例如:
http://xxx.xxx.com/refresh?refreshtoken=&client_id=&client_secret=
传入 refresh token 和 client_id,鉴权服务器验证通过后,返回一个新的 access token。为了安全,Oauth2.0 引入了两个措施:
1、Oauth2.0 要求,refresh token 一定是保存在客户端的服务器上的,而绝不能存放在狭义的客户端(例如移动 app、PC端软件) 上。调用 refresh 接口的时候,一定是从服务器到服务器的访问;
Oauth2.0 引入了 client_secret 机制。即每一个 client_id 都对应一个 client_secret。这个 client_secret 会在客户端申请 client_id 时,随 client_id 一起分配给客户端。客户端必须把 client_secret 妥善保管在服务器上,决不能泄露。刷新 access token 时,需要验证这个 client_secret。
- 范围(Scope)
在简单情况下API只需一个作用域,如果你想细分API功能,并允许不同客户端访问不同的部分。
授权模式
OAuth2.0 定义了四种授权模式
Implicit
:简化模式;直接通过浏览器的链接跳转申请令牌。Client Credentials
:客户端凭证模式;该方法通常用于服务器之间的通讯;该模式仅发生在Client与Identity Server之间。Resource Owner Password Credentials
:密码模式Authorization Code
:授权码模式;
Client Credentials
客户端凭证模式,是最简单的授权模式,因为授权的流程仅发生在Client与Identity Server之间。
该模式的适用场景为服务器与服务器之间的通信。比如对于一个电子商务网站,将订单和物流系统分拆为两个服务分别部署。订单系统需要访问物流系统进行物流信息的跟踪,物流系统需要访问订单系统的快递单号信息进行物流信息的定时刷新。而这两个系统之间服务的授权就可以通过这种模式来实现。
Resource Owner Password Credentials
Resource Owner其实就是User,所以可以直译为用户名密码模式。密码模式相较于客户端凭证模式,多了一个参与者,就是User。
在这种模式中,用户必须把自己的密码给客户端,但是客户端不得存储密码,这通常用在用户对客户端高度信任的情况下,比如客户端是系统的一部分,或者由一个著名公司出品。而认证服务器只有在其他授权模式无法执行的情况下,才能考虑使用这种模式。
Authorization Code
授权码模式适用于有后端的应用,因为客户端根据授权码去请求token时是需要把客户端密码转进来的,为了避免客户端密码被暴露,所以请求token这个过程需要放在后台。
授权码模式是目前功能最完整、流程最严密的授权模式。它主要分为两大步骤:认证和授权。
其流程为:
- 用户访问客户端,客户端将用户导向Identity Server。
- 用户填写凭证信息向客户端授权,认证服务器根据客户端指定的重定向URI,并返回一个【Authorization Code】给客户端。
- 客户端根据【Authorization Code】向Identity Server申请【Access Token】
Implicit
简化模式是相对于授权码模式而言的。简化模式不通过第三方应用程序的服务器【Client】,直接在浏览器中向认证服务器申请令牌,跳过了"授权码"这个步骤,因此得名。所有步骤在浏览器中完成,令牌对访问者是可见的,且客户端不需要认证。
这种模式的使用场景是基于浏览器的应用(如:SPA),需要将token存储在前端
这种方式把令牌直接传给前端,是很不安全的。因此,只能用于一些安全要求不高的场景,并且令牌的有效期必须非常短,通常就是会话期间(session)有效,浏览器关掉,令牌就失效了。不支持refresh token
AddIdentityServerAuthentication
和AddJwtBearer
的区别
AddIdentityServerAuthentication
是 IdentityServer
官方封装的用于认证的方法,接入 ASP.NET Core
的认证机制,包含在组件 IdentityServer4.AccessTokenValidation
中。
在 ASP.NET Core 早期,1.1、2.0时 AddIdentityServerAuthentication
还是 IdentityServer
官方文档及示例代码提供的注册认证的方法,后面都变更为了:
services.AddAuthentication("Bearer")
.AddJwtBearer()
一度我曾经以为 AddIdentityServerAuthentication
无用了,现在我更正我的想法,这个方法同时支持了 Reference Token
和JWT
的认证,所以说如果使用 Reference Token
还是要使用这个方法的。
当然,如果使用 JWT
的话还是推荐直接使用 AddJwtBearer
,这是微软官方提供的支持JWT的认证组件,不用额外安装 Nuget 包。
安装ui
dotnet new -i IdentityServer4.Templates::4.0.1
注意事项
IdentityServer4版本从3.1.x
升级到4.x
会报“无效的scope”,“Audience validation failed”等问题。
ApiResource 的 Scope 正式独立出来为 ApiScope 对象,区别ApiResource 和 Scope的关系, Scope 是属于ApiResource 的一个属性,可以包含多个Scope。,细化了权限配置,代码需做如下修改:
// Defining an API Resource
public static IEnumerable<ApiResource> Apis =>
new List<ApiResource>{
new ApiResource("Order.WebApi", "订单服务"){
Scopes=new[]{ "Order.Read","Order.Write" }
},
new ApiResource("Product.WebApi", "产品服务")
};
//4.x新增ApiScope
public static IEnumerable<ApiScope> GetApiScopes=>new[] { new ApiScope("Order.Read") , new ApiScope("Order.Write") };
// Defining Client
public static IEnumerable<Client> Clients =>
new List<Client> {
new Client
{
//没有交互式用户,使用clientid/secret进行身份验证
AllowedGrantTypes=GrantTypes.ClientCredentials,
ClientId="client",
ClientSecrets={new Secret("secret".Sha256())},
//客户端可以访问的范围
AllowedScopes={ "Order.Read", "Order.Write" }
}
};
builder.Services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddInMemoryIdentityResources(Config.IdentityResources)
.AddInMemoryApiScopes(Config.GetApiScopes)//4.x新增
.AddInMemoryApiResources(Config.Apis)
.AddInMemoryClients(Config.Clients);
参考
IdentityServer4系列:https://zhaobingwang.blog.csdn.net/?type=blog
晓晨Master:https://www.cnblogs.com/stulzq/p/8119928.html
圣杰:https://www.cnblogs.com/sheng-jie/p/9430920.html
理解OAuth 2.0(阮一峰):http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
2020-04-28 设计模式-模板方法模式