19-21Consent Page页实现
1-在授权服务端建立相应的显示ViewModel
namespace MvcCookieAuthSample.Models { public class ConsentViewModel { public string ClientId { get; set; } public string ClientName { get; set; } public string Client { get; set; } public string ClientLogUrl { get; set; } public bool AllowRememberConsent { get; set; } public string ClientUrl { get; set; } public IEnumerable<ScopeViewModel> IdentityScopes { get; set; } public IEnumerable<ScopeViewModel> ResourceScopes { get; set; } } }
namespace MvcCookieAuthSample.Models { public class ScopeViewModel { public string Name { get; set; } public string DisplayName { get; set; } public string Description { get; set; } public bool Emphasize { get; set; } public bool Required { get; set; } public bool Checked { get; set; } } }
2-新建相应的授权页ConsentController,
using Microsoft.AspNetCore.Mvc; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using IdentityServer4.Test; using IdentityServer4.Services; using IdentityServer4.Stores; using MvcCookieAuthSample.Models; using IdentityServer4.Models; namespace MvcCookieAuthSample.Controllers { public class ConsentController:Controller { private readonly IClientStore _clientStore; private readonly IResourceStore _resourceStore; private readonly IIdentityServerInteractionService _identityServerInteractionService; public ConsentController( IClientStore clientStore, IResourceStore resourceStore, IIdentityServerInteractionService identityServerInteractionService ) { _clientStore = clientStore; _resourceStore = resourceStore; _identityServerInteractionService = identityServerInteractionService; } public async Task<IActionResult> Index(string returnUrl) { Models.ConsentViewModel model = await BuildConsentViewModel(returnUrl); if (model == null) { } return View(model); } private async Task<ConsentViewModel> BuildConsentViewModel(string returnUrl) { var request = await _identityServerInteractionService.GetAuthorizationContextAsync(returnUrl); if (request == null) return null; var client = await _clientStore.FindEnabledClientByIdAsync(request.ClientId); var resources = await _resourceStore.FindEnabledResourcesByScopeAsync(request.ScopesRequested); return CreateConsentViewModel(request, client, resources); } private ConsentViewModel CreateConsentViewModel(AuthorizationRequest request, Client client, Resources resources) { var vm = new ConsentViewModel(); vm.ClientName = client.ClientName; vm.ClientLogUrl = client.LogoUri; vm.ClientUrl = client.ClientUri; vm.AllowRememberConsent = client.AllowRememberConsent; vm.IdentityScopes = resources.IdentityResources.Select(i=>CreateScopeViewModel(i)); vm.ResourceScopes = resources.ApiResources.SelectMany(i=>i.Scopes).Select(i=>CreateScopeViewModel(i)); return vm; } private ScopeViewModel CreateScopeViewModel(IdentityResource identityResource) { return new ScopeViewModel { Name = identityResource.Name, DisplayName = identityResource.DisplayName, Description = identityResource.Description, Required = identityResource.Required, Checked = identityResource.Required, Emphasize = identityResource.Emphasize }; } private ScopeViewModel CreateScopeViewModel(Scope scope) { return new ScopeViewModel { Name = scope.Name, DisplayName = scope.DisplayName, Description = scope.Description, Required = scope.Required, Checked = scope.Required, Emphasize = scope.Emphasize }; } } }
3-编写相应的index.cshtml
@using MvcCookieAuthSample.ViewModel; @model ConsentViewModel <div class="row page-header"> <div class="col-sm-10"> @if (string.IsNullOrWhiteSpace(Model.ClientLogUrl)) { <div> <img src="@Model.ClientLogUrl" /> </div> } <h1> @Model.ClientName <small>希望使用你的账号</small> </h1> </div> </div> <div class="row"> <form> @if (Model.IdentityScopes.Any()) { <div class="panel"> <div class="panel-heading"> <span class="glyphicon glyphicon-tasks"></span> identity应用权限 </div> <ul class="list-group"> @foreach (var scope in Model.IdentityScopes) { @await Html.PartialAsync("_ScopeListItem", scope); } </ul> </div> } @if (Model.ResourceScopes.Any()) { <div class="panel"> <div class="panel-heading"> <span class="glyphicon glyphicon-tasks"></span> resource应用权限 </div> <ul class="list-group"> @foreach (var scope in Model.ResourceScopes) { await Html.PartialAsync("_ScopeListItem", scope); } </ul> </div> } </form> </div>
4- _ScopeListItem.cshtml分页视图
@* For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860 *@ @using MvcCookieAuthSample.ViewModel; @model ScopeViewModel <li> <label> <input type="checkbox" name="ScopesConsented" id="scopes_@Model.Name" value="@Model.Name" checked="@Model.Checked" disabled="@Model.Required" /> <strong>@Model.Name</strong> @if (Model.Emphasize) { <span class="glyphicon glyphicon-exclamation-sign"></span> } </label> @if (string.IsNullOrEmpty(Model.Description)) { <div> <label for="scopes_@Model.Name"> @Model.Description</label> </div> } </li>
5-Config.cs
namespace MvcCookieAuthSample { public class Config { public static IEnumerable<ApiResource> GetApiResources() { return new List<ApiResource>() { new ApiResource("api1","api DisplayName") }; } public static IEnumerable<Client> GetClients() { return new List<Client>() { new Client(){ ClientId="mvc", ClientName="mvc Name", ClientUri="http://localhost:5001", AllowRememberConsent=true, AllowedGrantTypes= GrantTypes.Implicit, ClientSecrets= new List<Secret>(){ new Secret("secret".Sha256()) }, RedirectUris = {"http://localhost:5001/signin-oidc" }, PostLogoutRedirectUris = { "http://localhost/signout-callback-oidc"}, RequireConsent=true,//启用客户端手动授权 AllowedScopes={ IdentityServerConstants.StandardScopes.Profile, IdentityServerConstants.StandardScopes.OpenId, } } }; } public static IEnumerable<IdentityResource> GetIdentityResources() { return new List<IdentityResource>() { new IdentityResources.OpenId(), new IdentityResources.Email(), new IdentityResources.Profile() }; } public static List<TestUser> GetTestUsers() { return new List<TestUser>() { new TestUser(){ SubjectId="oa001", Username="qinzb", Password="123456" } }; } } }
6-显示结果