Identity Server4學習系列四之用戶名密碼得到訪問令牌

一、簡介html

Identity Server4支持用戶名密碼模式,容許調用客戶端使用用戶名密碼來得到訪問Api資源(遵循Auth 2.0協議)的Access Token,MS可能考慮兼容老的系統,實現了這個功能,可是不建議這麼作.編程

 

二、實戰一服務端配置api

接着Identity Server4學習系列三的基礎上,直接擴展裏面的項目代碼,讓服務端同時支持密鑰認證和用戶名密碼認證mvc

第一步:擴展ThirdClients類,以下:app

    /// <summary>
    /// 配置能夠訪問IdentityServer4 保護的Api資源模型的第三方客戶端
    /// 配置客戶端訪問的密鑰
    /// </summary>
    public class ThirdClients
    {
        public static IEnumerable<Client> GetClients()
        {
            return new List<Client>()
            {
                new Client()
                {
                    //客戶端的惟一Id,客戶端須要指定該ClientId才能訪問
                     ClientId = $"client",

                    //no interactive user, use the clientid/secret for authentication
                    //使用客戶端密鑰進行認證
                    AllowedGrantTypes = GrantTypes.ClientCredentials,

                    // 認證密鑰,客戶端必須使用secret密鑰才能成功訪問
                    ClientSecrets =
                    {
                        //用Sha256對"secret"進行加密
                        new Secret("secret".Sha256())
                    },

                    // scopes that client has access to
                    //若是客戶端的密鑰認證成功,限定該密鑰能夠訪問的Api範圍
                    AllowedScopes = { "api1" }
                },
                //添加支持用戶名密碼模式訪問的客戶端類型
                new Client()
                {
                    ClientId = "userPwd.client",
                    AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,

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

        /// <summary>
        /// 配置能夠訪問IdentityServer4 保護的Api資源模型的第三方客戶端
        /// 使用用戶名密碼模式
        /// </summary>
        /// <returns></returns>
        public static List<TestUser> GetUsers()
        {
            return new List<TestUser>()
            {
                new TestUser()
                {
                    SubjectId = "1",
                    Username = "alice",
                    Password = "password"
                }
            };
        }
    }

 

第二步:註冊TestUser到Identity Server4,修改StartUp文件以下:異步

    public class Startup
    {
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            //優雅的鏈式編程
            //注入Identity Server4服務到DI容器中
            services.AddIdentityServer()
           //注入臨時簽名憑據到DI容器,後期可用簽名證書的密鑰替換,用於生成零時密鑰
           .AddDeveloperSigningCredential()
           //注入須要受Identity Server4保護的Api資源添注入到DI容器中 -內存級別
           .AddInMemoryApiResources(Apis.GetApiResources())
           //注入須要訪問受Identity Server4保護的Api資源的客戶端(密鑰模式)注入到DI容器中 -內存級別
           .AddInMemoryClients(ThirdClients.GetClients())
           //注入須要訪問受Identity Server4保護的Api資源的客戶端(用戶名密碼訪問模式)注入到DI容器中 -內存級別
           .AddTestUsers(ThirdClients.GetUsers());

            //注入基本的MVC服務
            services.AddMvcCore()
            //注入MVC的認證服務,對應控制器的Authorize特性
           .AddAuthorization()
           //注入MVC格式化程序,對應JsonResult等等的格式化操做,主要用於控制器返回值的格式化操做
           .AddJsonFormatters();

            //注入身份認證服務,設置Bearer爲默認方案
            services.AddAuthentication("Bearer")
            //注入並配置Bearer爲默認方案的基本參數
            .AddIdentityServerAuthentication(options =>
            {
                //設置令牌的發佈者
                options.Authority = "http://localhost:5000";
                //設置Https
                options.RequireHttpsMetadata = false;
                //須要認證的api資源名稱
                options.ApiName = "api1";
            });
        }

        // 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())
            {
                //從管道中捕獲同步和異步System.Exception實例並生成HTML錯誤響應。
                app.UseDeveloperExceptionPage();
            }

            //將IdentityServer 4服務注入到管道模型中(對應上面的IdentityServer 4服務的配置)
            app.UseIdentityServer();

            //將認證服務經過Microsoft.AspNetCore.Authentication.AuthenticationMiddleware中間件
            //注入到管道模型中(對應上面認證服務的配置)
            app.UseAuthentication();

            //將mvc添加到Microsoft.AspNetCore.Builder.IApplicationBuilder請求執行中(對應上的MVC配置)
            app.UseMvc();
        }
    }

ok,到這一步,Identity Server4服務端配置完成!async

 

三、實戰一客戶端發起調用ide

調用代碼以下:post

    class Program
    {
        static void Main(string[] args)
        {
            Request();
            Console.ReadKey();
        }

        async static void Request()
        {
            //請求Identity Server4服務
            var disco = await DiscoveryClient.GetAsync("http://localhost:5000");
            if (disco.IsError)
            {
                Console.WriteLine(disco.Error);
                return;
            }
            var tokenClient = new TokenClient(disco.TokenEndpoint, "userPwd.client", "secret");
            var tokenResponse = await tokenClient.RequestResourceOwnerPasswordAsync("alice", "password", "api1");

            if (tokenResponse.IsError)
            {
                Console.WriteLine(tokenResponse.Error);
                return;
            }
            //經過Identity Server4的認證事後,拿到AccessToken
            var client = new HttpClient();
            client.SetBearerToken(tokenResponse.AccessToken);
            var response = await client.GetAsync("http://localhost:5000/identity");
            if (!response.IsSuccessStatusCode)
            {
                Console.WriteLine(response.StatusCode);
            }
            else
            {
                //認證成功,輸出Identity控制器的返回值
                var content = await response.Content.ReadAsStringAsync();
                Console.WriteLine(JArray.Parse(content));
            }
            Console.WriteLine(tokenResponse.Json);
            Console.WriteLine("\n\n");
        }
    }

ok,使用用戶名加密鑰模式,訪問Api成功拿到Api返回值,注意密鑰任然須要給,由於這個密鑰是用與給Token加密的,而用戶名和密碼無非是繼續加一了一層認證,若是密鑰認證成功,必須進行用戶名和密碼的認證,二者必須同時認證成功,才能成功的發起Api的調用.學習

用戶名和密碼必須和服務端給定的一致,不然客戶端會報這個錯:

無效的受權.

 

至此,用戶名密碼加密鑰模式介紹完畢!

相關文章
相關標籤/搜索