From d18fc2711fdaf550c0293452d299b24277f3c92c Mon Sep 17 00:00:00 2001 From: bicijinlian Date: Thu, 8 Jun 2023 23:45:22 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20Broswer=20=E8=AE=A4=E8=AF=81=E6=9B=B4?= =?UTF-8?q?=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BrowserAuthenticationDefault.cs | 9 +- .../BrowserAuthenticationExtensions.cs | 4 +- .../BrowserAuthenticationHandler.cs | 99 +++++++++++++++---- .../BrowserAuthenticationOptions.cs | 12 +-- .../Controllers/AccountsController.cs | 6 ++ AuthStudy.WebApp/Program.cs | 2 +- 6 files changed, 98 insertions(+), 34 deletions(-) diff --git a/AuthStudy.Authentication.Browser/BrowserAuthenticationDefault.cs b/AuthStudy.Authentication.Browser/BrowserAuthenticationDefault.cs index f6e1d59..901d31c 100644 --- a/AuthStudy.Authentication.Browser/BrowserAuthenticationDefault.cs +++ b/AuthStudy.Authentication.Browser/BrowserAuthenticationDefault.cs @@ -8,7 +8,12 @@ namespace AuthStudy.Authentication.Browser { public static class BrowserAuthenticationDefault { - public const string AuthenticationSchemeName = "BrowserScheme"; - public const string AuthenticationDispayName = "浏览器方案"; + public const string SchemeName = "BrowserScheme"; + + public const string DispayName = "浏览器方案"; + + public static List AllowBrowsers = new List() { "Chrome", "Edge", "Firefox" }; + + public static BrowserAuthenticationOptions DefaultOptions = new BrowserAuthenticationOptions(); } } diff --git a/AuthStudy.Authentication.Browser/BrowserAuthenticationExtensions.cs b/AuthStudy.Authentication.Browser/BrowserAuthenticationExtensions.cs index 590e173..d0e5a72 100644 --- a/AuthStudy.Authentication.Browser/BrowserAuthenticationExtensions.cs +++ b/AuthStudy.Authentication.Browser/BrowserAuthenticationExtensions.cs @@ -12,7 +12,7 @@ namespace AuthStudy.Authentication.Browser { public static AuthenticationBuilder AddBrowser(this AuthenticationBuilder builder) { - return builder.AddBrowser(BrowserAuthenticationDefault.AuthenticationSchemeName); + return builder.AddBrowser(BrowserAuthenticationDefault.SchemeName); } @@ -24,7 +24,7 @@ namespace AuthStudy.Authentication.Browser public static AuthenticationBuilder AddBrowser(this AuthenticationBuilder builder, Action configureOptions) { - return builder.AddBrowser(BrowserAuthenticationDefault.AuthenticationSchemeName, configureOptions); + return builder.AddBrowser(BrowserAuthenticationDefault.SchemeName, configureOptions); } public static AuthenticationBuilder AddBrowser diff --git a/AuthStudy.Authentication.Browser/BrowserAuthenticationHandler.cs b/AuthStudy.Authentication.Browser/BrowserAuthenticationHandler.cs index 65957c1..41b9acf 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.RegularExpressions; using System.Text.Unicode; using System.Threading.Tasks.Sources; @@ -20,54 +21,95 @@ namespace AuthStudy.Authentication.Browser /// 可实现子接口 IAuthenticationRequestHandler, 以控制后续中间件是否执行. /// public class BrowserAuthenticationHandler : - IAuthenticationHandler, IAuthenticationRequestHandler, IAuthenticationSignInHandler, IAuthenticationSignOutHandler + IAuthenticationHandler, IAuthenticationRequestHandler, + IAuthenticationSignInHandler, + IAuthenticationSignOutHandler where TOptions : AuthenticationSchemeOptions, new() { - public const string DefaultAuthenticationScheme = BrowserAuthenticationDefault.AuthenticationSchemeName; + public string DefaultSchemeName = BrowserAuthenticationDefault.SchemeName; public HttpContext? CurrentHttpContext; - public List supportedBrowsers = new() { "Chrome", "Edge" }; + public List AllowBrowsers = BrowserAuthenticationDefault.AllowBrowsers; + + public BrowserAuthenticationOptions Options = BrowserAuthenticationDefault.DefaultOptions; + + + public BrowserAuthenticationHandler() + { + + } /// /// 认证 /// public Task AuthenticateAsync() { + //认证结果 + AuthenticateResult result = AuthenticateResult.NoResult(); + + //属性 var properties = new AuthenticationProperties(); - properties.Items.Add("x-test", "测试"); + properties.Items.Add("AuthenticationBrowser", "浏览器认证属性"); - //获取浏览器信息 - CurrentHttpContext?.Request.Headers.TryGetValue("User-Agentx", out StringValues browserInfo); + //获取请求浏览器信息,如果请头重复则以后面的为准 + var userAgent = CurrentHttpContext?.Request.Headers["User-Agent"].LastOrDefault(); + if (userAgent == null) + { + properties.UpdateTokenValue("AuthenticationBrowser", "失败:获取不到浏览器信息"); + result = AuthenticateResult.Fail($"失败:获取不到浏览器信息", properties); + return Task.FromResult(result); + } - ClientInfo clientInfo = Parser.GetDefault().Parse(CurrentHttpContext?.Request.Headers["User-Agent"]); - if (!supportedBrowsers.Contains(clientInfo.UA.Family)) + ClientInfo clientInfo = Parser.GetDefault().Parse(userAgent); + + //移动设备认证 + if (!Options.AllowMobile && IsMobile(clientInfo.UA.Family)) { - var success = AuthenticateResult.Fail($"不支持的浏览器:{clientInfo.UA.Family}", properties); + properties.UpdateTokenValue("AuthenticationBrowser", "失败:不被允许的可移动设备"); + result = AuthenticateResult.Fail($"不被允许的可移动设备:{clientInfo.UA.Family}", properties); + return Task.FromResult(result); + } - return Task.FromResult(success); + //爬虫认证 + if (!Options.AllowSpider && clientInfo.Device.IsSpider) + { + properties.UpdateTokenValue("AuthenticationBrowser", "失败:不允许爬虫"); + result = AuthenticateResult.Fail($"不允许爬虫", properties); + return Task.FromResult(result); + } + + //浏览器类型认证 + if (!AllowBrowsers.Contains(clientInfo.UA.Family)) + { + properties.UpdateTokenValue("AuthenticationBrowser", "失败:不支持的浏览器"); + result = AuthenticateResult.Fail($"不支持的浏览器:{clientInfo.UA.Family}", properties); + + return Task.FromResult(result); } //声明(身份项) - var role = new Claim(ClaimTypes.Role, "Admin"); - var email = new Claim(ClaimTypes.Email, "bicijinlian@168.com"); + 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 Claims = new List(); - Claims.Add(role); - Claims.Add(email); + Claims.Add(browser); + Claims.Add(os); + Claims.Add(device); //身份:包含声明集合,是声明集合的包装类,一个身份对应多个声明 - var claimsIdentity = new ClaimsIdentity(Claims, DefaultAuthenticationScheme); + var claimsIdentity = new ClaimsIdentity(Claims, DefaultSchemeName); //当事人/主角:是身份Identity的包装,对应多个身份 var claimsPrincipal = new ClaimsPrincipal(claimsIdentity); //票据:对Principal的包装,一对一 - var ticket = new AuthenticationTicket(claimsPrincipal, DefaultAuthenticationScheme); + var ticket = new AuthenticationTicket(claimsPrincipal, DefaultSchemeName); //认证结果:认证信息会写入 当前请求的 User属性中,供下一个授权中间件使用 - var result = AuthenticateResult.Success(ticket); + result = AuthenticateResult.Success(ticket); //调用登陆 //CurrentHttpContext?.SignInAsync(BrowserAuthentication.DefaultAuthenticationScheme, claimsPrincipal, properties); @@ -110,7 +152,6 @@ namespace AuthStudy.Authentication.Browser /// IAuthenticationRequestHandler /// 返回true,立即反回,不执行后续中间件 /// - /// public Task HandleRequestAsync() { return Task.FromResult(false); @@ -135,8 +176,8 @@ namespace AuthStudy.Authentication.Browser /// public Task SignInAsync(ClaimsPrincipal user, AuthenticationProperties? properties) { - //导航到登陆页 - CurrentHttpContext?.Response.Redirect("https://www.baidu.com"); + //导航到主页 + //CurrentHttpContext?.Response.Redirect("/api/app/index"); return Task.CompletedTask; } @@ -151,5 +192,23 @@ namespace AuthStudy.Authentication.Browser CurrentHttpContext?.Response.Redirect("/api/auth/login"); return Task.CompletedTask; } + + private bool IsMobile(string deviceInfo) + { + bool isMobile = false; + + if (string.IsNullOrWhiteSpace(deviceInfo)) + { + return isMobile; + } + + Regex phoneRegex = new Regex(@"(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino", RegexOptions.IgnoreCase | RegexOptions.Multiline); + if (phoneRegex.IsMatch(deviceInfo)) + { + isMobile = true; + } + + return isMobile; + } } } \ No newline at end of file diff --git a/AuthStudy.Authentication.Browser/BrowserAuthenticationOptions.cs b/AuthStudy.Authentication.Browser/BrowserAuthenticationOptions.cs index 9ec0ca7..66f8937 100644 --- a/AuthStudy.Authentication.Browser/BrowserAuthenticationOptions.cs +++ b/AuthStudy.Authentication.Browser/BrowserAuthenticationOptions.cs @@ -10,11 +10,6 @@ namespace AuthStudy.Authentication.Browser { public class BrowserAuthenticationOptions : AuthenticationSchemeOptions { - /// - /// 是否启用浏览器认证 - /// - public bool Enable { get; set; } = true; - /// /// 允许的浏览器 /// @@ -31,15 +26,14 @@ namespace AuthStudy.Authentication.Browser public bool AllowSpider { get; set; } public BrowserAuthenticationOptions() : - this(true, new List() { "Chrome", "Firfox", "Edge" }, true, true) + this(null, true, true) { } - public BrowserAuthenticationOptions(bool enable, List allowedBrowsers, bool allowedMMobile, bool allowedSpider) + public BrowserAuthenticationOptions(List? allowedBrowsers, bool allowedMMobile, bool allowedSpider) { - Enable = enable; - AllowBrowsers = allowedBrowsers; + AllowBrowsers = allowedBrowsers ?? BrowserAuthenticationDefault.AllowBrowsers; AllowMobile = allowedMMobile; AllowSpider = allowedSpider; } diff --git a/AuthStudy.WebApp/Controllers/AccountsController.cs b/AuthStudy.WebApp/Controllers/AccountsController.cs index 3aa401a..f44b9cd 100644 --- a/AuthStudy.WebApp/Controllers/AccountsController.cs +++ b/AuthStudy.WebApp/Controllers/AccountsController.cs @@ -16,6 +16,12 @@ namespace AuthStudy.WebApp.Controllers [HttpGet] public IActionResult GetAll() { + //输出认证信息 + foreach (var claim in User.Claims) + { + Console.WriteLine($"{claim.Type}={claim.Value}"); + } + List accounts = new List() { new AccountVM(){ Name="张三", Email="zhangsan@qq.com", Password="123456"}, diff --git a/AuthStudy.WebApp/Program.cs b/AuthStudy.WebApp/Program.cs index 62a1d79..600798d 100644 --- a/AuthStudy.WebApp/Program.cs +++ b/AuthStudy.WebApp/Program.cs @@ -19,7 +19,7 @@ namespace AuthStudy.WebApp #region 认证注册 builder.Services.AddAuthentication(configOption => { - configOption.AddScheme>(BrowserAuthenticationDefault.AuthenticationSchemeName, BrowserAuthenticationDefault.AuthenticationDispayName); + configOption.AddScheme>(BrowserAuthenticationDefault.SchemeName, BrowserAuthenticationDefault.DispayName); }); #endregion