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授權模式的過程就進行完了。


掃描二維碼關注我的公衆號,共同學習,共同進步!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章