IdentityServer4-EF动态配置Client和对Claims授权(二)

原文:IdentityServer4-EF动态配置Client和对Claims授权(二)

本节介绍Client的ClientCredentials客户端模式,先看下画的草图:

一、在Server上添加动态新增Client的API 接口。

为了方便测试,在Server服务端中先添加swagger,添加流程可参考:https://www.cnblogs.com/suxinlcq/p/6757556.html

在ValuesController控制器中注入ConfigurationDbContext上下文,此上下文可用来加载或配置IdentityServer4.EntityFramework的Client、身份信息、API资源信息或CORS数据等。

在ValuesController中实添加以下代码:

        private ConfigurationDbContext _context;public ValuesController(ConfigurationDbContext context){_context = context;}

添加动态新增Client的API接口:

        [HttpPost]public IActionResult Post([FromBody] IdentityServer4.EntityFramework.Entities.Client client){var res = _context.Clients.Add(client);if(_context.SaveChanges() >0)return Ok(true);elsereturn Ok(false);}

控制器代码如下:


二、对Server上的API进行保护

(1)安装IdentityServer4.AccessTokenValidation包

(2)在startup.cs中ConfigureServices方法添加如下代码:

            //protect API
            services.AddMvcCore().AddAuthorization().AddJsonFormatters();services.AddAuthentication("Bearer").AddIdentityServerAuthentication(options =>{options.Authority = "http://localhost:5000";options.RequireHttpsMetadata = false;options.ApiName = "api1";});

AddAuthentication把Bearer配置成默认模式,将身份认证服务添加到DI中。

AddIdentityServerAuthentication把IdentityServer的access token添加到DI中,供身份认证服务使用。

(3)在startup.cs中Configure方法添加如下代码:

      public void Configure(IApplicationBuilder app, IHostingEnvironment env){//if (env.IsDevelopment())//{//    app.UseDeveloperExceptionPage();//}//AddSwagger
            app.UseSwagger();app.UseSwaggerUI(c =>{c.SwaggerEndpoint("/swagger/v1/swagger.json", "Server接口文档");});InitializeDatabase(app);app.UseAuthentication();app.UseIdentityServer();app.UseMvc();}

UseAuthentication将身份验证中间件添加到管道中,以便在每次调用主机时自动执行身份验证。

(4)在ValuesController控制器中添加[Authorize]

(5)在项目属性->调试 中,启动浏览器,并设成swagger,如图:

(6)启动项目,并调用第一个Get接口。

显示Unauthorized(未授权),证明[Authorize]起作用了。


三、搭建Client客户端

(1)新建一个控制台程序,安装IdentityModel包

(2)添加类IDSHelper.cs,添加客户端请求API接口代码。

public class IDSHelper{public static async Task MainAsync(){try{DiscoveryResponse disco = await DiscoveryClient.GetAsync("http://localhost:5000");if (disco.IsError){Console.WriteLine(disco.Error);return;}TokenClient tokenClient = new TokenClient(disco.TokenEndpoint, "Client", "secret");var tokenResponse = await tokenClient.RequestClientCredentialsAsync("api1");if (tokenResponse.IsError){Console.WriteLine(tokenResponse.Error);return;}Console.WriteLine(tokenResponse.Json);var client = new HttpClient();client.SetBearerToken(tokenResponse.AccessToken);var response = await client.GetAsync("http://localhost:5000/api/values/");if (!response.IsSuccessStatusCode){Console.WriteLine(response.StatusCode);}else{var content = await response.Content.ReadAsStringAsync();Console.WriteLine(content);}}catch (Exception ex){}}
}

(3)修改Program.cs代码,如下:

class Program{static void Main(string[] args)=> IDSHelper.MainAsync().GetAwaiter().GetResult();}

(4)按Ctrl+F5,可以获取到access token和接口返回值

复制token,用postman调用,成功获取到了接口返回值。


四、测试动态新增Client接口

安装IdentityServer4包。

安装IdentityServer4.EntityFramework包。

在IDSHelper.cs类中添加Post方法:

