利用OpenID Connect添加用户认证

利用OpenID Connect添加用户认证

在这个示例中我们想要通过OpenID Connect协议将交互用户添加到我们的IdentityServer上面。

准备就绪后,我们会创建一个MVC的应用来使用IdentityServer做认证。

添加UI

关于该协议支持所需要的一切都内建到了IdentityServer中,你需要为登陆、登出、确认和错误等提供必要的UI页面。

虽然在每一个实现了IdentityServer的服务中它所实现的外观和工作流程等都是不一样的,我们提供了一个MVC模板,你可以将其作为起点。

可以从 Quickstart UI repo找到这个示例。你可以(使用github)克隆或者下载到你的桌面然后将控制器、视图、模型和Css样式表等放到你的应用里面。

你也可以在你的项目的根目录下面运行下面这个命令行(在powershell)进行自动的安装:

  1. iex ((New-Object System.Net.WebClient).DownloadString('https://raw.githubusercontent.com/IdentityServer/IdentityServer4.Quickstart.UI/release/get.ps1'))

一点你安装好了这些之后,你也需要在Startup类中配置好你的MVC,这需要在ConfigureService里面将MVC添加到DI中并在Configure方法中将MVC中间件添加到管道上。

  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddMvc();
  4.  
  5. // configure identity server with in-memory stores, keys, clients and scopes
  6. services.AddIdentityServer()
  7. .AddDeveloperSigningCredential()
  8. .AddInMemoryApiResources(Config.GetApiResources())
  9. .AddInMemoryClients(Config.GetClients())
  10. .AddTestUsers(Config.GetUsers());
  11. }

并且应该将MVC作为管道的最后一个中间件:

  1. public void Configure(IApplicationBuilder app, IHostingEnvironment env)
  2. {
  3. if (env.IsDevelopment())
  4. {
  5. app.UseDeveloperExceptionPage();
  6. }
  7.  
  8. app.UseIdentityServer();
  9.  
  10. app.UseStaticFiles();
  11. app.UseMvcWithDefaultRoute();
  12. }

readme可以看到更多的信息。

花费一些时间检查以下控制器和模型,你越了解他们,在后续的升级和改造过程中也会越容易。大多数代码都保存在一个QuickStart的文件夹中。如果这种方式不适合你的话,你可以自己修改成你要的风格。

创建一个MVC客户端

下一步你得创建一个MVC的应用。使用Asp.net core自带的模板就可以。不要配置认证信息。关于认证的信息需要你在应用里面自己配置。一旦你创建好应用后,将应用的端口号配置到5002上面。

为了添加对OpenID Connect认证的支持,需要在Startup类中的ConfigureService方法中进行如下的配置。

  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddMvc();
  4.  
  5. JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
  6.  
  7. services.AddAuthentication(options =>
  8. {
  9. options.DefaultScheme = "Cookies";
  10. options.DefaultChallengeScheme = "oidc";
  11. })
  12. .AddCookie("Cookies")
  13. .AddOpenIdConnect("oidc", options =>
  14. {
  15. options.SignInScheme = "Cookies";
  16.  
  17. options.Authority = "http://localhost:5000";
  18. options.RequireHttpsMetadata = false;
  19.  
  20. options.ClientId = "mvc";
  21. options.SaveTokens = true;
  22. });
  23. }

AddAuthentication 方法将认证服务添加到了DI系统中,我们使用了一个cookie作为认证用户的主要手段(通过options.DefaultScheme=“Cookies”来指定)。我们将DefaultChallengeScheme设置成“oidc”使用为当我们需要用户登陆的时候,我们要使用OpenID Connect的scheme。

然后我们使用AddCookie方法添加一个对应的处理Cookie的handler(对应于options.DefaultScheme=“”Cookies“这个配置)。

最后,AddOpenIdConnect方法配置了相应的handler(对应于options.DefaultChallengeScheme=”oidc”)来执行OpenID Connect协议。Authority指定了我们要新人的IdentityServer;然后通过ClientId标志了客户端;SiginScheme=“Cookies“这个表示当OpenId Connect协议执行完成之后会使用cookie handler来发布cookie。

