使用Identity Server 4建立Authorization Server (1)

solenovex發表於2017-11-03

預備知識: http://www.cnblogs.com/cgzl/p/7746496.html

本文內容基本完全來自於Identity Server 4官方文件: https://identityserver4.readthedocs.io/

官方文件很詳細的.

使用OAuth可以更安全, 這裡我們的authorization server和web api 以及網站將分別獨立執行. 

建立authorization server

建立asp.net core 專案使用空模板.

專案建立後, 執行方式改為使用控制檯執行而不是IISExpress, 以便檢視各種debug資訊.

開啟launchSettings.json:

{
  "profiles": {
    "AuthServer": {
      "commandName": "Project",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      },
      "applicationUrl": "http://localhost:5000/"
    }
  }
}

把IISExpress相關的內容刪掉, 然後埠改為5000.

Program.cs裡的BuildWebHost也應該加上Url:

        public static IWebHost BuildWebHost(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseUrls("http://0.0.0.0:5000")
                .UseStartup<Startup>()
                .Build();

其實不加也好用.

執行就會彈出控制檯:

安裝Identity Server4:

開啟nuget, 搜尋 identityserver4:

安裝即可.

配置asp.net core 管道

開啟startup.cs, 編輯Configure方法:

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            app.UseDeveloperExceptionPage();
            app.UseIdentityServer();
        }

就是使用上面這個中介軟體. 

配置Identity Server

還是Startup.cs,編輯ConfigureServices方法:

這裡不僅要把IdentityServer註冊到容器中, 還要至少對其配置三點內容:

1. 哪些API可以使用這個authorization server.

2. 那些客戶端Client(應用)可以使用這個authorization server.

3. 指定可以使用authorization server授權的使用者.

首先需要把上面這些做成一個配置檔案:

建立Configuration/InMemoryConfiguration.cs:

namespace AuthServer.Configuration
{
    public class InMemoryConfiguration
    {
        public static IEnumerable<ApiResource> ApiResources()
        {
            return new[]
            {
                new ApiResource("socialnetwork", "社交網路")
            };
        }

        public static IEnumerable<Client> Clients()
        {
            return new[]
            {
                new Client
                {
                    ClientId = "socialnetwork",
                    ClientSecrets = new [] { new Secret("secret".Sha256()) },
                    AllowedGrantTypes = GrantTypes.ResourceOwnerPasswordAndClientCredentials,
                    AllowedScopes = new [] { "socialnetwork" }
                }
            };
        }

        public static IEnumerable<TestUser> Users()
        {
            return new[]
            {
                new TestUser
                {
                    SubjectId = "1",
                    Username = "mail@qq.com",
                    Password = "password"
                }
            };
        }
    }
}

ApiResources: 這裡指定了name和display name, 以後api使用authorization server的時候, 這個name一定要一致, 否則就不好用的.

Clients: Client的屬性太多了, 這裡就指定幾個. 其中ClientSecrets是Client用來獲取token用的. AllowedGrantType: 這裡使用的是通過使用者名稱密碼和ClientCredentials來換取token的方式. ClientCredentials允許Client只使用ClientSecrets來獲取token. 這比較適合那種沒有使用者參與的api動作. AllowedScopes: 這裡只用socialnetwork

Users: 這裡的記憶體使用者的型別是TestUser, 只適合學習和測試使用, 實際生產環境中還是需要使用資料庫來儲存使用者資訊的, 例如接下來會使用asp.net core identity. TestUser的SubjectId是唯一標識.

然後回到StartUp的ConfigureServices:

前一篇文章講過, 我們需要對token進行簽名, 這意味著identity server需要一對public和private key. 幸運的是, 我們可以告訴identity server在程式的執行時候對這項工作進行設定: AddDeveloperSigningCredential(), 它預設會存到硬碟上的, 所以每次重啟服務不會破壞開發時的資料同步. 這個方法只適合用於identity server4在單個機器執行, 如果是production farm你得使用AddSigningCredential()這個方法.

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddIdentityServer()
                .AddDeveloperSigningCredential()
                .AddTestUsers(InMemoryConfiguration.Users().ToList())
                .AddInMemoryClients(InMemoryConfiguration.Clients())
                .AddInMemoryApiResources(InMemoryConfiguration.ApiResources());
        }

