zoukankan      html  css  js  c++  java
  • IdentityServer4在Asp.Net Core中的应用(三)

        今天的内容是授权模式中的简化模式,还是先看以下授权流程图:

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

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

            添加对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授权模式,添加以下代码:

    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中,添加:

    .AddInMemoryIdentityResources(Config.GetIdentityResources())

    修改返回的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到我们的服务端里,在控制台使用命令:

    如果你是Windows系统,使用以下命令:

    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授权模式的过程就进行完了。

    扫描二维码关注我的公众号,共同学习,共同进步!

  • 相关阅读:
    人生感悟:人与人之间的距离
    9月22日测试题目
    Java自学第五十二天
    Java自学第五十一天
    Java自学第五十天
    Java自学第四十九天
    Java自学第四十八天
    Java自学第四十七天
    Java自学第四十六天
    Java自学第四十五天
  • 原文地址:https://www.cnblogs.com/Allen0910/p/8676239.html
Copyright © 2011-2022 走看看