前言:

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

授权模式:

 环境准备

 a)调整项目结构如下:

  

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

public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews(); services.Configure<CookiePolicyOptions>(options =>
{
options.MinimumSameSitePolicy = SameSiteMode.Strict;
}); services.AddIdentityServer()
.AddDeveloperSigningCredential()
//api资源
.AddInMemoryApiResources(InMemoryConfig.GetApiResources())
//4.0版本需要添加,不然调用时提示invalid_scope错误
.AddInMemoryApiScopes(InMemoryConfig.GetApiScopes())
.AddTestUsers(InMemoryConfig.Users().ToList())
.AddInMemoryIdentityResources(InMemoryConfig.GetIdentityResourceResources())
.AddInMemoryClients(InMemoryConfig.GetClients());
} // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
} app.UseRouting(); app.UseStaticFiles();
app.UseCookiePolicy();
app.UseIdentityServer(); app.UseAuthentication();
//使用默认UI,必须添加
app.UseAuthorization(); app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(name: "default", pattern: "{controller=Home}/{action=Index}/{id?}");
});
  }
}

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

namespace cz.Api.Order.Controllers
{
[Route("identity")]
[ApiController]
[Authorize]
public class IdentityController : ControllerBase
{
[HttpGet]
public IActionResult Get()
{
return new JsonResult(from c in User.Claims select new { c.Type, c.Value });
}
}
}

 1、客户端模式

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

new Client
{
ClientId = "credentials_client", //访问客户端Id,必须唯一
ClientName = "ClientCredentials Client",
//使用客户端授权模式,客户端只需要clientid和secrets就可以访问对应的api资源。
AllowedGrantTypes = GrantTypes.ClientCredentials,
ClientSecrets =
{
new Secret("secret".Sha256())
},
AllowedScopes = {
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
"goods"
},
},

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

/// <summary>
/// 客户端认证模式
/// </summary>
private static void ClientCredentials_Test()
{
Console.WriteLine("ClientCredentials_Test------------------->");
var client = new HttpClient();
var disco = client.GetDiscoveryDocumentAsync("http://localhost:5600/").Result;
if (disco.IsError)
{
Console.WriteLine(disco.Error);
return;
}
//请求token
var tokenResponse = client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
{
Address = disco.TokenEndpoint,
ClientId = "credentials_client",
ClientSecret = "secret",
Scope = "goods"
}).Result; if (tokenResponse.IsError)
{
Console.WriteLine(tokenResponse.Error);
return;
} Console.WriteLine(tokenResponse.Json);
//调用认证api
var apiClient = new HttpClient();
apiClient.SetBearerToken(tokenResponse.AccessToken); var response = apiClient.GetAsync("http://localhost:5601/identity").Result;
if (!response.IsSuccessStatusCode)
{
Console.WriteLine(response.StatusCode);
}
else
{
var content = response.Content.ReadAsStringAsync().Result;
Console.WriteLine(content);
}
}

  运行该程序结果如下:

  

 2、密码模式

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

new Client
{
ClientId = "password_client",
ClientName = "Password Client",
ClientSecrets = new [] { new Secret("secret".Sha256()) },
//这里使用的是通过用户名密码换取token的方式.
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
AllowedScopes = {
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
"order","goods",
}
},

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

/// <summary>
/// 用户名密码模式
/// </summary>
public static void ResourceOwnerPassword_Test()
{
Console.WriteLine("ResourceOwnerPassword_Test------------------->");
// request token
var client = new HttpClient();
var disco = client.GetDiscoveryDocumentAsync("http://localhost:5600/").Result;
var tokenResponse = client.RequestPasswordTokenAsync(new PasswordTokenRequest()
{
Address = disco.TokenEndpoint,
ClientId = "password_client",
ClientSecret = "secret",
UserName = "cba",
Password = "cba",
Scope = "order goods",
}).Result; if (tokenResponse.IsError)
{
Console.WriteLine(tokenResponse.Error);
return;
}
Console.WriteLine(tokenResponse.Json);
// call api
var apiClient = new HttpClient();
client.SetBearerToken(tokenResponse.AccessToken);
var response = apiClient.GetAsync("http://localhost:5601/identity").Result;
if (!response.IsSuccessStatusCode)
{
Console.WriteLine(response.StatusCode);
}
else
{
var content = response.Content.ReadAsStringAsync().Result;
Console.WriteLine(content);
}
}

  运行该程序结果同上:  

 3、简化模式

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

new Client
{
ClientId = "implicit_client",
ClientName = "Implicit Client",
ClientSecrets = new [] { new Secret("secret".Sha256()) },
AllowedGrantTypes = GrantTypes.Implicit,
AllowedScopes = {
"order","goods",
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile
},
RedirectUris = { "http://localhost:5021/signin-oidc" },
PostLogoutRedirectUris = { "http://localhost:5021" },
//是否显示授权提示界面
RequireConsent = true,
},

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

public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
} public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
  // This lambda determines whether user consent for non-essential cookies is needed for a given request.
  options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy =
SameSiteMode.Lax;
});
JwtSecurityTokenHandler.DefaultMapInboundClaims = false; services.AddControllersWithViews(); services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies")
.AddOpenIdConnect("oidc", options =>
{
options.RequireHttpsMetadata = false;
options.Authority = "http://localhost:5600";
options.ClientId = "implicit_client";
options.ClientSecret = "secret"
;
});

} // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseCookiePolicy(); app.UseRouting(); app.UseAuthentication();
app.UseAuthorization(); app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
}

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

