IdentityServer4在Asp.Net Core中的应用(一)

    IdentityServer4是一套身份授权以及访问控制的解决方案,专注于帮助使用.Net 技术的公司为现代应用程序建立标识和访问控制解决方案,包括单点登录、身份管理、授权和API安全。

    下面我将具体介绍如何在.Net Core中实现OAuth授权,从最简单的授权模式开始,在上一篇对OAuth2.0的详细描述中,在客户端模式中,我们说它在严格意义上讲是不存在授权的问题,我们再来看下它的授权流程:

客户端在向授权服务器申请令牌后,授权服务器直接将令牌返回给了客户端,这个过程不需要其他角色的任何操作,只是客户端和授权服务器的交互。我们结合具体的示例来进一步了解这个过程。

    操作系统:Mac OS

    开发工具:VS Code

    调试工具:Postman

    开发框架:.Net Core 2.0

在具体示例实现之前,先说一下在VS Code我们会用到的插件,以方便我们的开发,毕竟VS Code没有我们宇宙第一IDE-Visual Studio那么强大,但是也是目前为止最好用的编辑器,它提供了各式各样的插件,几乎满足我们所有的开发需求。在这里我们用到的一个插件叫做Nuget Package Manager,这个插件可以方便我们使用快捷键对Nuget包进行管理。

    接下来我们首先创建一个授权服务器的项目,打开VS Code使用控制台,创建一个WebApi的项目,使用命令:

dotnet new WebApi -n IdentityServer4.Server

创建完成后,我们可以启动查看我们的项目,run一下:

这样我们的项目是可以运行成功的,下面我们进行添加IdentitServer4包的引用,在我们安装了Nuget Package Manager后,我们可以快速的使用快捷键,在Mac系统中使用command+p,然后输入">",然后输入Nuget... (注意一定要切换到当前的项目下)会出现以下提示:

选择第一个选项添加Package:

按回车,选择IdentityServer4最新版本的安装,这里是2.1.3,安装完后,我们在StartUp中添加IdentityServer4的引用,并使用AddIdentityServer()方法在依赖注入系统中注册IdentityServer,当然这里我们也可以等到添加完配置类后再进行操作。我们先添加一个配置类,叫做Config.cs,首先定义一个管道(Scope),指定我们所保护Api资源,该方法返回一个ApiResources集合,具体代码如下:new ApiResource("api","UsersApi"),第一个参数为Api的名称,第二个参数为显示的名称:

下一步进行客户端注册,定义给客户端可以返回的资源,即允许哪个Scope定义,代码如下:

下面我们将该配置注入到系统中,

AddDeveloperSigningCredential(),是一种RSA证书加密方式,它会生成一个tempkey.rsa证书文件,项目每次启动时,会检查项目根目录是否存在该证书文件,若不存在,则会生成该文件,否则会继续使用该证书文件。后面依次将ApiResources和Clients添加到内存中。

下一步是配置IdentityServer4的管道,在Configure里面添加,app.UseIdentityServer(),在这里我们用不到mvc,将app.UseMvc()注释掉即可。下面我们运行我们的项目,当然直接访问http://localhost:5000是看不到任何东西的,在这里我们使用一个固定的地址http://localhost:5000/.well-known/openid-configuration,可以查看IdentityServer4的配置信息,运行格式化后内容如下:

1{ 2 "issuer": "http://localhost:5000", 3 "jwks_uri": "http://localhost:5000/.well-known/openid-configuration/jwks", 4 "authorization_endpoint": "http://localhost:5000/connect/authorize", 5 "token_endpoint": "http://localhost:5000/connect/token", 6 "userinfo_endpoint": "http://localhost:5000/connect/userinfo", 7 "end_session_endpoint": "http://localhost:5000/connect/endsession", 8 "check_session_iframe": "http://localhost:5000/connect/checksession", 9 "revocation_endpoint": "http://localhost:5000/connect/revocation", 10 "introspection_endpoint": "http://localhost:5000/connect/introspect", 11 "frontchannel_logout_supported": true, 12 "frontchannel_logout_session_supported": true, 13 "backchannel_logout_supported": true, 14 "backchannel_logout_session_supported": true, 15 "scopes_supported": [ 16 "api", 17 "offline_access" 18 ], 19 "claims_supported": [], 20 "grant_types_supported": [ 21 "authorization_code", 22 "client_credentials", 23 "refresh_token", 24 "implicit" 25 ], 26 "response_types_supported": [ 27 "code", 28 "token", 29 "id_token", 30 "id_token token", 31 "code id_token", 32 "code token", 33 "code id_token token" 34 ], 35 "response_modes_supported": [ 36 "form_post", 37 "query", 38 "fragment" 39 ], 40 "token_endpoint_auth_methods_supported": [ 41 "client_secret_basic", 42 "client_secret_post" 43 ], 44 "subject_types_supported": [ 45 "public" 46 ], 47 "id_token_signing_alg_values_supported": [ 48 "RS256" 49 ], 50 "code_challenge_methods_supported": [ 51 "plain", 52 "S256" 53 ] 54}

