使用Identity Server 4建立Authorization Server (2)
第一部分主要是建立了一個簡單的Identity Server.
接下來繼續:
建立Web Api專案
如圖可以在同一個解決方案下建立一個web api專案:
(可選)然後修改webapi的launchSettings.json, 我習慣使用控制檯, 所以把IISExpress相關的都刪掉, 並且把埠改成5001:
{ "profiles": { "WebApi": { "commandName": "Project", "launchBrowser": true, "launchUrl": "api/values", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" }, "applicationUrl": "http://localhost:5001/" } } }
為Web Api新增Swagger幫助頁面
完全依照官方文件安裝swagger即可: https://docs.microsoft.com/en-us/aspnet/core/tutorials/web-api-help-pages-using-swagger?tabs=visual-studio
通過nuget安裝或者通過package manager console:
Install-Package Swashbuckle.AspNetCore
在Startup的ConfigureServices註冊並配置Swagger, 然後在StartUp的Configure方法使用Swagger中介軟體:
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddMvc(); // Register the Swagger generator, defining one or more Swagger documents services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new Info { Title = "My API", Version = "v1" }); }); } // 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(); } // Enable middleware to serve generated Swagger as a JSON endpoint. app.UseSwagger(); // Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.), specifying the Swagger JSON endpoint. app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1"); }); app.UseMvc(); }
可以執行一下專案, 通過地址: http://localhost:5001/swagger/ 訪問swagger幫助頁面:
新增庫IdentityServer4.AccessTokenValidation
webapi配置identity server就需要對token進行驗證, 這個庫就是對access token進行驗證的. 通過nuget安裝:
在Startup的ConfigureServices裡面註冊配置:
services.AddMvcCore()
.AddAuthorization()
.AddJsonFormatters();
services.AddAuthentication("Bearer")
.AddIdentityServerAuthentication(options =>
{
options.RequireHttpsMetadata = false;
options.Authority ="http://localhost:5000";
options.ApiName = "socialnetwork";
});
這裡AddAuthentication()是把驗證服務註冊到DI, 並配置了Bearer作為預設模式.
AddIdentityServerAuthentication()是在DI註冊了token驗證的處理者.
由於是本地執行, 所以就不使用https了, RequireHttpsMetadata = false. 如果是生產環境, 一定要使用https.
Authority指定Authorization Server的地址.
ApiName要和Authorization Server裡面配置ApiResource的name一樣.
然後, 在Startup的Configure方法裡配置Authentication中介軟體.
app.UseAuthentication();
app.UseMvc();
這句話就是在把驗證中介軟體新增到管道里, 這樣每次請求就會呼叫驗證服務了. 一定要在UserMvc()之前呼叫.
當在controller或者Action使用[Authorize]屬性的時候, 這個中介軟體就會基於傳遞給api的Token來驗證Authorization, 如果沒有token或者token不正確, 這個中介軟體就會告訴我們這個請求是UnAuthorized(未授權的).
新增[Authorize]屬性:
開啟ValuesController, 在Controller上面新增這個屬性:
[Authorize]
[Route("api/[controller]")]
public class ValuesController : Controller
然後執行 webapi:
會自動開啟這個網址: http://localhost:5001/api/values
Chrome按F12, 開啟除錯視窗的network摺頁 (按F12以後可能需要重新整理一下瀏覽器):
401, 顯示該請求為UnAuthorized.
也可以使用postman:
還是401.
也可以使用swagger, 依然401:
所以我們首先需要獲取到一個token. 不過需要把Authorization Server也跑起來.
點選解決方案屬性, 讓兩個專案都啟動:
然後執行, 使用postman先獲取token:
如果報錯的話, 可能是生成的證書有問題, 上次文章裡面有一個引數rsa我後邊寫的是2014, 寫錯了, 應該是2048. 如果報錯就重新生成一個吧.
然後複製一下 access_token的值. 回到api/values的那個請求, 把access_token貼到Authorization Header的值裡面, 前邊要加上Bearer表示型別, 還有一個空格.
這樣, 請求就會通過驗證, 返回200和正確的值.
看一下Authorization Server的控制檯資訊:
會發現有人請求了這個地址, 事實上這就是api從identity server請求獲取public key, 然後在webapi裡用它來驗證token.
如果你改變了token的一個字母, 請求結果就會變成401.
在ValuesController裡面設斷點看看Claims
使用User.Claims來獲取claims.
看看claims, 裡面包含著authorization server的資訊, 包括client, scope等等. 這些都是從token裡面來的, 這個token在這肯定不是被篡改過的, 因為它已經從authorization server驗證過了.
上面這種驗證 我們使用的是client_credentials. 下面我們使用resourceownerpassword這個flow來試試:
在postman裡面這樣請求token, grant_type改成password, 然後新增username和password:
然後複製token, 請求api/values, 還看那個斷點:
這時claims和之前不一樣了. 這裡有sub (subject), 它是使用者的id, 還有一些其他資訊.
分析一下Token
去https://jwt.io/ 可以分析一下這個token:
token分為三個部分, 每個部分之間使用一個點來分開.
我們知道第一個部分是Header, 包括演算法和型別等資訊:
第二部分是Payload(資料), 就是斷點裡Claims的資料:
第三部分是簽名:
比較忙, 這次寫的比較少. 看來還能寫很多集... - -!