接上一篇:IdentityServer4實現OAuth2.0四種模式之隱藏模式javascript
受權碼模式隱藏碼模式最大不一樣是受權碼模式不直接返回token,而是先返回一個受權碼,而後再根據這個受權碼去請求token。這比隱藏模式更爲安全。從應用場景上來區分的話,隱藏模式適應於全前端的應用,受權碼模式適用於有後端的應用,由於客戶端根據受權碼去請求token時是須要把客戶端密碼轉進來的,爲了不客戶端密碼被暴露,因此請求token這個過程須要放在後臺。html
1,添加客戶端前端
新建一個支持受權碼模式的客戶端,請求token時須要客戶端密碼,因此須要設置clientSecret。登陸成功後重定向地址依然用以前創建的HTML頁面。java
new Client() { //客戶端Id ClientId="apiClientCode", ClientName="ApiClient for Code", //客戶端密碼 ClientSecrets={new Secret("apiSecret".Sha256()) }, //客戶端受權類型,Code:受權碼模式 AllowedGrantTypes=GrantTypes.Code, //容許登陸後重定向的地址列表,能夠有多個 RedirectUris = {"https://localhost:5002/auth.html"}, //容許訪問的資源 AllowedScopes={ "secretapi" } }
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> <script type="text/javascript"> var content = ""; window.onload = function () { var url = window.location.href; var array = url.split("#"); if (array.length > 1) { content = array[1]; } var search = window.location.search; if (search) { search = search.substr(1); var paras = search.split("&"); paras.forEach(element => { content += element; content+=";" }); } document.getElementById("content").innerHTML = content; } </script> </head> <body> <div id="content"></div> </body> </html>
根據OAuth2.0協議,傳遞如下參數,傳遞地址仍是參數IdentityServer4的Discover說明中的authorization_endpoint節點值http://localhost:5000/connect/authorizejson
client_id:客戶端Id redirect_uri=重定向Url,用戶登陸成功後跳回此地址 response_type=code,固定值,表示獲取受權碼 scope=secretapi,此token須要訪問的api
拼接url:http://localhost:5000/connect/authorize?client_id=apiClientCode&redirect_uri=https://localhost:5002/auth.html&response_type=code&scope=secretapi後端
在瀏覽器中訪問此url,會跳轉到用戶登陸界面,用以前建立的用戶apiUser和密碼登陸後瀏覽器會自動跳轉回設置的重定向Urlapi
能夠看到已經取到了code。瀏覽器
public async Task<IActionResult> GetData(string type,string userName,string password,string code) { type = type ?? "client"; var client = new HttpClient(); var disco = await client.GetDiscoveryDocumentAsync("http://localhost:5000"); if (disco.IsError) return new JsonResult(new { err=disco.Error}); TokenResponse token = null; switch (type) { case "client": token = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest() { //獲取Token的地址 Address = disco.TokenEndpoint, //客戶端Id ClientId = "apiClientCd", //客戶端密碼 ClientSecret = "apiSecret", //要訪問的api資源 Scope = "secretapi" }); break; case "password": token = await client.RequestPasswordTokenAsync(new PasswordTokenRequest() { //獲取Token的地址 Address = disco.TokenEndpoint, //客戶端Id ClientId = "apiClientPassword", //客戶端密碼 ClientSecret = "apiSecret", //要訪問的api資源 Scope = "secretapi", UserName =userName, Password = password }); break; case "code": token = await client.RequestAuthorizationCodeTokenAsync(new AuthorizationCodeTokenRequest() { Address = disco.TokenEndpoint, ClientId = "apiClientCode", //客戶端密碼 ClientSecret = "apiSecret", Code = code, RedirectUri = "https://localhost:5002/auth.html" }); break; } if (token.IsError) return new JsonResult(new { err = token.Error }); client.SetBearerToken(token.AccessToken); string data = await client.GetStringAsync("https://localhost:5001/api/identity"); JArray json = JArray.Parse(data); return new JsonResult(json); }
直接訪問:https://localhost:5002/home/getdata?type=code&code=93516f5af0c644c13228a66954d6c892816d358704536b6ca4e6623f6b00dee0安全
根據OAuth2.0協議,傳如下參數,地址則是以前在客戶端模式和密碼模式獲取token時用到的地址,能夠在identityServer4的discover文檔中找到。async
client_id:客戶端Id client_secret:客戶端密碼 grant_type:authorization_code,固定值 redirect_uri=重定向Url,用戶登陸成功後跳回此地址 code:獲取到的受權碼 scope=secretapi,此token須要訪問的api
獲取到token就能夠訪問api了。
四種模式講完,IdentityServer.Config.GetIdentityResouce還沒用上呢!由於這四種模式只涉及到IdentityServer4的OAuth2.0特性,OpenId部分尚未涉及,請看下一篇
。