这表明我们的IdentityServer已经配置成功,下面我们借助Postman模拟发起获取令牌请求,我们使用token_point的地址:http://localhost:5000/connect/token获取acces token,Postman配置如下:

上面指定的3个参数都是客户端模式需要指定的参数,下面就是我们请求到的access token。接着我们创建一个Api,去调用我们的授权服务器进行授权,重复上面的步骤,创建一个WebApi项目,不再赘述,直接去配置调用授权服务器,这个项目只是一个Api的项目,不需要完整的IdentityServer4的引用,只引用一个IdentityServer4.AccessTokenValidation包就可以了。在授权服务器中我们已经占用5000端口,所以在这个项目中我们指定为5001端口,在Program.cs里面指定5001端口,添加.UseUrls("http://localhost:5001"):

在ValuesController里面添加 Microsoft.AspNetCore.Authorization的引用,并添加[Authorize]标签,即要求该Controller要通过授权才可以访问,

下面我们在StartUp.cs里面去配置授权服务:

接着我们分别启动授权服务器和Api,我们运行Api,访问:http://localhost:5001/api/values ,访问结果如下:

提示Http Error 401 ,在状态码中401即未授权,我们把它拿到Postman中运行:

我们在Headers中指定Authorization 模式为Bearer,状态401 未授权,这个结果也是我们意料中的结果了,因为我们并未获取到令牌,我们继续使用Postman模拟获取到access token,

我们将获取到的access_token放到Api的Headers里面:

注意令牌与Bearer中间加空格,接下来继续请求:

这样我们就拿到了Api里面要获取的值了,到这里我们使用Postman验证了我们的结果,下面我们再创建一个第三方应用,去请求我们的Api资源,继续了解我们的授权流程,客户端我使用控制台程序进行测试。

我们继续使用命令行创建第三方应用,名称为ThirdPartyApplication,IdentityServer4有一个专门专门为客户端程序用的Nuget包,叫做IdentityModel,我们还是通过快捷键添加Nuget Package,下面直接上代码,必要说明会在代码中直接注释:

1using System; 2using System.Net.Http; 3using IdentityModel; 4using IdentityModel.Client; 5 6 7namespace ThirdPartyApplication 8{ 9 class Program 10 { 11 static void Main(string[] args) 12 { 13 //请求授权服务器 14 var diso=DiscoveryClient.GetAsync("http://localhost:5000").Result; 15 if(diso.IsError) 16 { 17 Console.WriteLine(diso.Error); 18 } 19 20 //授权服务器根据客户端发来的请求返回令牌 21 var tokenClient=new TokenClient(diso.TokenEndpoint,"Client","secret"); 22 var tokenResponse=tokenClient.RequestClientCredentialsAsync("api").Result; 23 if(tokenResponse.IsError) 24 { 25 Console.WriteLine(tokenResponse.Error); 26 } 27 //如果成功,则打印输出返回的令牌信息 28 else 29 { 30 Console.WriteLine(tokenResponse.Json); 31 } 32 33 //创建HttpClient对象 34 var httpClient=new HttpClient(); 35 36 //设置Authorization的Value值 37 httpClient.SetBearerToken(tokenResponse.AccessToken); 38 39 //根据授权服务器返回的令牌信息请求Api资源 40 var response= httpClient.GetAsync("http://localhost:5001/api/values").Result; 41 42 //如果返回结果为成功,输出Api资源的结果 43 if(response.IsSuccessStatusCode) 44 { 45 Console.WriteLine(response.Content.ReadAsStringAsync().Result); 46 } 47 } 48 } 49}

下面输出结果:

以上就是我们整个OAuth2.0授权模式中完整的客户端授权模式了,以上流程简化如下:

后面文章会继续讲解其他几种授权模式的使用。各位,晚安。

扫描二维码关注我的公众号,共同学习,共同进步!

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )