前言:

 前面介绍了IdentityServer4 的简单应用,本篇将继续讲解IdentityServer4 的各种授权模式使用示例

授权模式:

 环境准备

 a)调整项目结构如下:

  

 b)调整cz.IdentityServer项目中Statup文件如下 

  1. public class Startup
  2. {
  3. public void ConfigureServices(IServiceCollection services)
  4. {
  5. services.AddControllersWithViews();
  6.  
  7. services.Configure<CookiePolicyOptions>(options =>
  8. {
  9. options.MinimumSameSitePolicy = SameSiteMode.Strict;
  10. });
  11.  
  12. services.AddIdentityServer()
  13. .AddDeveloperSigningCredential()
  14. //api资源
  15. .AddInMemoryApiResources(InMemoryConfig.GetApiResources())
  16. //4.0版本需要添加,不然调用时提示invalid_scope错误
  17. .AddInMemoryApiScopes(InMemoryConfig.GetApiScopes())
  18. .AddTestUsers(InMemoryConfig.Users().ToList())
  19. .AddInMemoryIdentityResources(InMemoryConfig.GetIdentityResourceResources())
  20. .AddInMemoryClients(InMemoryConfig.GetClients());
  21. }
  22.  
  23. // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
  24. public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
  25. {
  26. if (env.IsDevelopment())
  27. {
  28. app.UseDeveloperExceptionPage();
  29. }
  30.  
  31. app.UseRouting();
  32.  
  33. app.UseStaticFiles();
  34. app.UseCookiePolicy();
  35. app.UseIdentityServer();
  36.  
  37. app.UseAuthentication();
  38. //使用默认UI,必须添加
  39. app.UseAuthorization();
  40.  
  41. app.UseEndpoints(endpoints =>
  42. {
  43. endpoints.MapControllerRoute(name: "default", pattern: "{controller=Home}/{action=Index}/{id?}");
  44. });
  45.   }
    }

 c)在cz.Api.Order项目中添加控制器:IdentityController

  1. namespace cz.Api.Order.Controllers
  2. {
  3. [Route("identity")]
  4. [ApiController]
  5. [Authorize]
  6. public class IdentityController : ControllerBase
  7. {
  8. [HttpGet]
  9. public IActionResult Get()
  10. {
  11. return new JsonResult(from c in User.Claims select new { c.Type, c.Value });
  12. }
  13. }
  14. }

 1、客户端模式

  a)在InMemoryConfigGetClients方法中添加客户端:

  1. new Client
  2. {
  3. ClientId = "credentials_client", //访问客户端Id,必须唯一
  4. ClientName = "ClientCredentials Client",
  5. //使用客户端授权模式,客户端只需要clientid和secrets就可以访问对应的api资源。
  6. AllowedGrantTypes = GrantTypes.ClientCredentials,
  7. ClientSecrets =
  8. {
  9. new Secret("secret".Sha256())
  10. },
  11. AllowedScopes = {
  12. IdentityServerConstants.StandardScopes.OpenId,
  13. IdentityServerConstants.StandardScopes.Profile,
  14. "goods"
  15. },
  16. },

  b)在cz.ConsoleClient项目中安装Nuget包:IdentityModel,在Program中添加如下方法:

  1. /// <summary>
  2. /// 客户端认证模式
  3. /// </summary>
  4. private static void ClientCredentials_Test()
  5. {
  6. Console.WriteLine("ClientCredentials_Test------------------->");
  7. var client = new HttpClient();
  8. var disco = client.GetDiscoveryDocumentAsync("http://localhost:5600/").Result;
  9. if (disco.IsError)
  10. {
  11. Console.WriteLine(disco.Error);
  12. return;
  13. }
  14. //请求token
  15. var tokenResponse = client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
  16. {
  17. Address = disco.TokenEndpoint,
  18. ClientId = "credentials_client",
  19. ClientSecret = "secret",
  20. Scope = "goods"
  21. }).Result;
  22.  
  23. if (tokenResponse.IsError)
  24. {
  25. Console.WriteLine(tokenResponse.Error);
  26. return;
  27. }
  28.  
  29. Console.WriteLine(tokenResponse.Json);
  30. //调用认证api
  31. var apiClient = new HttpClient();
  32. apiClient.SetBearerToken(tokenResponse.AccessToken);
  33.  
  34. var response = apiClient.GetAsync("http://localhost:5601/identity").Result;
  35. if (!response.IsSuccessStatusCode)
  36. {
  37. Console.WriteLine(response.StatusCode);
  38. }
  39. else
  40. {
  41. var content = response.Content.ReadAsStringAsync().Result;
  42. Console.WriteLine(content);
  43. }
  44. }

  运行该程序结果如下:

  

 2、密码模式

  a)在InMemoryConfigGetClients方法中添加客户端:

  1. new Client
  2. {
  3. ClientId = "password_client",
  4. ClientName = "Password Client",
  5. ClientSecrets = new [] { new Secret("secret".Sha256()) },
  6. //这里使用的是通过用户名密码换取token的方式.
  7. AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
  8. AllowedScopes = {
  9. IdentityServerConstants.StandardScopes.OpenId,
  10. IdentityServerConstants.StandardScopes.Profile,
  11. "order","goods",
  12. }
  13. },

  b)cz.ConsoleClient项目继续在Program中添加如下方法:

  1. /// <summary>
  2. /// 用户名密码模式
  3. /// </summary>
  4. public static void ResourceOwnerPassword_Test()
  5. {
  6. Console.WriteLine("ResourceOwnerPassword_Test------------------->");
  7. // request token
  8. var client = new HttpClient();
  9. var disco = client.GetDiscoveryDocumentAsync("http://localhost:5600/").Result;
  10. var tokenResponse = client.RequestPasswordTokenAsync(new PasswordTokenRequest()
  11. {
  12. Address = disco.TokenEndpoint,
  13. ClientId = "password_client",
  14. ClientSecret = "secret",
  15. UserName = "cba",
  16. Password = "cba",
  17. Scope = "order goods",
  18. }).Result;
  19.  
  20. if (tokenResponse.IsError)
  21. {
  22. Console.WriteLine(tokenResponse.Error);
  23. return;
  24. }
  25. Console.WriteLine(tokenResponse.Json);
  26. // call api
  27. var apiClient = new HttpClient();
  28. client.SetBearerToken(tokenResponse.AccessToken);
  29. var response = apiClient.GetAsync("http://localhost:5601/identity").Result;
  30. if (!response.IsSuccessStatusCode)
  31. {
  32. Console.WriteLine(response.StatusCode);
  33. }
  34. else
  35. {
  36. var content = response.Content.ReadAsStringAsync().Result;
  37. Console.WriteLine(content);
  38. }
  39. }

  运行该程序结果同上:  

 3、简化模式

  a)在InMemoryConfigGetClients方法中添加客户端:

  1. new Client
  2. {
  3. ClientId = "implicit_client",
  4. ClientName = "Implicit Client",
  5. ClientSecrets = new [] { new Secret("secret".Sha256()) },
  6. AllowedGrantTypes = GrantTypes.Implicit,
  7. AllowedScopes = {
  8. "order","goods",
  9. IdentityServerConstants.StandardScopes.OpenId,
  10. IdentityServerConstants.StandardScopes.Profile
  11. },
  12. RedirectUris = { "http://localhost:5021/signin-oidc" },
  13. PostLogoutRedirectUris = { "http://localhost:5021" },
  14. //是否显示授权提示界面
  15. RequireConsent = true,
  16. },

  b)调整在cz.MVCClient中Statup文件中内容如下:

  1. public class Startup
  2. {
  3. public Startup(IConfiguration configuration)
  4. {
  5. Configuration = configuration;
  6. }
  7.  
  8. public IConfiguration Configuration { get; }
  9.  
  10. // This method gets called by the runtime. Use this method to add services to the container.
  11. public void ConfigureServices(IServiceCollection services)
  12. {
  13. services.Configure<CookiePolicyOptions>(options =>
  14. {
  15.   // This lambda determines whether user consent for non-essential cookies is needed for a given request.
  16.   options.CheckConsentNeeded = context => true;
  17. options.MinimumSameSitePolicy = SameSiteMode.Lax;
  18. });
  19.  
  20. JwtSecurityTokenHandler.DefaultMapInboundClaims = false;
  21.  
  22. services.AddControllersWithViews();
  23.  
  24. services.AddAuthentication(options =>
  25. {
  26. options.DefaultScheme = "Cookies";
  27. options.DefaultChallengeScheme = "oidc";
  28. })
  29. .AddCookie("Cookies")
  30. .AddOpenIdConnect("oidc", options =>
  31. {
  32. options.RequireHttpsMetadata = false;
  33. options.Authority = "http://localhost:5600";
  34. options.ClientId = "implicit_client";
  35. options.ClientSecret = "secret";
  36. });
  37. }
  38.  
  39. // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
  40. public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
  41. {
  42. if (env.IsDevelopment())
  43. {
  44. app.UseDeveloperExceptionPage();
  45. }
  46. else
  47. {
  48. app.UseExceptionHandler("/Home/Error");
  49. }
  50. app.UseStaticFiles();
  51. app.UseCookiePolicy();
  52.  
  53. app.UseRouting();
  54.  
  55. app.UseAuthentication();
  56. app.UseAuthorization();
  57.  
  58. app.UseEndpoints(endpoints =>
  59. {
  60. endpoints.MapControllerRoute(
  61. name: "default",
  62. pattern: "{controller=Home}/{action=Index}/{id?}");
  63. });
  64. }
  65. }

  c)在cz.MVCClient中添加Nuget包:IdentityServer4.AccessTokenValidation、Microsoft.AspNetCore.Authentication.OpenIdConnect;在HomeController中添加方法:

  1. [Authorize]
  2. public IActionResult Secure()
  3. {
  4. ViewData["Message"] = "Secure page.";
  5.  
  6. return View();
  7. }
  8. //注销
  9. public IActionResult Logout()
  10. {
  11. return SignOut("oidc", "Cookies");
  12. }

  d)界面调整:

   在_Layout.cshtml文件中添加导航按钮:Secure、Logout   

  1. <li class="nav-item">
  2. <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Secure">Secure</a>
  3. </li>
  4. @if (User.Identity.IsAuthenticated)
  5. {
  6. <li class="nav-item">
  7. <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Logout">Logout</a>
  8. </li>
  9. }

   添加视图:Secure.cshtml文件:

  1. @{
  2. ViewData["Title"] = "Secure";
  3. }
  4.  
  5. <h2>@ViewData["Title"]</h2>
  6.  
  7. <h3>User claims</h3>
  8.  
  9. <dl>
  10. @foreach (var claim in User.Claims)
  11. {
  12. <dt>@claim.Type</dt>
  13. <dd>@claim.Value</dd>
  14. }
  15. </dl>

  e)运行结果如下:

  

  简化模式还支持在Js客户端中运行可以查看官方说明文档:https://identityserver4.readthedocs.io/en/latest/quickstarts/4_javascript_client.html

 4、授权码模式

  a)在InMemoryConfigGetClients方法中添加客户端:

  1. new Client
  2. {
  3. ClientId = "code_client",
  4. ClientName = "Code Client",
  5. ClientSecrets = new [] { new Secret("secret".Sha256()) },
  6. AllowedGrantTypes = GrantTypes.Code,
  7. RedirectUris = { "http://localhost:5021/signin-oidc" },
  8. PostLogoutRedirectUris = { "http://localhost:5021/signout-callback-oidc" },
      //是否显示授权提示界面
  9. RequireConsent= true,
  10. AllowedScopes = {
  11. "order","goods",
  12. IdentityServerConstants.StandardScopes.OpenId,
  13. IdentityServerConstants.StandardScopes.Profile
  14. }
  15. },

  b)调整在cz.MVCClient中Statup文件中ConfigureServices方法内容如下:

  1. // This method gets called by the runtime. Use this method to add services to the container.
  2. public void ConfigureServices(IServiceCollection services)
  3. {
  4.  
  5. services.Configure<CookiePolicyOptions>(options =>
  6. {
  7. // This lambda determines whether user consent for non-essential cookies is needed for a given request.
  8. options.CheckConsentNeeded = context => true;
  9. options.MinimumSameSitePolicy = SameSiteMode.Lax;
  10. });
  11.  
  12. JwtSecurityTokenHandler.DefaultMapInboundClaims = false;
  13.  
  14. services.AddControllersWithViews();
  15.  
  16. services.AddAuthentication(options =>
  17. {
  18. options.DefaultScheme = "Cookies";
  19. options.DefaultChallengeScheme = "oidc";
  20. })
  21. .AddCookie("Cookies")
  22. .AddOpenIdConnect("oidc", options =>
  23. {
  24. options.RequireHttpsMetadata = false;
  25. options.Authority = "http://localhost:5600";
  26. options.ClientId = "code_client";
  27. options.ClientSecret = "secret";
  28. options.ResponseType = "code";
  29. options.SaveTokens = true;
  30. options.Scope.Add("order");
  31. options.Scope.Add("goods");
  32. options.GetClaimsFromUserInfoEndpoint = true;
  33. });
  34. }

  c)运行结果如下:同简化模式运行效果相同

 5、混合模式(Hybrid)

