.NET Core IdentityServer4实战 第六章-Consent授权页

  在identityServer4中登陆页面只要是成功了,就会注册一个Cookie在服务器资源上,像现在大部分的网站第三方授权,都是经过一个页面,然后选需要的功能,IdentityServer4也给我们提供了,只要你登陆成功,就会跳转到Consent/Index(Get)中,所以我们只要在其中做手脚就好了。

  在编写代码之前我们要知道IdentityServer的三个接口, IClientStore 是存放客户端信息的, IResourceStore 是存放资源API信息的,这两个接口都是在IdentityServer4的Stores的命名空间下,还有一个接口是 IIdentityServerInteractionService 用于与IdentityServer通信的服务,主要涉及用户交互。它可以从依赖注入系统获得,通常作为构造函数参数注入到IdentityServer的用户界面的MVC控制器中。

  下面我们创建一个Consent控制器在认证服务器上,名为 ConsentController ,在其中我们需要将这三个接口通过构造函数构造进来。

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;
        }
}

在控制器中,因为登陆成功是从Account控制器调过来的,那个时候还带着ReturnUrl这个而参数,我们在这个控制器中也需要ReturnUrl,所以在Get方法中写上该参数,要不然跳转不过来的。

public async Task Index(string returnUrl)
        {
            var model =await BuildConsentViewModel(returnUrl);return View(model);
        }

其中调用了 BuildConsentViewModel 方法用于返回一个consent对象,其中我们使用 _identityServerInteractionService 接口获取了上下文,然后再通过其余的两个接口找到它客户端还有资源api的信息。然后再调用了自定义的 CreateConsentViewModel 对象创建了consent对象。

/// 
        /// 返回一个consent对象
        /// 
        private async Task BuildConsentViewModel(string returlUrl)
        {
            //获取验证上下文
            var request = await _identityServerInteractionService.GetAuthorizationContextAsync(returlUrl);
            if (request == null)
                return null;
            //根据上下文获取client的信息以及资源Api的信息
            var client = await _clientStore.FindEnabledClientByIdAsync(request.ClientId);
            var resources = await _resourceStore.FindEnabledResourcesByScopeAsync(request.ScopesRequested);
            //创建consent对象
            var vm =  CreateConsentViewModel(request,client,resources);
            vm.ReturnUrl = returlUrl;
            return vm;
        }

 在其中创建对象并返回,只不过在获取ResourceScopes的时候,它是一个ApiResource,所以需要先转换成Scopes然呢再Select一下变成我们的ViewModel.

/// 
        /// 创建consent对象
        /// 
        private ConsentVm CreateConsentViewModel(AuthorizationRequest request,Client client,Resources resources)
        {
            var vm = new ConsentVm(); 
            vm.ClientId = client.ClientId;
            vm.Logo = client.LogoUri;
            vm.ClientName = client.ClientName;
            vm.ClientUrl = client.ClientUri;//客户端url
            vm.RemeberConsent = client.AllowRememberConsent;//是否记住信息
            vm.IdentityScopes = resources.IdentityResources.Select(i=>CreateScopeViewModel(i));
            vm.ResourceScopes = resources.ApiResources.SelectMany(u => u.Scopes).Select(x => CreatesScoreViewModel(x));
            return vm;
        }
        public ScopeVm CreatesScoreViewModel(Scope scope)
        {
            return new ScopeVm
            {
                name = scope.Name,
                DisplayName = scope.DisplayName,
                Description = scope.Description,
                Required = scope.Required,
                Checked = scope.Required,
                Emphasize = scope.Emphasize
            };
        }
        private ScopeVm CreateScopeViewModel(IdentityResource identityResource)
        {
            return new ScopeVm
            {
                name = identityResource.Name,
                DisplayName = identityResource.DisplayName,
                Description = identityResource.Description,
                Required = identityResource.Required,
                Checked = identityResource.Required,
                Emphasize = identityResource.Emphasize
            };
        }

以上我们的控制器就完成了,现在我们搞一下视图,在视图中我们就是简单做一下,使用ConsentVm作为视图绑定对象,在之中我遇到了一个Bug,我用 @Html.Partial("_ScopeListItem", item); 的时候突然就报错了,在页面上显示一个Task一大堆的错误信息,我也不知道啥情况(望大佬解决),换成不是异步的就行了。

Consent Page

@using mvcWebFirstSolucation.Models; @model ConsentVm
class="row page-header">
class="col-sm-10"> @if (!string.IsNullOrWhiteSpace(Model.Logo)) {
"@Model.Logo" />
}

@Model.ClientName 欢迎来到第三方授权

class="row">
class="col-sm-8">
"Index"> "hidden" asp-for="ReturnUrl" />
class="panel">
class="panel-heading"> class="glyphicon glyphicon-tasks"> 用户信息
    class="list-group"> @foreach (var item in Model.IdentityScopes) { @Html.Partial("_ScopeListItem", item); }
class="panel">
class="panel-heading"> class="glyphicon glyphicon-tasks"> 应用权限
    class="list-group"> @foreach (var item in Model.ResourceScopes) { @Html.Partial("_ScopeListItem", item); }
@if (!string.IsNullOrEmpty(Model.ClientUrl)) { "@Model.ClientUrl" class="pull-right btn btn-default"> class="glyphicon glyphicon-info-sign"> @Model.ClientUrl }

下面是局部视图的定义,传过来的对象是 ResourceScopes 和 IdentityScopes ,但他们都是对应ScopeVm,在其中呢就是把他们哪些权限列出来,然后勾选,在它的父页面已经做了post提交,所以我们还得弄个控制器。

@using mvcWebFirstSolucation.Models;
@model ScopeVm

  • @if (!string.IsNullOrEmpty(Model.Description)) {
    }
  •  这个方法的参数是我们所自定义的实体,其中有按钮还有返回的地址,在其中我们判断了是否选择OK,选择不那就直接赋一个拒绝的指令,如果ok那么就直接判断是否有这个权力,因为我们在config中进行了配置,然后如果有,呢么就直接添加,在不==null的清空下,我们根据 returlUrl 这个字符串获取了请求信息,然后通过 GrantConsentAsync 方法直接同意了授权,然后直接跳转过去,就成功了。

            [HttpPost]
            public async Task Index(InputConsentViewModel viewmodel)
            {
                // viewmodel.ReturlUrl
                ConsentResponse consentResponse = null;
                if (viewmodel.Button =="no")
                {
                    consentResponse = ConsentResponse.Denied;
                }
                else
                {
                    if (viewmodel.ScopesConsented !=null && viewmodel.ScopesConsented.Any()) 
                    {
                        consentResponse = new ConsentResponse
                        {
                            RememberConsent = viewmodel.RemeberConsent,
                            ScopesConsented = viewmodel.ScopesConsented
                        };
                    }
                }
                if (consentResponse != null)
                {
                    var request = await _identityServerInteractionService.GetAuthorizationContextAsync(viewmodel.ReturnUrl);
                    await _identityServerInteractionService.GrantConsentAsync(request, consentResponse);
                    return Redirect(viewmodel.ReturnUrl);
                }
                return View(await BuildConsentViewModel(viewmodel.ReturnUrl));
            }

    最后,在调试的时候一定要Client的 RequireConsent 设置为true.

     .NET Core IdentityServer4实战 第六章-Consent授权页_第1张图片

     

    你可能感兴趣的:(.NET Core IdentityServer4实战 第六章-Consent授权页)