IdentityServer4實現OAuth2.0四種模式之受權碼模式

接上一篇: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"
                    }
                }

二,MVC客戶端配置

  • 因爲和隱藏模式返回token用瞄點的方式不一樣,受權碼是url參數化傳遞過來的。因此修改一下須要修改一下HTML代碼,使其能夠顯示出參數化的受權碼。

 

<!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。瀏覽器

四,訪問被保護的API

1,經過後臺訪問

 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安全

 

 

 

2,經過原生Http請求訪問

根據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部分尚未涉及,請看下一篇

IdentityServer4:OpenIdConnect

相關文章
相關標籤/搜索