diff --git a/AuthStudy.Authentication.Browser/BrowserAuthenticationHandler2.cs b/AuthStudy.Authentication.Browser/BrowserAuthenticationBaseHandler.cs
similarity index 85%
rename from AuthStudy.Authentication.Browser/BrowserAuthenticationHandler2.cs
rename to AuthStudy.Authentication.Browser/BrowserAuthenticationBaseHandler.cs
index e54e55f..29a0cb5 100644
--- a/AuthStudy.Authentication.Browser/BrowserAuthenticationHandler2.cs
+++ b/AuthStudy.Authentication.Browser/BrowserAuthenticationBaseHandler.cs
@@ -17,28 +17,25 @@ using UAParser;
namespace AuthStudy.Authentication.Browser
{
///
- /// 浏览器认证 处理器
+ /// 浏览器认证处理器:基于接口实现
/// 可实现子接口 IAuthenticationRequestHandler, 以控制后续中间件是否执行.
///
- public class BrowserAuthenticationHandler2 :
+ public class BrowserAuthenticationBaseHandler :
IAuthenticationHandler,
IAuthenticationRequestHandler,
IAuthenticationSignInHandler,
IAuthenticationSignOutHandler
- where TOptions : AuthenticationSchemeOptions, new()
{
public string DefaultSchemeName = BrowserAuthenticationDefault.SchemeName;
public HttpContext? CurrentHttpContext;
- public List AllowBrowsers = BrowserAuthenticationDefault.AllowBrowsers;
+ public BrowserAuthenticationOptions Options;
- public BrowserAuthenticationOptions Options = BrowserAuthenticationDefault.DefaultOptions;
-
- public BrowserAuthenticationHandler2()
+ public BrowserAuthenticationBaseHandler(BrowserAuthenticationOptions option)
{
-
+ Options = option;
}
///
@@ -65,7 +62,7 @@ namespace AuthStudy.Authentication.Browser
ClientInfo clientInfo = Parser.GetDefault().Parse(userAgent);
//移动设备认证
- if (!Options.AllowMobile && BrowserAuthenticationHandler2.IsMobile(clientInfo.UA.Family))
+ if (!Options.AllowMobile && IsMobile(clientInfo.UA.Family))
{
properties.UpdateTokenValue("AuthenticationBrowser", "失败:不被允许的可移动设备");
result = AuthenticateResult.Fail($"不被允许的可移动设备:{clientInfo.UA.Family}", properties);
@@ -81,7 +78,7 @@ namespace AuthStudy.Authentication.Browser
}
//浏览器类型认证
- if (!AllowBrowsers.Contains(clientInfo.UA.Family))
+ if (!Options.AllowBrowsers.Contains(clientInfo.UA.Family))
{
properties.UpdateTokenValue("AuthenticationBrowser", "失败:不支持的浏览器");
result = AuthenticateResult.Fail($"不支持的浏览器:{clientInfo.UA.Family}", properties);
@@ -91,11 +88,11 @@ namespace AuthStudy.Authentication.Browser
//声明(身份项)
var browser = new Claim("Browser", clientInfo.UA.ToString()); //浏览器
- var os = new Claim("OS", clientInfo.OS.ToString()); //操作系统
- var device = new Claim("Device", clientInfo.Device.ToString()); //设备 //设备
+ var os = new Claim("OS", clientInfo.OS.ToString()); //操作系统
+ var device = new Claim("Device", clientInfo.Device.ToString()); //设备 //设备
//声明集合
- var Claims = new List
+ var claims = new List
{
browser,
os,
@@ -103,7 +100,7 @@ namespace AuthStudy.Authentication.Browser
};
//身份:包含声明集合,是声明集合的包装类,一个身份对应多个声明
- var claimsIdentity = new ClaimsIdentity(Claims, DefaultSchemeName);
+ var claimsIdentity = new ClaimsIdentity(claims, DefaultSchemeName);
//当事人/主角:是身份Identity的包装,对应多个身份
var claimsPrincipal = new ClaimsPrincipal(claimsIdentity);
@@ -121,16 +118,16 @@ namespace AuthStudy.Authentication.Browser
}
///
- /// 无认证:服务端向客户端(浏览器)发质询(要求提供一个新票据),质询体现为 htpp请求的响应。
+ /// 无认证:服务端向客户端(浏览器)发质询(要求提供一个新票据),质询体现为 http请求的响应。
///
public async Task ChallengeAsync(AuthenticationProperties? properties)
{
- properties?.Parameters.Add("x-itme", "无效的认证");
+ properties?.Parameters.Add("x-item", "无效的认证");
CurrentHttpContext!.Response.StatusCode = 401;
if (CurrentHttpContext?.Response.Body.CanWrite ?? false)
{
- var msg = UTF8Encoding.UTF8.GetBytes("认证无效");
+ var msg = Encoding.UTF8.GetBytes("认证无效");
await CurrentHttpContext!.Response.Body.WriteAsync(msg);
}
CurrentHttpContext?.Items.Add("认证结束时间", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
@@ -138,14 +135,14 @@ namespace AuthStudy.Authentication.Browser
}
///
- /// 无权限:服务端向客户端(浏览器)发质询(要求提供一个新票据),质询体现为 htpp请求的响应。
+ /// 无权限:服务端向客户端(浏览器)发质询(要求提供一个新票据),质询体现为 http请求的响应。
///
public async Task ForbidAsync(AuthenticationProperties? properties)
{
CurrentHttpContext!.Response.StatusCode = 403;
if (CurrentHttpContext?.Response.Body.CanWrite ?? false)
{
- var msg = UTF8Encoding.UTF8.GetBytes("无权访问");
+ var msg = Encoding.UTF8.GetBytes("无权访问");
await CurrentHttpContext!.Response.Body.WriteAsync(msg);
}
//return Task.CompletedTask;
@@ -163,7 +160,7 @@ namespace AuthStudy.Authentication.Browser
///
/// 初始化
///
- public async Task InitializeAsync(AuthenticationScheme scheme, Microsoft.AspNetCore.Http.HttpContext context)
+ public async Task InitializeAsync(AuthenticationScheme scheme, HttpContext context)
{
//初始化工作,传递给认证方法和授权中间件
CurrentHttpContext = context;
diff --git a/AuthStudy.Authentication.Browser/BrowserAuthenticationExtensions.cs b/AuthStudy.Authentication.Browser/BrowserAuthenticationExtensions.cs
index 18ba244..7de538c 100644
--- a/AuthStudy.Authentication.Browser/BrowserAuthenticationExtensions.cs
+++ b/AuthStudy.Authentication.Browser/BrowserAuthenticationExtensions.cs
@@ -12,6 +12,7 @@ namespace AuthStudy.Authentication.Browser
{
public static class BrowserAuthenticationExtensions
{
+ #region 基于接口的扩展注册
public static IServiceCollection AddBrowserAuthentication
(
this IServiceCollection builder,
@@ -36,7 +37,7 @@ namespace AuthStudy.Authentication.Browser
options.DefaultSignInScheme = AuthenticationSchemeName;
options.DefaultSignOutScheme = AuthenticationSchemeName;
- options.AddScheme(AuthenticationSchemeName, AuthenticationDispalyName);
+ options.AddScheme(AuthenticationSchemeName, AuthenticationDispalyName);
});
return builder;
@@ -47,9 +48,14 @@ namespace AuthStudy.Authentication.Browser
{
BrowserAuthenticationOptions defaultOption = option ?? new();
builder.AddSingleton(defaultOption);
- builder.AddSingleton();
+ builder.AddSingleton();
return builder;
}
+
+ #endregion
+
+ #region 基于默认基数的扩展注册
+ #endregion
}
}
diff --git a/AuthStudy.Authentication.Browser/BrowserAuthenticationHandler.cs b/AuthStudy.Authentication.Browser/BrowserAuthenticationHandler.cs
index d2be67a..bcdeeed 100644
--- a/AuthStudy.Authentication.Browser/BrowserAuthenticationHandler.cs
+++ b/AuthStudy.Authentication.Browser/BrowserAuthenticationHandler.cs
@@ -3,6 +3,7 @@ using System.Security.Claims;
using System.Security.Policy;
using System.Security.Principal;
using System.Text;
+using System.Text.Encodings.Web;
using System.Text.RegularExpressions;
using System.Text.Unicode;
using System.Threading.Tasks.Sources;
@@ -10,6 +11,8 @@ using System.Threading.Tasks.Sources;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
using Microsoft.Extensions.Primitives;
using UAParser;
@@ -17,31 +20,30 @@ using UAParser;
namespace AuthStudy.Authentication.Browser
{
///
- /// 浏览器认证 处理器
- /// 可实现子接口 IAuthenticationRequestHandler, 以控制后续中间件是否执行.
+ /// 浏览器认证处理器:基于默认类型实现
///
- public class BrowserAuthenticationHandler :
- IAuthenticationHandler,
- IAuthenticationRequestHandler,
- IAuthenticationSignInHandler,
- IAuthenticationSignOutHandler
+ public class BrowserAuthenticationHandler : AuthenticationHandler
+
{
public string DefaultSchemeName = BrowserAuthenticationDefault.SchemeName;
-
public HttpContext? CurrentHttpContext;
- public BrowserAuthenticationOptions Options;
-
- public BrowserAuthenticationHandler(BrowserAuthenticationOptions option)
+ public BrowserAuthenticationHandler
+ (
+ IOptionsMonitor options,
+ ILoggerFactory logger,
+ UrlEncoder encoder,
+ ISystemClock clock
+ ) : base(options, logger, encoder, clock)
{
- Options = option;
+
}
///
/// 认证
///
- public Task AuthenticateAsync()
+ protected override Task HandleAuthenticateAsync()
{
//认证结果
AuthenticateResult result;
@@ -88,11 +90,11 @@ namespace AuthStudy.Authentication.Browser
//声明(身份项)
var browser = new Claim("Browser", clientInfo.UA.ToString()); //浏览器
- var os = new Claim("OS", clientInfo.OS.ToString()); //操作系统
- var device = new Claim("Device", clientInfo.Device.ToString()); //设备 //设备
+ var os = new Claim("OS", clientInfo.OS.ToString()); //操作系统
+ var device = new Claim("Device", clientInfo.Device.ToString()); //设备 //设备
//声明集合
- var claims = new List
+ var Claims = new List
{
browser,
os,
@@ -100,7 +102,7 @@ namespace AuthStudy.Authentication.Browser
};
//身份:包含声明集合,是声明集合的包装类,一个身份对应多个声明
- var claimsIdentity = new ClaimsIdentity(claims, DefaultSchemeName);
+ var claimsIdentity = new ClaimsIdentity(Claims, DefaultSchemeName);
//当事人/主角:是身份Identity的包装,对应多个身份
var claimsPrincipal = new ClaimsPrincipal(claimsIdentity);
@@ -118,78 +120,19 @@ namespace AuthStudy.Authentication.Browser
}
///
- /// 无认证:服务端向客户端(浏览器)发质询(要求提供一个新票据),质询体现为 http请求的响应。
+ /// 质询:服务端向客户端(浏览器)发质询(要求提供一个新票据),质询体现为 htpp请求的响应。
///
- public async Task ChallengeAsync(AuthenticationProperties? properties)
+ protected override Task HandleChallengeAsync(AuthenticationProperties? properties)
{
- properties?.Parameters.Add("x-item", "无效的认证");
+ properties?.Parameters.Add("x-itme", "无效的认证");
CurrentHttpContext!.Response.StatusCode = 401;
if (CurrentHttpContext?.Response.Body.CanWrite ?? false)
{
- var msg = Encoding.UTF8.GetBytes("认证无效");
- await CurrentHttpContext!.Response.Body.WriteAsync(msg);
+ var msg = UTF8Encoding.UTF8.GetBytes("认证无效");
+ var t = CurrentHttpContext!.Response.Body.WriteAsync(msg);
}
CurrentHttpContext?.Items.Add("认证结束时间", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
- //return Task.CompletedTask;
- }
-
- ///
- /// 无权限:服务端向客户端(浏览器)发质询(要求提供一个新票据),质询体现为 http请求的响应。
- ///
- public async Task ForbidAsync(AuthenticationProperties? properties)
- {
- CurrentHttpContext!.Response.StatusCode = 403;
- if (CurrentHttpContext?.Response.Body.CanWrite ?? false)
- {
- var msg = Encoding.UTF8.GetBytes("无权访问");
- await CurrentHttpContext!.Response.Body.WriteAsync(msg);
- }
- //return Task.CompletedTask;
- }
-
- ///
- /// IAuthenticationRequestHandler
- /// 返回true,立即反回,不执行后续中间件
- ///
- public Task HandleRequestAsync()
- {
- return Task.FromResult(false);
- }
-
- ///
- /// 初始化
- ///
- public async Task InitializeAsync(AuthenticationScheme scheme, HttpContext context)
- {
- //初始化工作,传递给认证方法和授权中间件
- CurrentHttpContext = context;
-
- context.Items.Add("认证初始时间", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
-
- await Task.CompletedTask;
- }
-
- ///
- /// 登陆方法
- /// 写入Cookie和Session,认证信息持久化等
- ///
- public Task SignInAsync(ClaimsPrincipal user, AuthenticationProperties? properties)
- {
- //导航到主页
- //CurrentHttpContext?.Response.Redirect("/api/app/index");
-
- return Task.CompletedTask;
- }
-
- ///
- /// 退出方法: 反操作登陆方法
- /// 清除Cookie和Session,删除认证信息的持久化,作废票据等
- ///
- public Task SignOutAsync(AuthenticationProperties? properties)
- {
- //导航到登陆页
- CurrentHttpContext?.Response.Redirect("/api/auth/login");
return Task.CompletedTask;
}
@@ -210,5 +153,6 @@ namespace AuthStudy.Authentication.Browser
return isMobile;
}
+
}
}
\ No newline at end of file
diff --git a/AuthStudy.WebApp/Controllers/AccountsController.cs b/AuthStudy.WebApp/Controllers/AccountsController.cs
index f63c2d2..a181931 100644
--- a/AuthStudy.WebApp/Controllers/AccountsController.cs
+++ b/AuthStudy.WebApp/Controllers/AccountsController.cs
@@ -1,3 +1,4 @@
+using AuthStudy.Authentication.Browser;
using AuthStudy.WebApp.VModels;
using Microsoft.AspNetCore.Authorization;
@@ -15,7 +16,8 @@ namespace AuthStudy.WebApp.Controllers
}
- [Authorize]
+ [Authorize(AuthenticationSchemes = BrowserAuthenticationDefault.SchemeName)]
+ [Authorize(AuthenticationSchemes = "BrowserAuthenticationHandlerByBase")]
[HttpGet]
public IActionResult GetAll()
{
diff --git a/AuthStudy.WebApp/Program.cs b/AuthStudy.WebApp/Program.cs
index abcfb7f..4d6b01d 100644
--- a/AuthStudy.WebApp/Program.cs
+++ b/AuthStudy.WebApp/Program.cs
@@ -1,6 +1,8 @@
using AuthStudy.Authentication.Browser;
+using Microsoft.AspNetCore.Components.Forms;
+
namespace AuthStudy.WebApp
{
public class Program
@@ -17,6 +19,7 @@ namespace AuthStudy.WebApp
builder.Services.AddSwaggerGen();
#region 认证注册
+ //接口实现注册
builder.Services.AddBrowserAuthentication
(
BrowserAuthenticationDefault.SchemeName,
@@ -26,6 +29,14 @@ namespace AuthStudy.WebApp
AllowBrowsers = new List() { "Edge" }
}
);
+ builder.Services
+ .AddAuthentication("BrowserAuthenticationHandlerByBase")
+ .AddScheme("BrowserAuthenticationHandlerByBase", t =>
+ {
+ t.AllowBrowsers = new List() { "Edge", "Chrome", "Firefox" };
+ });
+ //默认基类实现注册
+
#endregion
WebApplication app = builder.Build();