IdentityServer4揭秘---Consent(同意页面)
授权同意页面与登录一样首先要分析页面的需要什么模型元素后建立相关的模型类
界面的话就 记住选择 、按钮、RuturnUrl、以及选择的资源Scope
/// <summary>
/// 主要绑定Consent界面上的一些模型
/// </summary>
public class ConsentViewModel
{
public string ReturnUrl { get; set; }
public bool RememberConsent { get; set; }
public string Button { get; set; }
public IEnumerable<string> ScopesConsented { get; set; }
}
ConsentViewModel
这里可以注意到还有Idr4的对应数据 比如客户端的一些信息,如名称、Logo、客户端的授权Scope等等、这里根据需要可以多写一些
/// <summary>
/// 主要绑定Idr4中关于Consent界面交互的实体字段
/// </summary>
public class Idr4ConsentViewModel : ConsentViewModel
{
public string ClientName { get; set; }
public string ClientUrl { get; set; } public string ClientLogoUrl { get; set; } public bool AllowRememberConsent { get; set; } public IEnumerable<Idr4ScopeViewModel> IdentityScopes { get; set; }
public IEnumerable<Idr4ScopeViewModel> ResouceScopes { get; set; }
}
Idr4ConsentViewModel
这里同样需要构建Idr4Consent页面展示模型
private async Task<Idr4ConsentViewModel> CreateIdr4ConsentViewModelAsync(string ReturnUrl)
{
var request = await _identityServerInteractionService.GetAuthorizationContextAsync(ReturnUrl);
if (request != null)
{
//通过客户端id获取客户端信息
var clientModel = await _clientStore.FindEnabledClientByIdAsync(request.ClientId);
if (clientModel != null)
{
//获取资源Scope信息 这里包括了两种 一种是IdentityResource 和ApiResource var resources = await _resourceStore.FindEnabledResourcesByScopeAsync(request.ScopesRequested);
//获取所有的权限 // var resources = await _resourceStore.FindEnabledResourcesByScopeAsync(clientModel.AllowedScopes); if (resources != null && (resources.ApiResources.Any() || resources.IdentityResources.Any()))
{
//构造界面需要的模型 var vm = new Idr4ConsentViewModel(); //界面初始化时候
vm.RememberConsent = true; //默认true
vm.ScopesConsented = Enumerable.Empty<string>();
vm.ReturnUrl = ReturnUrl;
//构建关于Client的信息
vm.ClientName = clientModel.ClientName;
vm.ClientUrl = clientModel.ClientUri;
vm.ClientLogoUrl = clientModel.LogoUri;
vm.AllowRememberConsent = clientModel.AllowRememberConsent;
vm.IdentityScopes = resources.IdentityResources.Select(x => new Idr4ScopeViewModel
{
Name = x.Name,
DisplayName = x.DisplayName,
Description = x.Description,
Emphasize = x.Emphasize,
Required = x.Required,
Checked = vm.ScopesConsented.Contains(x.Name) || x.Required
}).ToArray();
vm.ResouceScopes = resources.ApiResources.SelectMany(x => x.Scopes).Select(k => new Idr4ScopeViewModel
{
Name = k.Name,
DisplayName = k.DisplayName,
Description = k.Description,
Emphasize = k.Emphasize,
Required = k.Required,
Checked = vm.ScopesConsented.Contains(k.Name) || k.Required }).ToArray();
//离线
if (ConsentOptions.EnableOfflineAccess && resources.OfflineAccess)
{
vm.ResouceScopes = vm.ResouceScopes.Union(new Idr4ScopeViewModel[] {
new Idr4ScopeViewModel{ Name = IdentityServer4.IdentityServerConstants.StandardScopes.OfflineAccess,
DisplayName = ConsentOptions.OfflineAccessDisplayName,
Description = ConsentOptions.OfflineAccessDescription,
Emphasize = true,
Checked = vm.ScopesConsented.Contains(IdentityServer4.IdentityServerConstants.StandardScopes.OfflineAccess)
}
});
}
return vm;
}
else
{
//客户端Scope不存在 可以在界面提示并记录日志
return null;
} }
else
{
//客户端不存在 可以在界面提示并记录日志
return null; } }
return null;
}
CreateIdr4ConsentViewModelAsync
里面具体的话无非就是获取更具ReturnUrl地址获取用户交互接口相关的数据信息以及页面Scope绑定以及获取
值得注意的 选项required这种情况在界面上是 disabled属性 后台Action中是获取不到的,所以需要加一些影藏域
这里是Get Consent
[HttpGet]
public async Task<IActionResult> Consent(string ReturnUrl)
{
//获取请求授权信息
var vm = await CreateIdr4ConsentViewModelAsync(ReturnUrl);
if (vm != null)
{
return View(vm);
}
return View();
}
Consent Get
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Consent(Idr4ConsentViewModel model)
{ ConsentResponse consentResponse = null; if (model == null)
{
ModelState.AddModelError("", "数据发送异常");
}
//有没有选择授权 if (model.ScopesConsented == null || model.ScopesConsented.Count() == )
{
ModelState.AddModelError("", "请至少选择一个权限");
} //同意授权
if (model.Button == "yes")
{
//选择了授权Scope
if (model.ScopesConsented != null && model.ScopesConsented.Any())
{
var scopes = model.ScopesConsented;
if (ConsentOptions.EnableOfflineAccess == false)
{
scopes = scopes.Where(x => x != IdentityServer4.IdentityServerConstants.StandardScopes.OfflineAccess);
} consentResponse = new ConsentResponse
{
RememberConsent = model.RememberConsent,
ScopesConsented = scopes
}; }
}
//不同意授权
else if (model.Button == "no")
{
consentResponse = ConsentResponse.Denied;
}
else
{
var vm1 = await CreateIdr4ConsentViewModelAsync(model.ReturnUrl);
return View(vm1); } //无论同意还是不同意都是需要跳转
if (consentResponse != null)
{ var request = await _identityServerInteractionService.GetAuthorizationContextAsync(model.ReturnUrl);
if (request == null)
{
ModelState.AddModelError("", "客户端登录验证不匹配");
}
//if (consentResponse == ConsentResponse.Denied)
//{
// string url = new Uri(request.RedirectUri).Authority;
// return Redirect(url);
//} //沟通Idr4服务端实现授权
await _identityServerInteractionService.GrantConsentAsync(request, consentResponse); return Redirect(model.ReturnUrl); } var vm = await CreateIdr4ConsentViewModelAsync(model.ReturnUrl);
if (vm != null)
{
return View(vm);
} return View();
}
Consent Post
@using SSOServer.Models;
@model Idr4ConsentViewModel
@{
Layout = null;
} <!DOCTYPE html> <html>
<head>
<meta name="viewport" content="width=device-width" />
<title>确认授权页面</title>
</head>
<body>
<div>
<div><img src="@Model.ClientLogoUrl" width="" height="" /></div>
<div>@Model.ClientName</div>
<div><a href="@Model.ClientUrl" target="_blank"> @Model.ClientUrl</a></div>
</div>
<div>
<div asp-validation-summary="All"></div>
<form asp-action="Consent" class="consent-form">
<input type="hidden" asp-for="ReturnUrl" />
<div>请求你的授权</div> @if (Model.IdentityScopes.Any())
{
<div class="panel panel-default consent-buttons">
<div class="panel-heading">
<span class="glyphicon glyphicon-user"></span>
个人信息
</div>
<ul class="list-group">
@foreach (var scope in Model.IdentityScopes)
{
<li class="list-group-item">
<label>
<input class="consent-scopecheck"
type="checkbox"
name="ScopesConsented"
id="scopes_@scope.Name"
value="@scope.Name"
checked="@scope.Checked"
disabled="@scope.Required" />
@if (scope.Required)
{
<input type="hidden"
name="ScopesConsented"
value="@scope.Name" />
}
<strong>@scope.DisplayName</strong>
@if (scope.Emphasize)
{
<span class="glyphicon glyphicon-exclamation-sign"></span>
}
</label>
@if (scope.Required)
{
<span><em>(必需)</em></span>
}
@if (scope.Description != null)
{
<div class="consent-description">
<label for="scopes_@scope.Name">@scope.Description</label>
</div>
}
</li>
}
</ul>
</div>
}
@if (Model.ResouceScopes.Any())
{
<div class="panel panel-default">
<div class="panel-heading">
<span class="glyphicon glyphicon-tasks"></span>
应用授权
</div>
<ul class="list-group">
@foreach (var scope in Model.ResouceScopes)
{
<li class="list-group-item">
<label>
<input class="consent-scopecheck"
type="checkbox"
name="ScopesConsented"
id="scopes_@scope.Name"
value="@scope.Name"
checked="@scope.Checked"
disabled="@scope.Required" />
@if (scope.Required)
{
<input type="hidden"
name="ScopesConsented"
value="@scope.Name" />
}
<strong>@scope.DisplayName</strong>
@if (scope.Emphasize)
{
<span class="glyphicon glyphicon-exclamation-sign"></span>
}
</label>
@if (scope.Required)
{
<span><em>(必需)</em></span>
}
@if (scope.Description != null)
{
<div class="consent-description">
<label for="scopes_@scope.Name">@scope.Description</label>
</div>
}
</li>
}
</ul>
</div>
}
@if (Model.AllowRememberConsent)
{
<div class="consent-remember">
<label>
<input class="consent-scopecheck" asp-for="RememberConsent" />
<strong>记住选择</strong>
</label>
</div>
}
<div class="consent-buttons">
<button name="button" value="yes" class="btn btn-primary" autofocus>是, 允许</button>
<button name="button" value="no" class="btn">否,不允许</button> </div>
</form> </div> </body>
</html>
Consent View
IdentityServer4揭秘---Consent(同意页面)的更多相关文章
- IdentityServer4揭秘---登录
IdentityServer4默认提供了的登录地址是Account/Index 同意页面是Consent/Index 这里我们可以通过IdentittyServer4的用户交互自定义配置设置 在Con ...
- IdentityServer4 禁用 Consent screen page(权限确认页面)
IdentityServer4 在登录完成的适合,会再跳转一次页面(权限确认),如下: 我之前以为 IdentityServer4 就是这样使用的,但实际业务场景并不需要进行权限确认,而是登陆成功后直 ...
- asp.net core系列 58 IS4 基于浏览器的JavaScript客户端应用程序
一. 概述 本篇探讨使用"基于浏览器的JavaScript客户端应用程序".与上篇实现功能一样,只不过这篇使用JavaScript作为客户端程序,而非core mvc的后台代码Ht ...
- asp.net core系列 57 IS4 使用混合流(OIDC+OAuth2.0)添加API访问
一.概述 在上篇中,探讨了交互式用户身份验证,使用的是OIDC协议. 在之前篇中对API访问使用的是OAuth2.0协议.这篇把这两个部分放在一起,OpenID Connect和OAuth 2.0组合 ...
- IdentityServer4【Topic】之确认(Consent)
Consent 确认 在授权请求期间,如果身份服务器需要用户同意,浏览器将被重定向到同意页面.也就是说,确认也算是IdentityServer中的一个动作.确认这个词直接翻译过来有一些古怪,既然大家都 ...
- IdentityServer4中文文档
欢迎IdentityServer4 IdentityServer4是ASP.NET Core 2的OpenID Connect和OAuth 2.0框架. 它在您的应用程序中启用以下功能: 认证即服务 ...
- 一步一步学习IdentityServer4 (7) IdentityServer4成功配置全部配置
auth.liyouming.com 全部配 public class Startup { public Startup(IConfiguration configuration) { Configu ...
- 一步一步学习IdentityServer4 (2) 开始一个简单的事例
前面将来一些配置,但是很多都不是必要的,先放一些事例需要的简要配置把 既然是IdentityServer4 所里下面的例子我 直接放到 Linux上 测试环境 CentOS 7 +Nginx1.9.3 ...
- 一步一步学习IdentityServer4 (1) 概要配置说明
//结合EFCore生成IdentityServer4数据库 // 项目工程文件最后添加 <ItemGroup><DotNetCliToolReference Include=&qu ...
随机推荐
- sqlalchemy基本使用
一.ORM介绍 orm英文全称object relational mapping,就是对象映射关系程序,简单来说我们类似python这种面向对象的程序来说一切皆对象,但是我们使用的数据库却都是关系型的 ...
- python基础之while语句continue以及break --语法以及案例
1.while 死循环 [root@localhost python]# cat while.py #!/usr/bin/env python # _*_ coding:utf8 _*_ import ...
- android textview空格占位符以及一些其他占位符汇总
== 普通的英文半角空格 == == == no-break space (普通的英文半角空格但不换行) == 中文全角空格 (一个中文宽度) == == en空格 (半个中文 ...
- 全解析jQuery插件开发!很好很强大!
最近对JQuery插件开发超级感兴趣,看到这样一篇好文章,可以说是<用实例一步步教你写Jquery插件>的十全大补,大家可以两篇结合着看看! jQuery插件的开发包括两种: 一种是类级别 ...
- 【leetcode 简单】 第七十五题 第一个错误的版本
你是产品经理,目前正在带领一个团队开发新的产品.不幸的是,你的产品的最新版本没有通过质量检测.由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的. 假设你有 n 个版本 [1, ...
- 网络流建图(典型)(EK)
题目链接:https://cn.vjudge.net/contest/68128#problem/B 具体思路: 按照 源点 - > 食物 - > 牛1 - > 牛2 - > ...
- 无需登录-悟空CRM 存储型XSS
无需登录-悟空CRM 存储型XSS 审计悟空的缘由是看见某云爆出CRM的getshell,于是就想着去挖出来瞅瞅!但可能自己把自己给局限了,就想着去挖那些无限制访问的文件. 故事的发生点 漏洞文件:/ ...
- Codechef AMXOR
Problem Codechef Solution 我们可以按位进行考虑,如果一个 \(m_i\) 在某一位上为1,但 \(x_i\) 却取了0,那么我们就称它脱离了限制,更低位可以随便乱填.也就是说 ...
- openjudge-NOI 2.5基本算法之搜索 专题题解目录
1.1700 八皇后问题 2.1756 八皇后 3.1789 算24
- linux用户权限 -> 系统基本权限
比如rwxr-xr-x linux中正是这9个权限位来控制文件属主(User).属组(Group).其他用户(Other)基础权限. 用户对资源来说, 有三种角色 User(u): 属主用户(文件所有 ...