此外,我们关闭了JWT claim的类型映射以允许OpenId Connect中的claim类型。

  1. JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
  1. 然后为了认证服务会在每个请求中都执行,需要在Startup类中的Configure方法中配置认证的中间件:
  1. public void Configure(IApplicationBuilder app, IHostingEnvironment env)
  2. {
  3. if (env.IsDevelopment())
  4. {
  5. app.UseDeveloperExceptionPage();
  6. }
  7. else
  8. {
  9. app.UseExceptionHandler("/Home/Error");
  10. }
  11.  
  12. app.UseAuthentication();
  13.  
  14. app.UseStaticFiles();
  15. app.UseMvcWithDefaultRoute();
  16. }

认证中间件应该放在MVC的前面。

最后一步是要触发认证。我们需要在home控制器上面添加[Autorize]特性。同时修改一下about页面:

  1. <dl>
  2. @foreach (var claim in User.Claims)
  3. {
  4. <dt>@claim.Type</dt>
  5. <dd>@claim.Value</dd>
  6. }
  7. </dl>

如果你现在使用浏览器访问了刚才配置好的控制器的路径,那么会有一个重定向发送到IdentityServer。这回导致一个错误因为MVC客户端还没有注册到Identityserver。

添加对OpenID Connect Identity Scopes的支持

和OAuth2.0相似的是,OpenID Connect同样使用了scopes这个概念。再一次声明:scopes代表了你想要保护的,同时,也是客户端想要访问的那种东西。与OAuth对比一下,scopes在OIDC中并不代表APIs,而是代表了用户的数据,比如user id、name或者email等。

在这里阐述一下:scopes在OIDC里面是和claim挂钩的,他们之间的关系是1对多。打个比方,profile里面包含了许多的claim,包括first_name last_name等等。。

在Config类中添加一个帮助方法,这个方法创建了一个IdentityResource的集合,它添加了对标准openid(subject id)和profile(用户的名、姓等等)scopes的支持。

  1. public static IEnumerable<IdentityResource> GetIdentityResources()
  2. {
  3. return new List<IdentityResource>
  4. {
  5. new IdentityResources.OpenId(),
  6. new IdentityResources.Profile(),
  7. };
  8. }

所有标准scopes对应的claims都能在specification找到。

然后你得将上面配置好的添加到ConfgureService方法中,使用AddInmemoryIdentityResource:

  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddMvc();
  4.  
  5. // configure identity server with in-memory stores, keys, clients and scopes
  6. services.AddIdentityServer()
  7. .AddDeveloperSigningCredential()
  8. .AddInMemoryIdentityResources(Config.GetIdentityResources())
  9. .AddInMemoryApiResources(Config.GetApiResources())
  10. .AddInMemoryClients(Config.GetClients())
  11. .AddTestUsers(Config.GetUsers());
  12. }

添加一个客户端用于演示OpenID Connect的隐式流程

最后一步是在IdentityServer中为MVC客户端添加一个新的入口。

在IdentitySErver中配置基于OpenId Connect的客户端和配置OAuth2.0的客户端有些相似。但是因为在OpenID Connect中经常会有交互发生,所有我们需要在配置中添加一写重定向。

在客户端配置的代码中写入如下:

  1. public static IEnumerable<Client> GetClients()
  2. {
  3. return new List<Client>
  4. {
  5. // other clients omitted...
  6.  
  7. // OpenID Connect implicit flow client (MVC)
  8. new Client
  9. {
  10. ClientId = "mvc",
  11. ClientName = "MVC Client",
  12. AllowedGrantTypes = GrantTypes.Implicit,
  13.  
  14. // where to redirect to after login
  15. RedirectUris = { "http://localhost:5002/signin-oidc" },
  16.  
  17. // where to redirect to after logout
  18. PostLogoutRedirectUris = { "http://localhost:5002/signout-callback-oidc" },
  19.  
  20. AllowedScopes = new List<string>
  21. {
  22. IdentityServerConstants.StandardScopes.OpenId,
  23. IdentityServerConstants.StandardScopes.Profile
  24. }
  25. }
  26. };
  27. }

测试客户端

现在终于都办妥了。

