asp.net core系列 55 IS4使用Identity密碼保護API

一.概述

  OAuth 2.0資源(web api)全部者密碼受權,容許客戶端(Client項目)向令牌服務(IdentityServer項目)發送用戶名和密碼,並獲取表明該用戶的訪問令牌。在官方文檔中講到:規範一般建議不要使用「資源全部者密碼受權」。當用戶進行身份驗證並請求訪問令牌時,使用一個交互式OpenID Connect流程一般要好得多(下篇再瞭解)。html

  本篇介紹「資源全部者密碼受權」是由於這種受權容許咱們快速啓動IdentityServer。開源地址:Github git

  下面示例與官方示例有點區別,該示例使用了Identity密碼保護API。關於asp.net core Identity的瞭解實現,查看以前章節或官方文檔。示例中分別是IdentityServer令牌項目、 API資源項目、 Client訪問項目。與上篇相比同樣,仍是三個項目,區別在於:github

  (1) IdentityServer令牌項目換成了含有asp.net core Identity的MVC項目。web

  (2) API資源項目沒有變更。數據庫

  (3) Client訪問項目使用了用戶名和密碼訪問受保護的API。api

 

二. IdentityServer項目

  IdentityServer令牌項目是包含了 Identity功能(安裝:Install-Package IdentityServer4),在項目中,添加了Config.cs類和Startup.cs中加入了IdentityServer的啓動配置。下面是MVC項目目錄結構:asp.net

  (1) 添加用戶ide

    IdentityServer類庫中自帶TestUser測試類,是DTO數據傳輸對象,存儲用戶及其聲明(claims)。TestUser是用於測試中的內存(In-memory)用戶對象。在正式環境下,獲取數據庫中的用戶表(User),須要結合IdentityServer的IResourceOwnerPasswordValidator接口(再也不本篇講述中)。 下面經過在config.cs類中添加GetUsers方法獲取用戶密碼,存儲在TestUser數據傳輸對象中。測試

        /// <summary>
        ///獲取用戶,這些用戶能夠訪問受密碼保護的API
        /// </summary>
        /// <param name="provider"></param>
        /// <returns></returns>
        public static List<TestUser> GetUsers(ServiceProvider provider)
        {
            var webAppIdentityDemoUser = provider.GetRequiredService<UserManager<WebAppIdentityDemoUser>>();
            IList<WebAppIdentityDemoUser> users = null;
            //獲取Identity的User表用戶,條件是屬於Administrator角色的用戶
            users = webAppIdentityDemoUser.GetUsersInRoleAsync("Administrator").Result;

            List<TestUser> testUserList = new List<TestUser>();
            foreach (WebAppIdentityDemoUser user in users)
            {
                testUserList.Add(new TestUser() { SubjectId = user.Id.ToString(), Username = user.UserName, Password = user.PasswordHash });
            }
            return testUserList;
        }

  (2) 而後在Startup類的ConfigureServices方法中使用IdentityServer注入測試用戶:ui

            ServiceProvider provider = services.BuildServiceProvider();

            var builder = services.AddIdentityServer()
                .AddInMemoryIdentityResources(Config.GetIdentityResources())
                .AddInMemoryApiResources(Config.GetApis())
                .AddInMemoryClients(Config.GetClients())
                .AddTestUsers(Config.GetUsers(provider));

  (3) 定義客戶端, 使用密碼授予訪問此API(資源範圍:api1)

    在config.cs類中,定義客戶端,經過修改AllowedGrantTypes枚舉來簡單地向現有客戶端添加對受權類型的支持, 將如下代碼添加到客戶端配置中, 裏面支持二個Client受權類型,分別是ClientCredentials使用憑證來訪問令牌和ResourceOwnerPassword 使用密碼來訪問令牌。

      public static IEnumerable<Client> GetClients()
        {
            return new List<Client>
            {
                new Client
                {
                    ClientId = "client",

                    // no interactive user, use the clientid/secret for authentication
                    AllowedGrantTypes = GrantTypes.ClientCredentials,

                    // secret for authentication
                    ClientSecrets =
                    {
                        new Secret("secret".Sha256())
                    },

                    // scopes that client has access to
                    AllowedScopes = { "api1" }
                },
                // resource owner password grant client
                new Client
                {
                    ClientId = "ro.client",
                    AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,

                    ClientSecrets =
                    {
                        new Secret("secret".Sha256())
                    },
                    AllowedScopes = { "api1" }
                }
            };
        }

  

三.Client項目

  該Client項目相似於上篇介紹的Client項目,該項目名爲ResourceOwnerClient, 該Client將收集用戶名和密碼,並在令牌請求期間,將其發送到IdentityServer令牌服務(WebAppIdentityDemo項目)

            // request token 請求令牌
            var tokenResponse = await client.RequestPasswordTokenAsync(new PasswordTokenRequest
            {
                Address = disco.TokenEndpoint,
                ClientId = "ro.client",
                ClientSecret = "secret",

                UserName = "924964690@qq.com",
                Password = "AQAAAAEAACcQAAAAEH4Xhui5BByq6d8VS5Z+S2o2SnlkyrP5pN9CmMpgJ4QiIVrt7lBLzDlEWa6AdlpxpA==",
                Scope = "api1"
            });

            if (tokenResponse.IsError)
            {
                Console.WriteLine(tokenResponse.Error);
                return;
            }

            Console.WriteLine(tokenResponse.Json);
            Console.WriteLine("\n\n");

  最後測試,先啓動WebAppIdentityDemo項目程序,再啓動API程序,最後啓動Client客戶端來訪問API,經過下圖能夠了解到:(1)客戶端請求使用「用戶名和和密碼」訪問令牌(token)成功, (2) 客戶端使用令牌(AccessToken)來訪問受密碼保護的web API接口成功。

  

  

  參考文獻

    使用密碼保護API

相關文章
相關標籤/搜索