[Authorize]
public IActionResult Secure()
{
ViewData["Message"] = "Secure page."; return View();
}
//注销
public IActionResult Logout()
{
return SignOut("oidc", "Cookies");
}

  d)界面调整:

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

<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Secure">Secure</a>
</li>
@if (User.Identity.IsAuthenticated)
{
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Logout">Logout</a>
</li>
}

   添加视图:Secure.cshtml文件:

@{
ViewData["Title"] = "Secure";
} <h2>@ViewData["Title"]</h2> <h3>User claims</h3> <dl>
@foreach (var claim in User.Claims)
{
<dt>@claim.Type</dt>
<dd>@claim.Value</dd>
}
</dl>

  e)运行结果如下:

  

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

 4、授权码模式

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

new Client
{
ClientId = "code_client",
ClientName = "Code Client",
ClientSecrets = new [] { new Secret("secret".Sha256()) },
AllowedGrantTypes = GrantTypes.Code,
RedirectUris = { "http://localhost:5021/signin-oidc" },
PostLogoutRedirectUris = { "http://localhost:5021/signout-callback-oidc" },
  //是否显示授权提示界面
RequireConsent= true,
AllowedScopes = {
"order","goods",
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile
}
},

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

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{ services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.Lax;
}); JwtSecurityTokenHandler.DefaultMapInboundClaims = false; services.AddControllersWithViews(); services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies")
.AddOpenIdConnect("oidc", options =>
{
options.RequireHttpsMetadata = false;
options.Authority = "http://localhost:5600";
options.ClientId = "code_client";
options.ClientSecret = "secret";
options.ResponseType = "code";
options.SaveTokens = true;
options.Scope.Add("order");
options.Scope.Add("goods");
options.GetClaimsFromUserInfoEndpoint = true
;
});

}

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

 5、混合模式(Hybrid)

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

new Client
{
ClientId = "hybrid_client",
ClientName = "Hybrid Client",
ClientSecrets = new [] { new Secret("secret".Sha256()) },
AllowedGrantTypes = GrantTypes.Hybrid,
//是否显示授权提示界面
RequireConsent = true,
AllowedScopes = {
"order","goods",
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile
}
}

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

public void ConfigureServices(IServiceCollection services)
{ services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.Lax;
}); JwtSecurityTokenHandler.DefaultMapInboundClaims = false; services.AddControllersWithViews(); services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies")
.AddOpenIdConnect("oidc", options =>
{
options.RequireHttpsMetadata = false;
options.Authority = "http://localhost:5600";
options.ClientId = "hybrid_client";
options.ClientSecret = "secret";
options.ResponseType = "code token id_token";
options.SaveTokens = true;
options.ResponseMode = "fragment";
options.GetClaimsFromUserInfoEndpoint = true;
options.Scope.Add("order");
options.Scope.Add("goods");
});
}

总结:

 应用场景总结

  • 客户端模式(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. K8s集群verification error" while trying to verify candidate authority certificate "kubernetes"

    问题内容 because of "crypto/rsa: verification error" while trying to verify candidate authorit ...

  2. 【工具-代码】OSS阿里云存储服务-代码实现

    上一章节[工具]OSS阿里云存储服务--超级简单--个人还是觉得Fastdfs好玩 https://www.cnblogs.com/Yangbuyi/p/13488323.html 接上一个文章讲解还 ...

  3. 如何使用screen命令

    大家好,我是良许. 很多时候,我们都需要执行一些需要很长时间的任务.如果这时候,你的网络连接突然断开了,那么你之前所做的所有工作可能都会丢失,所做的工作可能都要重做一遍,这会浪费我们许多的时间,非常影 ...

  4. IDEA使用教程(上)

     一.介绍 IDEA全称IntelliJ IDEA,是java语言开发的集成环境.idea提倡的是智能编码,目的是减少程序员的工作,其特色功能有智能的选取.丰富的导航模式.历史记录功能等,最突出的功能 ...

  5. mysql查看死锁及解锁方法

    解除正在死锁的状态有两种方法: 第一种: 1.查询是否锁表 show OPEN TABLES where In_use > 0; 2.查询进程(如果您有SUPER权限,您可以看到所有线程.否则, ...

  6. JavaGUI之Swing简单入门示例

    简介 AWT(译:抽象窗口工具包),是Java的平台独立的窗口系统,图形和用户界面器件工具包. Swing 是为了解决 AWT 存在的问题而以 AWT 为基础新开发的包(在使用Swing时也常会用到j ...

  7. Spring 的Controller 是单例or多例

    Spring 的Controller 是单例or多例 你什么也不肯放弃,又得到了什么? 背景:今天写代码遇到一个Controller 中的线程安全问题,那么Spring 的Controller 是单例 ...

  8. Fiddler或Charles文件转换为Jmeter可执行脚本

    解决脚本录制问题,可以将Fiddler或Charles转换成对应的Jmeter脚本,实现部分内容的参数化配置,通过修改部分参数或参数化可以对http协议的接口进行自动化测试或简单的压力测试 GitHu ...

  9. Mysql 5.6创建新用户并授权指定数据库相应权限

    一.环境 Centos 6.9 Mysql 5.6.40 二.步骤 1.使用root用户登陆mysql mysql -uroot -p 输入密码: 2.创建新用户 CREATE USER 'user' ...

  10. Java高级特性——反射机制(完结)——反射与注解

    按照我们的学习进度,在前边我们讲过什么是注解以及注解如何定义,如果忘了,可以先回顾一下https://www.cnblogs.com/hgqin/p/13462051.html. 在学习反射和注解前, ...