导航到被保护的控制器上以便触发认证,这时你会发现被重定向到了IdentitySErver上的登陆页面:

登陆成功后,会给用户呈现一个确认页面。在这里用户可以决定他是否要将一些访问资源的权限交给客户端。

确认页面可以在配置中的RequireConsent属性上取消。

最终页面会跳转到客户端应用上,展示用户的claim。

添加登出

在添加一个登出的功能吧。

使用像identity server这样的身份验证服务,只需要清除本地应用程序cookie就不够了。此外,你还需要对身份服务器进行一次往返,以清除中心单点登录会话。

确切的协议步骤是在OpenID Connect中间件中实现的,只需将以下代码添加到某个控制器中以触发信号:

  1. public async Task Logout()
  2. {
  3. await HttpContext.SignOutAsync("Cookies");
  4. await HttpContext.SignOutAsync("oidc");
  5. }

这将会清除本地的cookie然后重定向到Identityserver。Identtiyserver会清除它的Cookie然后给用户一个返回MVC应用的链接。

进一步的尝试

就像上面提到的,OpenId Connect中间件默认会请求profile scope。这个scope中包含了诸如name website等claim。

将这些claim添加到TestUser上面,这样一来IdentityServer可以将他们放到Id token里面:

  1. public static List<TestUser> GetUsers()
  2. {
  3. return new List<TestUser>
  4. {
  5. new TestUser
  6. {
  7. SubjectId = "",
  8. Username = "alice",
  9. Password = "password",
  10.  
  11. Claims = new []
  12. {
  13. new Claim("name", "Alice"),
  14. new Claim("website", "https://alice.com")
  15. }
  16. },
  17. new TestUser
  18. {
  19. SubjectId = "",
  20. Username = "bob",
  21. Password = "password",
  22.  
  23. Claims = new []
  24. {
  25. new Claim("name", "Bob"),
  26. new Claim("website", "https://bob.com")
  27. }
  28. }
  29. };
  30. }

下一次你再认证的时候,你的展示claims的页面就会展示这些额外的claim了。

试着任意添加一些claim,或者更多的scopes。在OpenId Connect中间件中的Scope属性上面进行的配置会决定你发送到IdentityServer的认证请求中会包含那些scopes:

  1. services.AddAuthentication(option =>
  2.  
  3. {
  4.  
  5. option.DefaultScheme = "cookies";
  6.  
  7. option.DefaultChallengeScheme = "oidc";
  8.  
  9. }).AddCookie("cookies").AddOpenIdConnect("oidc", option =>
  10.  
  11. {
  12.  
  13. option.Scope.Add("somescope");//这句
  14.  
  15. });

同样值得注意的是,检索令牌的claim是一个可扩展点----IProfileService。因为我们使用AddTestUsers,TestUserProfileService是默认被使用的。你可以检查源代码here 来看看它是如何工作的。