然後執行一下:

沒報錯, 紅線部分是記憶體配置版的一些解釋.

獲取Token

開啟postman, 如果你無法安裝postman, 也無法進入Chrome商店, 那麼你可以買一個海外伺服器, 使用shadowsocks伺服器和客戶端進行代理, 然後就可以訪問google了.

首先我們傳送一個錯誤的client_id, 然後得到的結果是: invalid_client. 控制檯的資訊如下:

然後我們再傳送一個正確的資料:

這次獲取到了token. 控制檯資訊如下:

由於identity server我們設定的是 ResourceOwnerPasswordAndClientCredentials 這個GrantType, 所以使用使用者名稱密碼以及使用ClientCredentials都可以. 那我們把使用者名稱和密碼去掉, 只傳送Client Credentials:

仍然獲取到了token. 控制檯上的資訊與上一個稍有不同, 沒有user相關的資訊了:

使用正經的證書:

證書可以通過幾種渠道獲得, 可以購買, 可以使用IIS生成, 也可以使用Openssl這樣的工具生成證書. 我就使用openssl吧.

去openssl的windows官網: https://slproweb.com/products/Win32OpenSSL.html

下載 1.1.0版: https://slproweb.com/download/Win64OpenSSL-1_1_0f.exe

安裝後, 開啟命令列.

openssl req -newkey rsa:2048 -nodes -keyout socialnetwork.key -x509 -days 365 -out socialnetwork.cer

具體的資訊就不管了. 這個證書的有效期是365天, 命令引數裡面設定的.

這是生成的檔案:

一個證書和一個key, 然後我們需要給他們倆封裝成一個檔案, 以便identity server可以使用它們去正確的簽名tokens. 這就需要使用另一個命令:

openssl pkcs12 -export -in socialnetwork.cer -inkey socialnetwork.key -out socialnetwork.pfx

這裡發生了錯誤...那就使用管理員開啟命令列:

輸入密碼和確認密碼後, 沒問題了.

pfx就是我們需要的檔案.

然後修改一個Startup的ConfigureServices:

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddIdentityServer()
                // .AddDeveloperSigningCredential()
                .AddSigningCredential(new X509Certificate2(@"D:\Projects\test\socialnetwork.pfx", "password"))
                .AddTestUsers(InMemoryConfiguration.Users().ToList())
                .AddInMemoryClients(InMemoryConfiguration.Clients())
                .AddInMemoryApiResources(InMemoryConfiguration.ApiResources());
        }

現在執行程式的話, 啥也不顯示. 那麼接下來, 就

新增像樣的UI

Identity Server 4 提供了一套QuickStart UI : https://github.com/IdentityServer/IdentityServer4.Quickstart.UI/tree/release

在專案根目錄開啟Powershell(可以在專案根目錄, 按住shift, 點選右鍵的Powershell)

然後輸入命令:

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

然後就把UI下載到專案了.

看看生成的檔案, 很多:

由於有wwwroot下很多靜態檔案, 所以asp.net core 需要啟用服務靜態檔案的功能: 修改Startup的Configure方法:

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            app.UseDeveloperExceptionPage();
            app.UseIdentityServer();
            app.UseStaticFiles();
            app.UseMvcWithDefaultRoute();
        }

使用靜態檔案, 並且使用了MVC.

別忘了在ConfigureServices裡面註冊MVC:

public void ConfigureServices(IServiceCollection services)
        {
            services.AddIdentityServer()
                // .AddDeveloperSigningCredential()
                .AddSigningCredential(new X509Certificate2(@"D:\Projects\test\socialnetwork.pfx", "Bx@steel"))
                .AddTestUsers(InMemoryConfiguration.Users().ToList())
                .AddInMemoryClients(InMemoryConfiguration.Clients())
                .AddInMemoryApiResources(InMemoryConfiguration.ApiResources());

            services.AddMvc();
        }

然後執行一下試試:

它現在已經具備了這些功能!

使用TestUser也可以登陸成功:

當然這個UI可以根據情況自行定義.

 

相關文章