a)在InMemoryConfigGetClients方法中添加客户端:

  1. new Client
  2. {
  3. ClientId = "hybrid_client",
  4. ClientName = "Hybrid Client",
  5. ClientSecrets = new [] { new Secret("secret".Sha256()) },
  6. AllowedGrantTypes = GrantTypes.Hybrid,
  7. //是否显示授权提示界面
  8. RequireConsent = true,
  9. AllowedScopes = {
  10. "order","goods",
  11. IdentityServerConstants.StandardScopes.OpenId,
  12. IdentityServerConstants.StandardScopes.Profile
  13. }
  14. }

  b)调整在cz.MVCClient中Statup文件中ConfigureServices方法内容如下:

  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3.  
  4. services.Configure<CookiePolicyOptions>(options =>
  5. {
  6. // This lambda determines whether user consent for non-essential cookies is needed for a given request.
  7. options.CheckConsentNeeded = context => true;
  8. options.MinimumSameSitePolicy = SameSiteMode.Lax;
  9. });
  10.  
  11. JwtSecurityTokenHandler.DefaultMapInboundClaims = false;
  12.  
  13. services.AddControllersWithViews();
  14.  
  15. services.AddAuthentication(options =>
  16. {
  17. options.DefaultScheme = "Cookies";
  18. options.DefaultChallengeScheme = "oidc";
  19. })
  20. .AddCookie("Cookies")
  21. .AddOpenIdConnect("oidc", options =>
  22. {
  23. options.RequireHttpsMetadata = false;
  24. options.Authority = "http://localhost:5600";
  25. options.ClientId = "hybrid_client";
  26. options.ClientSecret = "secret";
  27. options.ResponseType = "code token id_token";
  28. options.SaveTokens = true;
  29. options.ResponseMode = "fragment";
  30. options.GetClaimsFromUserInfoEndpoint = true;
  31. options.Scope.Add("order");
  32. options.Scope.Add("goods");
  33. });
  34. }

