IdentityServer4在Asp.Net Core中的应用(三)

    今天的内容是受权模式中的简化模式,仍是先看如下受权流程图:git

在这种模式中咱们将与OpenID结合使用,因此首先咱们要了解OpenID和OAuth的区别,关于他们的区别,在我上一篇博客《理解OpenID和OAuth的区别》中作了的一些简要的介绍,这里再也不多说。github

        受权服务器咱们仍是在以前的基础上改动,首先咱们须要在Config类里面添加对OpenID Connect Identity Scopes的支持,与OAuth2.0相比,OIDC(OpenID Connect)一样须要Scopes的概念,他也须要保护Scopes范围的内容而也须要让用户去访问的内容,可是OIDC中这里的范围并非用户要访问的API,而是用户标识、用户名、Email等信息。bash

        添加对OpenId(SubjectId) Profile(first name last name etc...)的支持范围,并返回一个IdentityReSource的集合,添加如下代码:服务器

//添加对OpenID Profile范围的支持
 public static IEnumerable<IdentityResource> GetIdentityResources()
 {
       return new List<IdentityResource>{
              new IdentityResources.OpenId(),
              new IdentityResources.Profile(),
         };
 }

再天际一个客户端,基于Implicit受权模式,添加如下代码:app

new Client(){
    ClientId="impClient",
    AllowedGrantTypes=GrantTypes.Implicit,

    //用于登陆成功后的RedirectUri
    RedirectUris={"http://localhost:5004/signin-oidc"},

    //用于注销后的RedirectUri
    PostLogoutRedirectUris={"http://localhost:5004/signout-callback-oidc"},

    //容许访问的范围
    AllowedScopes={
             IdentityServerConstants.StandardScopes.OpenId,
             IdentityServerConstants.StandardScopes.Profile
           }
  }

下面咱们还要将IdentityResource注入到IdentityServer中,在ConfigureService中,添加:curl

.AddInMemoryIdentityResources(Config.GetIdentityResources())async

修改返回的TestUser的方法,在每个用户中添加一个声明属性的集合,返回一个name和address信息,改动以下:学习

return new List<TestUser>{
     new TestUser(){
         SubjectId="1",
         Username="allen",
         Password="123456",
         Claims=new List<Claim>
              {
                  new Claim("name","Allen"),
                  new Claim("address","http://allen.com")
              }
         },
      new TestUser(){
         SubjectId="2",
         Username="alisa",
         Password="123456",
         Claims=new List<Claim>
                {
                    new Claim("name","Alisa"),
                    new Claim("address","http://alisa.com")
                }
         }

OIDC所需的全部协议已经内置在IdentityServer4中了,须要为登陆、注销、赞成受权内容以及错误等提供UI的部分,IdentityServer4提供了一个简单的基于MVC的UI界面,咱们能够直接download到咱们的服务端里,在控制台使用命令:ui

若是你是Windows系统,使用如下命令:this

iex ((New-Object System.Net.WebClient).DownloadString('https://raw.githubusercontent.com/IdentityServer/IdentityServer4.Quickstart.UI/release/get.ps1'))

若是你是MacOS或者Linux用户,使用:

\curl -L https://raw.githubusercontent.com/IdentityServer/IdentityServer4.Quickstart.UI/release/get.sh | bash

执行完成后,会发现多了一个QuickStart文件夹,放置了所用到的Controller,Views文件夹下也放置了对应的视图,

因为我建立的是WebApi项目,因此还要在StartUp.cs里面将原来咱们注释掉的app.UseMvc()解开,另外在配置默认路由前还要添加使用静态文件,以使用咱们的静态文件夹下的样式,app.UseStaticFiles(); 以上内容都修改完成后,下面咱们新建一个Mvc的项目,去请求咱们的受权服务器,如何建立再也不赘述,建立完成后添加对OIDC认证的支持,在ConfigureServices的方法中添加如下代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System.IdentityModel.Tokens.Jwt;

namespace MvcClient
{
    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)
        {
            JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

            //添加认证服务到DI中,
            services.AddAuthentication(options=>{
                //使用Cookies做为惟一的认证用户的主要手段
                options.DefaultScheme="Cookies";
                //须要用户登陆才可进入该应用程序,使用OpenID Connect scheme
                options.DefaultChallengeScheme="oidc";
            })
            //添加能够处理Cookie的处理程序
            .AddCookie("Cookies")

            //配置OpenID Connect协议
            .AddOpenIdConnect("oidc",options=>{
                //OIDC协议执行完成,发布Cookie
                options.SignInScheme="Cookies";

                //受权服务器地址
                options.Authority="http://localhost:5000";
                options.RequireHttpsMetadata=false;
                //指定客户端Id
                options.ClientId="impClient";
                //保存令牌在Cookie中
                options.SaveTokens=true;
            });

            services.AddMvc();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (!env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            app.UseStaticFiles();

            //添加认证中间件
            app.UseAuthentication();

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }
}

注意配置启动时将MvcClient启动端口改成5004,由于我在服务端指定的客户端的端口为5004,接着咱们添加一个Action,使他须要进行受权访问,

[Authorize]
public IActionResult Authorize()
{
      return View();
}

并添加对应的视图,展现用户信息:

@{
    ViewData["Title"] = "Authorize";
}

<h2>Claims:</h2>
<dl>
@foreach (var claim in User.Claims)
    {
        <dt>@claim.Type</dt>
        <dd>@claim.Value</dd>
    }
</dl>

至此,咱们的配置就完成了,下面咱们运行看下效果,首先run下服务端,再启动咱们的客户端,客户端点击Authorize菜单:

这个就对应咱们那个须要QQ登陆的界面了,须要经过认证,咱们输入咱们事先配置的用户名和密码,allen 123456,

到consent页面是要经过咱们的受权,将咱们用户信息共享给客户端,如今咱们选择用户profile,点击容许:

当咱们点击不容许读取用户信息的时候:

在不容许读取的状况下,咱们是没法看到用户名的。下面咱们再添加一个注销登陆的方法,

//注销登陆
public async Task LogOut()
{
     await HttpContext.SignOutAsync("Cookies");
     await HttpContext.SignOutAsync("oidc");
}

执行退出:

至此整个Implicit受权模式的过程就进行完了。

 

扫描二维码关注个人公众号,共同窗习,共同进步!

相关文章
相关标签/搜索