預備知識: 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可以根據情況自行定義.