.Net Core 3.0 IdentityServer4 快速入门02
.Net Core 3.0 IdentityServer4 快速入門
——?resource owner password credentials(密碼模式)
一、前言
OAuth2.0默認(rèn)有四種授權(quán)模式(GrantType):
1)授權(quán)碼模式
2)簡化模式
3)密碼模式(resource owner password credentials)
4)客戶端模式(client_credentials)
上一小節(jié)?接受了 客戶端模式 ,本小節(jié)將介紹 密碼模式,OAuth2.0資源所有者密碼授權(quán)功能允許客戶端將用戶名和密碼發(fā)送到授權(quán)服務(wù)器,并獲得該用戶的訪問令牌
認(rèn)證步驟:
1)用戶將用戶名和密碼提供給客戶端
2)客戶端再將用戶名和密碼發(fā)送給授權(quán)服務(wù)器(Id4)請求令牌
3)授權(quán)服務(wù)器(Id4)驗(yàn)證用戶的有效性,返回給客戶端令牌
4)Api資源收到第一個(gè)(首次)請求之后,會(huì)到授權(quán)服務(wù)器(Id4)獲取公鑰,然后用公鑰驗(yàn)證Token是否合法,如果合法將進(jìn)行后面的有效性驗(yàn)證,后面的請求都會(huì)用首次請求的公鑰來驗(yàn)證(jwt去中心化驗(yàn)證的思想)
Resource Owner 其實(shí)就是User,密碼模式相較于客戶端模式,多了一個(gè)參與者,就是User,通過User的用戶名和密碼向Identity Server 申請?jiān)L問令牌,這種模式下要求客戶端不得存儲(chǔ)密碼,但我們并不能確保客戶端是否存儲(chǔ)了密碼,所以該模式僅僅適用于受信任的客戶端。因此該模式不推薦使用
二、創(chuàng)建授權(quán)服務(wù)器
? 1)安裝Id4
?
2)創(chuàng)建一個(gè)Config類模擬配置要保護(hù)的資源和可以訪問的api客戶端服務(wù)器
using IdentityServer4; using IdentityServer4.Models; using IdentityServer4.Test; using System.Collections.Generic; namespace IdentityServer02 { public static class Config { /// <summary> /// 需要保護(hù)的api資源 /// </summary> public static IEnumerable<ApiResource> Apis => new List<ApiResource> { new ApiResource("api1","My Api") }; public static IEnumerable<Client> Clients => new List<Client> { //客戶端 new Client { ClientId="client", ClientSecrets={ new Secret("aju".Sha256())}, AllowedGrantTypes=GrantTypes.ResourceOwnerPassword, //如果要獲取refresh_tokens ,必須在scopes中加上OfflineAccess AllowedScopes={ "api1", IdentityServerConstants.StandardScopes.OfflineAccess}, AllowOfflineAccess=true } }; public static List<TestUser> Users = new List<TestUser> { new TestUser { SubjectId="001", Password="Aju_001", Username="Aju_001" }, new TestUser { SubjectId="002", Password="Aju_002", Username="Aju_002" } }; } }與客戶端模式不一致的地方就在于(AllowedGrantTypes=GrantTypes.ResourceOwnerPassword)此處設(shè)置為資源所有者(密碼模式)
3)配置StartUp
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; namespace IdentityServer02 { 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) { var builder = services.AddIdentityServer() .AddInMemoryApiResources(Config.Apis) .AddInMemoryClients(Config.Clients) .AddTestUsers(Config.Users);19 builder.AddDeveloperSigningCredential(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } // app.UseRouting(); app.UseIdentityServer(); } } }5)驗(yàn)證配置是否成功
在瀏覽器中輸入(http://localhost:5000/.well-known/openid-configuration)看到如下發(fā)現(xiàn)文檔算是成功的
?三、創(chuàng)建Api資源
1)步驟如創(chuàng)建授權(quán)服務(wù)的1)
2)安裝包
? 3)創(chuàng)建一個(gè)受保護(hù)的ApiController
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using System.Linq; namespace Api02.Controllers { [Route("Api")] [Authorize] public class ApiController : ControllerBase { public IActionResult Get() { return new JsonResult(from c in User.Claims select new { c.Type, c.Value }); } } }4)配置StartUp
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; namespace Api02 { public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddControllers(); services.AddAuthentication("Bearer").AddJwtBearer("Bearer", options => { options.Authority = "http://localhost:5000"; options.RequireHttpsMetadata = false; options.Audience = "api1"; }); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseRouting(); app.UseAuthentication();//認(rèn)證 app.UseAuthorization();//授權(quán) app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); } } }四、創(chuàng)建客戶端(控制臺(tái) 模擬客戶端)
using IdentityModel.Client; using Newtonsoft.Json.Linq; using System; using System.Net.Http; using System.Threading.Tasks; namespace Client02 { class Program { static async Task Main(string[] args) { // Console.WriteLine("Hello World!"); var client = new HttpClient(); var disco = await client.GetDiscoveryDocumentAsync("http://localhost:5000"); if (disco.IsError) { Console.WriteLine(disco.Error); return; } var tokenResponse = await client.RequestPasswordTokenAsync( new PasswordTokenRequest { Address = disco.TokenEndpoint, ClientId = "client", ClientSecret = "aju", Scope = "api1 offline_access", UserName = "Aju", Password = "Aju_password" }); if (tokenResponse.IsError) { Console.WriteLine(tokenResponse.Error); return; } Console.WriteLine(tokenResponse.Json); Console.WriteLine("\n\n"); //call api var apiClient = new HttpClient(); apiClient.SetBearerToken(tokenResponse.AccessToken); var response = await apiClient.GetAsync("http://localhost:5001/api"); if (!response.IsSuccessStatusCode) { Console.WriteLine(response.StatusCode); } else { var content = await response.Content.ReadAsStringAsync(); Console.WriteLine(JArray.Parse(content)); } Console.ReadLine(); } } }五、驗(yàn)證
1)直接獲取Api資源
出現(xiàn)了401未授權(quán)提示,這就說明我們的Api需要授權(quán)
2)運(yùn)行客戶端訪問Api資源
六、自定義用戶驗(yàn)證
在創(chuàng)建授權(quán)服務(wù)器的時(shí)候我們在Config中默認(rèn)模擬(寫死)兩個(gè)用戶,這顯得有點(diǎn)不太人性化,那我們就來自定義驗(yàn)證用戶信息
1)創(chuàng)建 自定義 驗(yàn)證 類?ResourceOwnerValidator?
using IdentityModel; using IdentityServer4.Models; using IdentityServer4.Validation; using System.Threading.Tasks; namespace IdentityServer02 { public class ResourceOwnerValidator : IResourceOwnerPasswordValidator { public Task ValidateAsync(ResourceOwnerPasswordValidationContext context) { if (context.UserName == "Aju" && context.Password == "Aju_password") { context.Result = new GrantValidationResult( subject: context.UserName, authenticationMethod: OidcConstants.AuthenticationMethods.Password); } else { context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "無效的秘鑰"); } return Task.FromResult(""); } } }2)在授權(quán)服務(wù)器StartUp配置類中,修改如下:
? 3)在客戶端中將 用戶名 和 密碼 修改成 我們在自定義 用戶 驗(yàn)證類 中寫的用戶名和密碼,進(jìn)行測試
七、通過refresh_token 獲取 Token
1)refresh_token?
獲取請求授權(quán)后會(huì)返回 access_token、expire_in、refresh_token 等內(nèi)容,每當(dāng)access_token 失效后用戶需要重新授權(quán),但是有了refresh_token后,客戶端(Client)檢測到Token失效后可以直接通過refresh_token向授權(quán)服務(wù)器申請新的token
八、參考文獻(xiàn)
http://docs.identityserver.io/en/latest/index.html
?
總結(jié)
以上是生活随笔為你收集整理的.Net Core 3.0 IdentityServer4 快速入门02的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 深入研究.NET Core的本地化机制
- 下一篇: .Net Core3.0 日志 logg