public static async Task Post(){try{DiscoveryResponse disco = await DiscoveryClient.GetAsync("http://localhost:5000");if (disco.IsError){Console.WriteLine(disco.Error);return;}TokenClient tokenClient = new TokenClient(disco.TokenEndpoint, "Client", "secret");var tokenResponse = await tokenClient.RequestClientCredentialsAsync("api1");if (tokenResponse.IsError){Console.WriteLine(tokenResponse.Error);return;}Console.WriteLine(tokenResponse.Json);var client = new HttpClient();client.SetBearerToken(tokenResponse.AccessToken);Client c1 = new Client{ClientId = "Test",AllowedGrantTypes = GrantTypes.ClientCredentials,ClientSecrets ={new Secret("secret".Sha256())},AllowedScopes = { "api1" }};string strJson = JsonConvert.SerializeObject(c1 .ToEntity());HttpContent content = new StringContent(strJson);content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");//由HttpClient发出Post请求Task<HttpResponseMessage> response = client.PostAsync("http://localhost:5000/api/values/", content);if (response.Result.StatusCode != System.Net.HttpStatusCode.OK){Console.WriteLine(response.Result.StatusCode);}else{Console.WriteLine(response.Result.Content.ReadAsStringAsync().Result);}}catch (Exception ex){}}

顺便把main中改成对Post调用:

static void Main(string[] args)=> IDSHelper.Post().GetAwaiter().GetResult();

按Ctrl+F5,调用新增Client的接口,并成功返回true。

同时可以在数据库中的Client表找到相关记录。需要注意的是,不能添加相同Client ID的Client。


五、在Client中添加Claim信息,并在API接口中对Claim信息进行验证。

关于Claim的介绍可以看这篇文章:http://www.cnblogs.com/stulzq/p/8726002.html

这里把Claim简单当做用户的身份信息使用,修改Post方法里面的Client:

                Client c1 = new Client{ClientId = "superAdmin",AllowedGrantTypes = GrantTypes.ClientCredentials,ClientSecrets ={new Secret("secret".Sha256())},AllowedScopes = { "api1" },Claims = new List<Claim>{new Claim(JwtClaimTypes.Role, "admin")}};

可以看出,Claims为List,可以是很多个角色,这里只添加一个。

Ctrl+F5,运行成功添加superAdmin Client。

现在,需要对Server服务端的新增Client接口进行Claim身份验证,添加如下代码:

[Authorize(Roles ="admin")]

然后再客户端修改授权的账号为superadmin。

TokenClient tokenClient = new TokenClient(disco.TokenEndpoint, "superAdmin", "secret");

Ctrl+F5运行

问题出现了,返回了Forbidden,没有权限进行访问。

这时候我们上官网查阅了资料,发现在添加Client的Claim时候,IdentityServer EntityFramework会为Claim的role添加一个默认前缀,为client_。所以,实际上它为client_role。

而服务端只能对role进行验证。

此时我们需要把Claim的默认前缀去掉,设置为空ClientClaimsPrefix = "" 。

去掉Server的Role验证,添加形如下面代码的Client。

Client c1 = new Client{ClientId = "adminClient",AllowedGrantTypes = GrantTypes.ClientCredentials,ClientSecrets ={new Secret("secret".Sha256())},AllowedScopes = { "api1" },Claims = new List<Claim>{new Claim(JwtClaimTypes.Role, "admin")},ClientClaimsPrefix = "" //把client_ 前缀去掉};

Ctrl+F5,运行成功添加adminClient Client,这次的是Role为admin。

然后重新再Server服务端加上[Authorize(Roles ="admin")]

同时修改验证账号为adminClient。

TokenClient tokenClient = new TokenClient(disco.TokenEndpoint, "adminClient", "secret");

最后运行程序,成功地在[Authorize(Roles ="admin")]权限下访问并新增了Client。


六、需要注意的问题

(1)新增Client到数据库时候,这里需要接收IdentityServer4.EntityFramework.Entities.Client

而不是IdentityServer4.Models.Client,否则API接口在接收和转化Client模型的时候会报错。

(2)此外,本节介绍的Client的AllowedGrantTypes 都为 GrantTypes.ClientCredentials,相应的,客户端请求是,需要用RequestClientCredentialsAsync方法。

最后再次提下,ClientCredentials模式的适用场景:用于和用户无关,服务与服务之间直接交互访问资源。


Server服务端源码地址:https://github.com/Bingjian-Zhu/Server

Client客户端源码地址:https://github.com/Bingjian-Zhu/Client

文中如有错漏,欢迎指正。

posted on 2018-12-30 13:32 NET未来之路 阅读(...) 评论(...) 编辑 收藏

转载于:https://www.cnblogs.com/lonelyxmas/p/10199198.html

IdentityServer4-EF动态配置Client和对Claims授权(二)相关推荐

  1. IdentityServer4-从数据库获取User登录并对Claims授权验证(五)

    本节将在第四节基础上介绍如何实现IdentityServer4从数据库获取User进行验证,并对Claim进行权限设置. 一.新建Web API资源服务,命名为ResourceAPI (1)新建API ...

  2. IdentityServer4-MVC+Hybrid实现Claims授权验证(四)

    上节IdentityServer4-客户端的授权模式原理分析(三)以对话形式,大概说了几种客户端授权模式的原理,这节重点介绍Hybrid模式在MVC下的使用.且为实现IdentityServer4从数 ...

  3. kafka原理_Kafka动态配置实现原理解析

    总 第19篇 2019年 第15篇 一.问题导读Apache Kafka在全球各个领域各大公司获得广泛使用,得益于它强大的功能和不断完善的生态.其中Kafka动态配置是一个比较高频好用的功能,下面我们 ...

  4. nginx动态配置及服务发现那些事

    标题,  <闲聊nginx动态配置及服务发现的那些事> - 这次的准备闲聊关于nginx服务发现的话题,  按照我以往写文章的性子,估计会迁移一些主题.  毕竟单纯聊nginx和动态服务发 ...

  5. ABP动态配置数据库连接字符串 Oracle11g数据库

    ABP动态配置数据库连接 Oracle11g数据库 ABP的仓储关于数据库连接字符串的配置是从web.config(app.config)的connectionStrings读取的. 我想实现的功能是 ...

  6. ZooKeeper Dynamic Reconfiguration(ZooKeeper 动态配置重构)

    Overview 概览 Prior to the 3.5.0 release, the membership and all other configuration parameters of Zoo ...

  7. Nacos的动态配置源码解析

    文章目录 1. 如何使用 2. 原理详解 2.1 采用延迟线程池定时执行"监听"文件是否有修改 2.2 通过长轮询的方式获得修改过的文件及其内容 2.3 拿到配置后通过applic ...

  8. springboot整合Quartz实现动态配置定时任务

    版权声明:本文为博主原创文章,转载请注明出处. https://blog.csdn.net/liuchuanhong1/article/details/60873295 前言 在我们日常的开发中,很多 ...

  9. Spring Boot 整合 Quartz 实现 Java 定时任务的动态配置

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 首先说下这次主题,动态配置.没接触过定时任务的同学可以先看 ...

最新文章

  1. Redis为什么又引入了多线程?单线程不香了?
  2. CentOS7安装和配置samba
  3. POJ 3061 -- Subsequence(二分)
  4. Hadoop系列(三)MapReduce Job的几种提交运行模式
  5. 2006年4月全国计算机等级考试二级Java语言程序设计
  6. 针对故障场景的血液,汗液和书写自动集成测试
  7. scala重载无参构造方法_Scala中的无参数方法
  8. Android蓝牙A2DP连接实现
  9. 启动程序端口被占用Address already in use: bind解决方案
  10. redirect()重新定向·
  11. WPS简历模板的图标怎么修改_新媒体运营-简历模板范文,【工作经历+项目经验+自我评价】怎么写?...
  12. 全量、增量 数据抽取 同步
  13. tomcat 窗口中文乱码解决
  14. Linux命令行运行多线程程序 和 QT集成IDE下运行多线程程序的问题。
  15. 以前看的关于物联网的总结
  16. 网络攻防--网络防御技术(一)
  17. 欢迎进入GeekYang博客导航一站式搜索(所有博客的汇总帖)
  18. Python-正则表达式
  19. orbslam2稠密地图转octomap
  20. matlab绘制单摆相图,单摆运动―相图.ppt

热门文章

  1. 实习的第一天——培训
  2. Python3 模块 -- Fabric自动化模版
  3. 8月21日至8月27日技术积累
  4. 单片机入门-矩阵键盘控制数码管显示
  5. 关于数据库SQL优化
  6. 福布斯2015中国非上市潜力企业100强
  7. PowerDesigner中使用vbscript访问对象进行批量操作
  8. OpenCV中CvArr* 的含义~
  9. SpringCloud Config简介
  10. k8s redis集群_基于K8S部署redis哨兵集群