git地址:https://github.com/yizhaoxian/CoreIdentityServer4Demo.githtml
2.一、《IdentityServer4 (1) 客戶端受權模式(Client Credentials)》
2.二、《IdentityServer4 (2) 密碼受權(Resource Owner Password)》
2.三、《IdentityServer4 (3) 受權碼模式(Authorization Code)》
2.四、《IdentityServer4 (4) 靜默刷新(Implicit)》
2.五、《IdentityServer4 (5) 混合模式(Hybrid)》git
IdentityServer4 中文文檔 http://www.identityserver.com.cn/
IdentityServer4 英文文檔 https://identityserver4.readthedocs.io/en/latest/
OpenID Connect 官網 https://openid.net/connect/
OpenID Connect 中文 https://www.cnblogs.com/linianhui/p/openid-connect-core.html
OpenID Connect和OAuth 2.0對比:https://www.jianshu.com/p/d453076e6433 github
一、訪問客戶端受保護的url
二、跳轉到受權服務器認證
三、用戶填寫認證(帳號密碼)
四、認證成功,選擇受權的scope
五、受權成功(點擊贊成受權),攜帶受權碼code返回客戶端
六、客戶端經過後臺通訊請求AccessToken 和IdToken,若是設置了 OfflineAccess=true也會返回RefreshToken(能夠刷新AccessToken)web
整個訪問流程建議使用fiddler 抓包查看,更好的瞭解api
地址:https://github.com/IdentityServer/IdentityServer4.Quickstart.UI 服務器
根據本身使用的Core 版本下載對應的,點擊 tags 裏找,我下載的是2.5,解壓後以下圖cookie
把官網下載的文件添加到項目中,Quickstart 我換成了Controllersmvc
參看 《IdentityServer4 (1) 客戶端受權模式(Client Credentials)》裏的,直接複製過來就能夠了app
IdpConfig.cs GetClients()async
AllowedScopes 屬性設置的值,必須在GetApiResources() GetApis() 裏提早定義好,而且在 StartUp.cs 裏已經註冊
new Client{ ClientId="mvc client", //客戶端Id ClientName="測試客戶端", //客戶端名稱 隨便寫 AllowedGrantTypes=GrantTypes.Code,//驗證模式 ClientSecrets= { new Secret("mvc secret".Sha256()) //客戶端驗證密鑰 }, // 登錄之後 咱們重定向的地址(客戶端地址), // {客戶端地址}/signin-oidc是系統默認的不用改,也能夠改,這裏就用默認的 RedirectUris = { "http://localhost:5003/signin-oidc" }, //註銷重定向的url PostLogoutRedirectUris = { "http://localhost:5003/signout-callback-oidc" }, //是否容許申請 Refresh Tokens //參考地址 https://identityserver4.readthedocs.io/en/latest/topics/refresh_tokens.html AllowOfflineAccess=true, //將用戶claims 寫人到IdToken,客戶端能夠直接訪問 AlwaysIncludeUserClaimsInIdToken=true, //客戶端訪問權限 AllowedScopes = { "api1", IdentityServerConstants.StandardScopes.OpenId, IdentityServerConstants.StandardScopes.Email, IdentityServerConstants.StandardScopes.Address, IdentityServerConstants.StandardScopes.Phone, IdentityServerConstants.StandardScopes.Profile, IdentityServerConstants.StandardScopes.OfflineAccess } }
ConfigureServices() 注意這裏我修改了路徑,若是你使用的是 git 下載下來的不須要修改,我這裏修改是我把 git 下載的改動了
services.AddIdentityServer(options => { //默認的登錄頁面是/account/login options.UserInteraction.LoginUrl = "/login"; //受權確認頁面 默認/consent //options.UserInteraction.ConsentUrl = ""; }) .AddDeveloperSigningCredential() .AddInMemoryApiResources(IdpConfig.GetApis()) .AddInMemoryClients(IdpConfig.GetClients()) .AddTestUsers(TestUsers.Users) .AddInMemoryIdentityResources(IdpConfig.GetApiResources());
Configure()
// 要寫在 UseMvc()前面 app.UseIdentityServer(); app.UseMvcWithDefaultRoute();
ConfigureServices()
//關閉了 JWT 身份信息類型映射 //這樣就容許 well-known 身份信息(好比,「sub」 和 「idp」)無干擾地流過。 //這個身份信息類型映射的「清理」必須在調用 AddAuthentication()以前完成 //區別可參考下面截圖 JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); //添加認證信息 services.AddAuthentication(options => { options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme; }) .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme) .AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options => { options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; //認證服務器 options.Authority = "http://localhost:5002"; //去掉 https options.RequireHttpsMetadata = false; options.ClientId = "mvc client"; options.ClientSecret = "mvc secret"; //把 token 存儲到 cookie options.SaveTokens = true; options.ResponseType = OpenIdConnectResponseType.Code; //添加申請 權限 ,這裏的 scope 必須在受權服務端定義的客戶端 AllowedScopes 裏 options.Scope.Clear(); options.Scope.Add("api1"); options.Scope.Add(OidcConstants.StandardScopes.OpenId); options.Scope.Add(OidcConstants.StandardScopes.Email); options.Scope.Add(OidcConstants.StandardScopes.Address); options.Scope.Add(OidcConstants.StandardScopes.Phone); options.Scope.Add(OidcConstants.StandardScopes.Profile); options.Scope.Add(OidcConstants.StandardScopes.OfflineAccess); options.Events = new OpenIdConnectEvents { OnAuthenticationFailed = context => { context.HandleResponse(); context.Response.WriteAsync("驗證失敗"); return Task.CompletedTask; } }; });
Configure()
//寫在 UseMvc() 前面 app.UseAuthentication(); app.UseMvcWithDefaultRoute();
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); 區別
[Authorize] public class TestController : Controller { /// <summary> /// 測試從服務端認證 /// </summary> /// <returns></returns> public async Task<IActionResult> Private() { var accessToken = await HttpContext.GetTokenAsync(OpenIdConnectParameterNames.AccessToken); var idToken = await HttpContext.GetTokenAsync(OpenIdConnectParameterNames.IdToken); var refreshToken = await HttpContext.GetTokenAsync(OpenIdConnectParameterNames.RefreshToken); var code = await HttpContext.GetTokenAsync(OpenIdConnectParameterNames.Code); var model = new HomeViewModel { Infos = new Dictionary<string, string>() { {"AccessToken", accessToken }, {"IdToken", idToken }, {"RefreshToken", refreshToken }, {"Code", code } //code 是空 由於code 是一次性的 } }; return View(model); } /// <summary> /// 測試請求API資源(api1) /// </summary> /// <returns></returns> public async Task<IActionResult> SuiBian() { var accesstoken = await HttpContext.GetTokenAsync(OpenIdConnectParameterNames.AccessToken); if (string.IsNullOrEmpty(accesstoken)) { return Json(new { msg = "accesstoken 獲取失敗" }); } var client = new HttpClient(); client.SetBearerToken(accesstoken); var httpResponse = await client.GetAsync("http://localhost:5001/api/suibian"); var result = await httpResponse.Content.ReadAsStringAsync(); if (!httpResponse.IsSuccessStatusCode) { return Json(new { msg = "請求 api1 失敗。", error = result }); } return Json(new { msg = "成功", data = JsonConvert.DeserializeObject(result) }); } }
參考上一篇《IdentityServer4 (1) 客戶端受權模式》
[HttpGet] public IActionResult Get() { return new JsonResult(from c in User.Claims select new { c.Type, c.Value }); }
【客戶端:5003】【 API :5001 】【 受權認證服務器:5002】,並確認3個端口能夠正常訪問
2.1 、輸入地址:http://localhost:5003/test/private 查看是否可正常跳轉到受權服務器,
2.二、正常跳轉,輸入帳號(alice)密碼(alice)並登錄。登錄成功,並顯示可受權的信息
2.三、點擊受權贊成,返回相關受權信息,並展現在頁面
2.4 、輸入地址 http://localhost:5003/test/suibian 訪問 API 資源,正確返回