总结:

 应用场景总结

  • 客户端模式(Client Credentials):和用户无关,应用于应用程序与 API 资源之间的交互场景。
  • 密码模式:和用户有关,常用于第三方登录。
  • 简化模式:可用于前端或无线端。
  • 混合模式:推荐使用,包含 OpenID 认证服务和 OAuth 授权,针对的是后端服务调用。

 过程中遇到的坑:

  • Postman调用时总是提示:invalid_scope异常;

   解决:在添加IdentityServer服务时:调用AddInMemoryApiScopes方法注册Scope

  • MVC项目登录成功后跳转时,找不到http://localhost:5020/signin-oidc路径:

   解决:在Statup文件中添加services.Configure<CookiePolicyOptions>(options =>{options.CheckConsentNeeded = context => true;options.MinimumSameSitePolicy = SameSiteMode.Lax; });

  • 登录时授权界面展示展示:

   解决:客户端注册时,指定属性RequireConsent= true

Git地址:https://github.com/cwsheng/IdentityServer.Demo.git

认证授权:IdentityServer4 - 各种授权模式应用的更多相关文章

  1. 授权认证(IdentityServer4)

    区别 OpenId: Authentication :认证 Oauth: Aurhorize :授权 输入账号密码,QQ确认输入了正确的账号密码可以登录 --->认证 下面需要勾选的复选框(获取 ...

  2. IdentityServer4 (3) 授权码模式(Authorization Code)

    写在前面 1.源码(.Net Core 2.2) git地址:https://github.com/yizhaoxian/CoreIdentityServer4Demo.git 2.相关章节 2.1. ...

  3. IdentityServer4系列 | 授权码模式

    一.前言 在上一篇关于简化模式中,通过客户端以浏览器的形式请求IdentityServer服务获取访问令牌,从而请求获取受保护的资源,但由于token携带在url中,安全性方面不能保证.因此,我们可以 ...

  4. IdentityServer4 自定义授权模式

    IdentityServer4除了提供常规的几种授权模式外(AuthorizationCode.ClientCredentials.Password.RefreshToken.DeviceCode), ...

  5. .Net Core身份认证:IdentityServer4实现OAuth 2.0 客户端模式 - 简书

    原文:.Net Core身份认证:IdentityServer4实现OAuth 2.0 客户端模式 - 简书 一.客户端模式介绍 客户端模式(Client Credentials Grant)是指客户 ...

  6. (转)基于OWIN WebAPI 使用OAuth授权服务【客户端模式(Client Credentials Grant)】

    适应范围 采用Client Credentials方式,即应用公钥.密钥方式获取Access Token,适用于任何类型应用,但通过它所获取的Access Token只能用于访问与用户无关的Open ...

  7. 基于 IdentityServer3 实现 OAuth 2.0 授权服务【客户端模式(Client Credentials Grant)】

    github:https://github.com/IdentityServer/IdentityServer3/ documentation:https://identityserver.githu ...

  8. 基于OWIN WebAPI 使用OAuth授权服务【客户端模式(Client Credentials Grant)】

    适应范围 采用Client Credentials方式,即应用公钥.密钥方式获取Access Token,适用于任何类型应用,但通过它所获取的Access Token只能用于访问与用户无关的Open ...

  9. ASP.NET Core 认证与授权[5]:初识授权

    经过前面几章的姗姗学步,我们了解了在 ASP.NET Core 中是如何认证的,终于来到了授权阶段.在认证阶段我们通过用户令牌获取到用户的Claims,而授权便是对这些的Claims的验证,如:是否拥 ...

  10. OAuth2.0学习(1-6)授权方式3-密码模式(Resource Owner Password Credentials Grant)

    授权方式3-密码模式(Resource Owner Password Credentials Grant) 密码模式(Resource Owner Password Credentials Grant ...

随机推荐

  1. 认识与学习BASH①——鸟叔的Linux私房菜

    文章目录 认识与学习BASH① 认识BASH 壳程序 多种shells Bash shell 的功能 type :查询指令是否为Bash shell 的内置指令 指令的换行输入和快速删除 Shell的 ...

  2. python设计模式之修饰器模式

    python设计模式之修饰器模式 无论何时我们想对一个对象添加额外的功能,都有下面这些不同的可选方法. [ ] 如果合理,可以直接将功能添加到对象所属的类(例如,添加一个新的方法) [ ] 使用组合 ...

  3. 【Leetcode 做题学算法周刊】第八期

    首发于微信公众号<前端成长记>,写于 2020.05.07 背景 本文记录刷题过程中的整个思考过程,以供参考.主要内容涵盖: 题目分析设想 编写代码验证 查阅他人解法 思考总结 目录 15 ...

  4. SQL Server 异常代码处理

    SQL Server使用TRY...CATCH 结构实现TSQL语句的错误处理,TRY命令负责监控语句执行的情况,如果有TSQL语句发生异常,并且严重级别(Severity Level)大于10,并且 ...

  5. OAuth2.0分布式系统环境搭建

    好好学习,天天向上 本文已收录至我的Github仓库DayDayUP:github.com/RobodLee/DayDayUP,欢迎Star,更多文章请前往:目录导航 介绍 OAuth(开放授权)是一 ...

  6. VMware Workstation 15 Pro安装带图形化界面的CentOS7

    1.双击打开“VMware Workstation”,然后选择“创建新的虚拟机” 2.在安装向导中,选择“稍后安装操作系统”,然后点击“下一步”继续安装 3.在“客户机操作系统”中选择“Linux(L ...

  7. Web安全攻防(简)学习笔记

    Web安全攻防-学习笔记 本文属于一种总结性的学习笔记,内容许多都早先发布独立的文章,可以通过分类标签进行查看 信息收集 信息收集是渗透测试全过程的第一步,针对渗透目标进行最大程度的信息收集,遵随&q ...

  8. 使用IDEA连接mysql后不显示表的解决方案

    使用idea连接mysql后显示如下: 没有显示我们要看的数据表.?????????? 解决方法: 点设置: 选择要看的数据库名称,保存后就OK了.

  9. linux云服务器搭建 express后台 nginx转发

    购买云服务器 或者自己在本地搭建一个虚拟机 (我用的是腾讯云云服务器(CVM),或者可以购买阿里云 ecs服务器) 购买完成后 配置安全组 允许http https ftp 端口 一般运营商会提供说明 ...

  10. python安装numpy、scipy、gensim以及报错unable to import 'smart_open.gcs', disabling that module处理

    首先,安装gensim库,必须先安装numpy+mkl和scipy 安装顺序是依次安装numpy+kml.scipy.gensim,根据自己Python下载的版本进行下载 如果你的库里面有numpy. ...