授权同意页面与登录一样首先要分析页面的需要什么模型元素后建立相关的模型类

界面的话就 记住选择  、按钮、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

最新文章

  1. html+css二级菜单制作!
  2. DownloadManager 的使用
  3. Good Number
  4. POJ 1852 Ants (等价思考)
  5. PHP set_exception_handler 设置异常处理函数
  6. Qt-获取网络接口信息的综合示例
  7. LINQ中的Aggregate用法总结
  8. ignite学习笔记
  9. Mac OS 终端利器 iTerm2
  10. JavaScript之对象继承
  11. Linux&#160;swappiness参数设置与内存交换
  12. [随时更新][Android]小问题记录
  13. 使用postman测试dubbo服务层的方法
  14. 【读书笔记】iOS-iOS AirPlay与AppleTV
  15. Nginx配置静态资源
  16. 水题 O
  17. AIDL旅行记之开篇AIDL基本介绍
  18. e685. 显示页面格式窗口
  19. 【liunx】nslookup命令
  20. webgis开发-开始向JS转向

热门文章

  1. aapt命令说明
  2. 在Ubuntu16.04上安装virtualbox后无法装载vboxdrv模块
  3. Docker应用三:Dockerfile使用介绍(以安装redis为例)
  4. Python之路,Day2 - Python基础,列表,循环
  5. 计算广告学-多点归因模型(Multi-Touch Attribution Model)
  6. 【清华集训 2017】小Y的地铁 [模拟退火]
  7. [bzoj1095][ZJOI2007]Hide 捉迷藏——线段树+括号序列
  8. Vue 表格内容根据后台返回状态位填充文字
  9. UNIX环境高级编程 第6章 系统数据文件和信息
  10. 使用Picker的时候,让input输入框使用焦点,手机键盘不弹出