一. IDS4简介
1. 什么是IDS4
IdentityServer是基于OpenID Connect协议标准的身份认证和授权程序,它实现了OpenID 和 OAuth 2.0 协议。
2. 相关地址
(1).官网:https://identityserver4.readthedocs.io/en/latest/
(2).GitHub地址:https://github.com/IdentityServer
(2).三方中文文档:http://www.identityserver.com.cn/Home/Detail/Zhengtizongshu
3. IDS4有哪些功能
(1).身份认证服务(官方认证的OpenID Connect实现)
(2).单点登录与注销(SSO)
(3).访问受控的Api
4. IDS4的内部概念
(1).用户-User
使用已注册的客户端(指在id4中已经注册)访问资源的人。
(2).客户端-Client (即第三方应用)
客户端就是从identityserver请求令牌的软件(你可以理解为一个app即可),既可以通过身份认证令牌来验证识别用户身份,又可以通过授权令牌来访问服务端的资源。但是客户端首先必须在申请令牌前已经在identityserver服务中注册过。实际客户端不仅可以是Web应用程序,app或桌面应用程序(你就理解为pc端的软件即可),SPA,服务器进程等。
(3).资源-Resources
资源就是你想用identityserver保护的东西,可以是用户的身份数据或者api资源。每一个资源都有一个唯一的名称,客户端使用这个唯一的名称来确定想访问哪一个资源(在访问之前,实际identityserver服务端已经配置好了哪个客户端可以访问哪个资源,所以你不必理解为客户端只要指定名称他们就可以随便访问任何一个资源)
(4).身份令牌(d_token jwt)
一个身份令牌指的就是对认证过程的描述。它至少要标识某个用户(Called the sub aka subject claim)的主身份信息,和该用户的认证时间和认证方式。但是身份令牌可以包含额外的身份数据,具体开发者可以自行设定,但是一般情况为了确保数据传输的效率,开发者一般不做过多额外的设置,大家也可以根据使用场景自行决定。
(5).访问令牌(access_token oauth 2.0)
访问令牌允许客户端访问某个 API 资源。客户端请求到访问令牌,然后使用这个令牌来访问 API资源。访问令牌包含了客户端和用户(如果有的话,这取决于业务是否需要,但通常不必要)的相关信息,API通过这些令牌信息来授予客户端的数据访问权限。
5. IDS4的几种模式
(1).客户端模式:ClientCredentials
(2).用户名密码模式:ResourceOwnerPassword
(3).隐式模式(简化模式):implicit
(4).授权码模式:Code
除此之外,还有多种模式共存,比如: 客户端+用户名密码模式 ResourceOwnerPasswordAndClientCredentials
二. 客户端模式
一. 模式深究
1. 含义
指【客户端(也就是 第三方应用)】以自己的名义,而不是以用户的名义,向【服务提供商】的【认证服务器】进行认证。严格地说,客户端模式并不属于OAuth2.0 框架所要解决的问题。在这种模式中,【用户】直接向【客户端】注册,【客户端】以自己的名义要求【服务提供商】提供服务,其实不存在授权问题。
2. 运行流程
步骤:
A. 客户端(第三方应用)向认证服务器发送请求进行身份认证,并要求得到一个访问令牌Token。
B. 认证服务器确认无误后(认证),向客户端颁发访问令牌Token(授权)。
C. 客户端拿到访问令牌(token),向资源服务器发送请求,获取需要的信息。(上图中没有画)
二. 基于IDS4代码实操
1. 项目环境准备
(1). MyClient1:客户端控制台程序。
(2). PostMan工具:也充当客户端程序。
(3). ID4Test:认证+授权服务器.
(4). ProductService:资源服务器.
PS.几种授权模式都会产生token,这里我单纯的想使用一下token,那么我直接给业务服务器ProductService中的api接口增加校验,这个校验直接加在业务服务器上,仅仅是为了测试。(后面介绍加在Ocelot上)
2.搭建测试步骤
(一). IDS4认证授权服务器的配置
(1).通过Nuget给ID4Test安装【IdentityServer4 4.0.2】
(2).新建Config1配置类,包括两个方法:GetApiResources 和 GetClients. 其中GetApiResources里包含需要保护的Api业务服务器名称,GetClients里包含了哪些客户端资源可以访问,其中可以通过AllowedScopes = { "GoodsService", "ProductService" } 来授权哪个客户端能访问哪些api资源,例外还要配置 ClientId、校验方式(GrantTypes.ClientCredentials)、密钥
(3).Startup中的ConfigureService和Config的配置,如代码所示.
(4).通过命令启动项目【dotnet ID4Test.dll --urls="http://*:7040" --ip="127.0.0.1" --port=7040 】
配置类:
/// <summary> /// 客户端模式 /// </summary> public class Config1 { /// <summary> /// 配置Api范围集合 /// 4.x版本新增的配置 /// </summary> /// <returns></returns> public static IEnumerable<ApiScope> GetApiScopes() { return new List<ApiScope> { new ApiScope("GoodsService"), new ApiScope("OrderService"), new ApiScope("ProductService") }; } /// <summary> /// 需要保护的Api资源 /// 4.x版本新增后续Scopes的配置 /// </summary> /// <returns></returns> public static IEnumerable<ApiResource> GetApiResources() { List<ApiResource> resources = new List<ApiResource>(); //ApiResource第一个参数是ServiceName,第二个参数是描述 resources.Add(new ApiResource("GoodsService", "GoodsService服务需要保护哦") { Scopes = { "GoodsService" } }); resources.Add(new ApiResource("OrderService", "OrderService服务需要保护哦") { Scopes = { "OrderService" } }); resources.Add(new ApiResource("ProductService", "ProductService服务需要保护哦") { Scopes = { "ProductService" } }); return resources; } /// <summary> /// 可以使用ID4 Server 客户端资源 /// </summary> /// <returns></returns> public static IEnumerable<Client> GetClients() { List<Client> clients = new List<Client>() { new Client { ClientId = "client1",//客户端ID AllowedGrantTypes = GrantTypes.ClientCredentials, //验证类型:客户端验证 ClientSecrets ={ new Secret("0001".Sha256())}, //密钥和加密方式 AllowedScopes = { "GoodsService", "OrderService", "ProductService" } //允许访问的api服务 }, new Client { ClientId = "client2",//客户端ID AllowedGrantTypes = GrantTypes.ClientCredentials, //验证类型:客户端验证 ClientSecrets ={ new Secret("0002".Sha256())}, //密钥和加密方式 AllowedScopes = { "GoodsService" , "ProductService" } //允许访问的api服务 }, new Client { ClientId = "client3",//客户端ID AllowedGrantTypes = GrantTypes.ClientCredentials, //验证类型:客户端验证 ClientSecrets ={ new Secret("0003".Sha256())}, //密钥和加密方式 AllowedScopes = {"OrderService" } //允许访问的api服务 }, new Client { ClientId = "client4",//客户端ID AllowedGrantTypes = GrantTypes.ClientCredentials, //验证类型:客户端验证 ClientSecrets ={ new Secret("0004".Sha256())}, //密钥和加密方式 AllowedScopes = { "ProductService" }, //允许访问的api服务 //基于角色授权 Claims= { new ClientClaim("role","ypfRole") }, ClientClaimsPrefix="", //把前缀设置成空,就IDS4和Core MVC之间就不用转换了 } }; return clients; } }