IdentityServer4【QuickStart】之利用OpenID Connect添加用户认证的更多相关文章

  1. .NET Core IdentityServer4实战 第二章-OpenID Connect添加用户认证

    内容:本文带大家使用IdentityServer4进行使用OpenID Connect添加用户认证 作者:zara(张子浩) 欢迎分享,但需在文章鲜明处留下原文地址. 在这一篇文章中我们希望使用Ope ...

  2. asp.net core系列 56 IS4使用OpenID Connect添加用户认证

    一.概述 在前二篇中讲到了客户端授权的二种方式: GrantTypes.ClientCredentials凭据授权和GrantTypes.ResourceOwnerPassword密码授权,都是OAu ...

  3. ASP.NET Core的身份认证框架IdentityServer4(9)-使用OpenID Connect添加用户认证

    OpenID Connect OpenID Connect 1.0是OAuth 2.0协议之上的一个简单的身份层. 它允许客户端基于授权服务器执行的身份验证来验证最终用户的身份,以及以可互操作和类似R ...

  4. IdentityServer4 中文文档 -11- (快速入门)添加基于 OpenID Connect 的用户认证

    IdentityServer4 中文文档 -11- (快速入门)添加基于 OpenID Connect 的用户认证 原文:http://docs.identityserver.io/en/releas ...

  5. IdentityServer4 使用OpenID Connect添加用户身份验证

    使用IdentityServer4 实现OpenID Connect服务端,添加用户身份验证.客户端调用,实现授权. IdentityServer4 目前已更新至1.0 版,在之前的文章中有所介绍.I ...

  6. 【转载】IdentityServer4 使用OpenID Connect添加用户身份验证

    使用IdentityServer4 实现OpenID Connect服务端,添加用户身份验证.客户端调用,实现授权. IdentityServer4 目前已更新至1.0 版,在之前的文章中有所介绍.I ...

  7. IdentityServer4(9)- 使用OpenID Connect添加用户身份验证(implicit)

    本文为 OpenID Connect 简化模式(implicit) 已更新至.NET Core 2.2 在本快速入门中,我们希望通过 OpenID Connect 协议向我们的 IdentitySer ...

  8. Identity Server 4使用OpenID Connect添加用户身份验证(三)

    一.说明 基于上一篇文章中的代码进行继续延伸,只需要小小的改动即可,不明白的地方可以先看看本人上一篇文章及源码: Identity Server 4资源拥有者密码认证控制访问API(二) GitHub ...

  9. 第11章 使用OpenID Connect添加用户身份验证 - Identity Server 4 中文文档(v1.0.0)

    在本快速入门中,我们希望通过OpenID Connect协议向我们的IdentityServer添加对交互式用户身份验证的支持. 一旦到位,我们将创建一个将使用IdentityServer进行身份验证 ...

随机推荐

  1. S/4 HANA中的MATDOC和MATDOC_EXTRACT

    最近做了销售和物料管理方面的一些需求,因此对S/4中的MM的数据模型有了一定的了解.目前网络已经有一些介绍物料凭证表MATDOC的文章,内容好像不是很详细,另外也没发现介绍库存变更数据表MATDOC_ ...

  2. 【大数据技术】操作系统和Hadoop版本选择

    1.操作系统选择 Hadoop产品是由Java语言开发的,所以推荐的是Linux操作系统,理由很简单开源免费,推荐的操作系统CentOS. CentOS是一个基于Red Hat 企业级 Linux 提 ...

  3. props default 数组/对象的默认值应当由一个工厂函数返回

    export default {props: { slides:{ type:Array, default:[] } },这是我的代码 报错是Invalid default value for pro ...

  4. python 列表 元祖

    # # 1,写代码,有如下列列表,按照要求实现每⼀一个功能li = ["alex", "WuSir", "ritian", "ba ...

  5. 刚学习java时的笔记, 有点渣, 毕竟都是从低往高走

    一片很有意义的论文: 写给那些在技术路上奔跑的人们!!!!! http://blog.csdn.net/xqhrs232/article/details/24885971 乱码处理 1.get处理 解 ...

  6. 四、Oracle 序列、常用函数、多表连接

    一.序列定义:是oracle数据库专门用来产生连续且自动增长的数字的对象创建语法:create sequence 序列名(sq_表名) nocache(无缓存) create sequence sq_ ...

  7. pytorch torch.Storage学习

    tensor分为头信息区(Tensor)和存储区(Storage) 信息区主要保存着tensor的形状(size).步长(stride).数据类型(type)等信息,而真正的数据则保存成连续数组,存储 ...

  8. 初学Python——集合及其运算

    一.集合定义及其功能 集合是一个无序的.不重复的数据组合,和字典列表一样也是一种数据类型. 集合两个最主要的功能:①去重(把一个列表变成集合,就自动去重了) ②关系测试(测试两组数据之间的交.并.差集 ...

  9. vector--不定长数组

    (一些很基础的东西) vector就是一个不定长数组 vector<int>a (黄色部分可替换) a.size() 读取它的大小 a.resize() 改变大小 a.push_back( ...

  10. Python脱产8期 Day08 2019/4/22

    一.三种字符串 1.普通字符串:u'以字符作为输出单位‘  #print(u‘abc’)#用于显示 2.二进制字符串:b'以字节作为输出单位’#用于传输 3.原义字符串:r‘以字符作为输出单位,原样输 ...