您好,登錄后才能下訂單哦!
今天就跟大家聊聊有關(guān).Net Core中如何寫自定義認(rèn)證實(shí)現(xiàn),可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。
最近項(xiàng)目中需要對項(xiàng)目同時支持JWT認(rèn)證,以及自定義的認(rèn)證校驗(yàn)方式認(rèn)證。通過對官方文檔了解,得到認(rèn)證實(shí)現(xiàn)主要通過繼承 IAuthenticationHandler 或 AuthenticationHandler<TOptions>來實(shí)現(xiàn)自定義認(rèn)證的處理?!?/p>
那么接下來實(shí)現(xiàn)一個自定義的認(rèn)證訪問。
1、根據(jù)前面內(nèi)容得知,處理認(rèn)證通過IAuthenticationHandler 實(shí)例處理;那么首先添加一個自定義IAuthenticationHandler 類型:
/// <summary> /// 方式一:自定義認(rèn)證處理器 /// </summary> public class CustomerAuthenticationHandler : IAuthenticationHandler { private IUserService _userService; public CustomerAuthenticationHandler(IUserService userService) { _userService = userService; } /// <summary> /// 自定義認(rèn)證Scheme名稱 /// </summary> public const string CustomerSchemeName = "cusAuth"; private AuthenticationScheme _scheme; private HttpContext _context; /// <summary> /// 認(rèn)證邏輯:認(rèn)證校驗(yàn)主要邏輯 /// </summary> /// <returns></returns> public Task<AuthenticateResult> AuthenticateAsync() { AuthenticateResult result; _context.Request.Headers.TryGetValue("Authorization", out StringValues values); string valStr = values.ToString(); if (!string.IsNullOrWhiteSpace(valStr)) { //認(rèn)證模擬basic認(rèn)證:cusAuth YWRtaW46YWRtaW4= string[] authVal = System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(valStr.Substring(CustomerSchemeName.Length + 1))).Split(':'); var loginInfo = new Dto.LoginDto() { Username = authVal[0], Password = authVal[1] }; var validVale = _userService.IsValid(loginInfo); if (!validVale) result = AuthenticateResult.Fail("未登陸"); else { var ticket = GetAuthTicket(loginInfo.Username, "admin"); result = AuthenticateResult.Success(ticket); } } else { result = AuthenticateResult.Fail("未登陸"); } return Task.FromResult(result); } /// <summary> /// 未登錄時的處理 /// </summary> /// <param name="properties"></param> /// <returns></returns> public Task ChallengeAsync(AuthenticationProperties properties) { _context.Response.StatusCode = (int)HttpStatusCode.Unauthorized; return Task.CompletedTask; } /// <summary> /// 權(quán)限不足時處理 /// </summary> /// <param name="properties"></param> /// <returns></returns> public Task ForbidAsync(AuthenticationProperties properties) { _context.Response.StatusCode = (int)HttpStatusCode.Forbidden; return Task.CompletedTask; } /// <summary> /// 初始化認(rèn)證 /// </summary> /// <param name="scheme"></param> /// <param name="context"></param> /// <returns></returns> public Task InitializeAsync(AuthenticationScheme scheme, HttpContext context) { _scheme = scheme; _context = context; return Task.CompletedTask; } #region 認(rèn)證校驗(yàn)邏輯 /// <summary> /// 生成認(rèn)證票據(jù) /// </summary> /// <param name="name"></param> /// <param name="role"></param> /// <returns></returns> private AuthenticationTicket GetAuthTicket(string name, string role) { var claimsIdentity = new ClaimsIdentity(new Claim[] { new Claim(ClaimTypes.Name, name), new Claim(ClaimTypes.Role, role), }, CustomerSchemeName); var principal = new ClaimsPrincipal(claimsIdentity); return new AuthenticationTicket(principal, _scheme.Name); } #endregion } /// <summary> /// 方式二:繼承已實(shí)現(xiàn)的基類 /// </summary> public class SubAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions> { public SubAuthenticationHandler(IOptionsMonitor<AuthenticationSchemeOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock) { } protected override Task<AuthenticateResult> HandleAuthenticateAsync() { throw new NotImplementedException(); } }
2、在Startup.cs中啟用自定義認(rèn)證:
public void ConfigureServices(IServiceCollection services) { //other code services.AddAuthentication(o => { x.DefaultAuthenticateScheme = CustomerAuthenticationHandler.CustomerSchemeName; x.DefaultChallengeScheme = CustomerAuthenticationHandler.CustomerSchemeName; o.AddScheme<CustomerAuthenticationHandler>(CustomerAuthenticationHandler.CustomerSchemeName, CustomerAuthenticationHandler.CustomerSchemeName); }); //other code } public void Configure(IApplicationBuilder app) { //other code app.UseRouting(); //在UseRouting后;UseEndpoints前添加以下代碼 app.UseAuthentication(); app.UseAuthorization(); //other code app.UseEndpoints() }
3、在控制器上添加認(rèn)證標(biāo)記,測試驗(yàn)證
//指定認(rèn)證時,采用CustomerAuthenticationHandler.CustomerSchemeName [Authorize(AuthenticationSchemes = CustomerAuthenticationHandler.CustomerSchemeName)] [Route("api/[controller]")] [ApiController] public class AuditLogController : ControllerBase { //code }
調(diào)用
在實(shí)際項(xiàng)目中可能存在,對一個控制器支持多種認(rèn)證方式如:常用的Jwt認(rèn)證、自定義認(rèn)證等,那么如何實(shí)現(xiàn)呢?
1、在Startup的ConfigureServices 方法中添加以下邏輯:
public void ConfigureServices(IServiceCollection services) { //other code services.Configure<JwtSetting>(Configuration.GetSection("JWTSetting")); var token = Configuration.GetSection("JWTSetting").Get<JwtSetting>(); //JWT認(rèn)證 services.AddAuthentication(x => { x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; //添加自定義認(rèn)證處理器 x.AddScheme<CustomerAuthenticationHandler>(CustomerAuthenticationHandler.CustomerSchemeName, CustomerAuthenticationHandler.CustomerSchemeName); }).AddJwtBearer(x => { x.RequireHttpsMetadata = false; x.SaveToken = true; x.TokenValidationParameters = new TokenValidationParameters { ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(token.SecretKey)), ValidIssuer = token.Issuer, ValidAudience = token.Audience, ValidateIssuer = false, ValidateAudience = false }; }); //other code }
2、在需要支持多種認(rèn)證方式的控制器上添加標(biāo)記:
//指定認(rèn)證時,采用CustomerAuthenticationHandler.CustomerSchemeName [Authorize(AuthenticationSchemes = CustomerAuthenticationHandler.CustomerSchemeName)] [Route("api/[controller]")] [ApiController] public class AuditLogController : ControllerBase { //code } //指定認(rèn)證采用JWT [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] public class WeatherForecastController : ControllerBase { //code }
這樣就支持了兩種認(rèn)證方式
3、一個控制器支持多種認(rèn)證類型:繼承Jwt認(rèn)證處理,并根據(jù)Scheme那么調(diào)用自定義的認(rèn)證處理器:
/// <summary> /// 方式二:同時支持多種認(rèn)證方式 /// </summary> public class MultAuthenticationHandler : JwtBearerHandler { public const string MultAuthName = "MultAuth"; IUserService _userService; public MultAuthenticationHandler(IOptionsMonitor<JwtBearerOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock, IUserService userService) : base(options, logger, encoder, clock) { _userService = userService; } protected override Task<AuthenticateResult> HandleAuthenticateAsync() { Context.Request.Headers.TryGetValue("Authorization", out StringValues values); string valStr = values.ToString(); if (valStr.StartsWith(CustomerAuthenticationHandler.CustomerSchemeName)) { var result = Valid(); if (result != null) return Task.FromResult(AuthenticateResult.Success(result)); else return Task.FromResult(AuthenticateResult.Fail("未認(rèn)證")); } else return base.AuthenticateAsync(); } private AuthenticationTicket Valid() { Context.Request.Headers.TryGetValue("Authorization", out StringValues values); string valStr = values.ToString(); if (!string.IsNullOrWhiteSpace(valStr)) { //認(rèn)證模擬basic認(rèn)證:cusAuth YWRtaW46YWRtaW4= string[] authVal = System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(valStr.Substring(CustomerAuthenticationHandler.CustomerSchemeName.Length + 1))).Split(':'); var loginInfo = new Dto.LoginDto() { Username = authVal[0], Password = authVal[1] }; if (_userService.IsValid(loginInfo)) return GetAuthTicket(loginInfo.Username, "admin"); } return null; } /// <summary> /// 生成認(rèn)證票據(jù) /// </summary> /// <param name="name"></param> /// <param name="role"></param> /// <returns></returns> private AuthenticationTicket GetAuthTicket(string name, string role) { var claimsIdentity = new ClaimsIdentity(new Claim[] { new Claim(ClaimTypes.Name, name), new Claim(ClaimTypes.Role, role), }, CustomerAuthenticationHandler.CustomerSchemeName); var principal = new ClaimsPrincipal(claimsIdentity); return new AuthenticationTicket(principal, CustomerAuthenticationHandler.CustomerSchemeName); } }
.Net Core中的自定義認(rèn)證主要通過實(shí)現(xiàn)IAuthenticationHandler 接口實(shí)現(xiàn),如果要實(shí)現(xiàn)多認(rèn)證方式通過AddScheme 應(yīng)用自定義實(shí)現(xiàn)的認(rèn)證處理器。
看完上述內(nèi)容,你們對.Net Core中如何寫自定義認(rèn)證實(shí)現(xiàn)有進(jìn)一步的了解嗎?如果還想了解更多知識或者相關(guān)內(nèi)容,請關(guān)注億速云行業(yè)資訊頻道,感謝大家的支持。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。