feat: Broswer 认证更新

main
bicijinlian 2 years ago
parent 6acd5f3b71
commit d18fc2711f

@ -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<string> AllowBrowsers = new List<string>() { "Chrome", "Edge", "Firefox" };
public static BrowserAuthenticationOptions DefaultOptions = new BrowserAuthenticationOptions();
}
}

@ -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<BrowserAuthenticationOptions> configureOptions)
{
return builder.AddBrowser(BrowserAuthenticationDefault.AuthenticationSchemeName, configureOptions);
return builder.AddBrowser(BrowserAuthenticationDefault.SchemeName, configureOptions);
}
public static AuthenticationBuilder AddBrowser

@ -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, 以控制后续中间件是否执行.
/// </summary>
public class BrowserAuthenticationHandler<TOptions> :
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<string> supportedBrowsers = new() { "Chrome", "Edge" };
public List<string> AllowBrowsers = BrowserAuthenticationDefault.AllowBrowsers;
public BrowserAuthenticationOptions Options = BrowserAuthenticationDefault.DefaultOptions;
public BrowserAuthenticationHandler()
{
}
/// <summary>
/// 认证
/// </summary>
public Task<AuthenticateResult> 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<Claim>();
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,立即反回,不执行后续中间件
/// </summary>
/// <returns></returns>
public Task<bool> HandleRequestAsync()
{
return Task.FromResult(false);
@ -135,8 +176,8 @@ namespace AuthStudy.Authentication.Browser
/// </summary>
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;
}
}
}

@ -10,11 +10,6 @@ namespace AuthStudy.Authentication.Browser
{
public class BrowserAuthenticationOptions : AuthenticationSchemeOptions
{
/// <summary>
/// 是否启用浏览器认证
/// </summary>
public bool Enable { get; set; } = true;
/// <summary>
/// 允许的浏览器
/// </summary>
@ -31,15 +26,14 @@ namespace AuthStudy.Authentication.Browser
public bool AllowSpider { get; set; }
public BrowserAuthenticationOptions() :
this(true, new List<string>() { "Chrome", "Firfox", "Edge" }, true, true)
this(null, true, true)
{
}
public BrowserAuthenticationOptions(bool enable, List<string> allowedBrowsers, bool allowedMMobile, bool allowedSpider)
public BrowserAuthenticationOptions(List<string>? allowedBrowsers, bool allowedMMobile, bool allowedSpider)
{
Enable = enable;
AllowBrowsers = allowedBrowsers;
AllowBrowsers = allowedBrowsers ?? BrowserAuthenticationDefault.AllowBrowsers;
AllowMobile = allowedMMobile;
AllowSpider = allowedSpider;
}

@ -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<AccountVM> accounts = new List<AccountVM>()
{
new AccountVM(){ Name="张三", Email="zhangsan@qq.com", Password="123456"},

@ -19,7 +19,7 @@ namespace AuthStudy.WebApp
#region 认证注册
builder.Services.AddAuthentication(configOption =>
{
configOption.AddScheme<BrowserAuthenticationHandler<BrowserAuthenticationOptions>>(BrowserAuthenticationDefault.AuthenticationSchemeName, BrowserAuthenticationDefault.AuthenticationDispayName);
configOption.AddScheme<BrowserAuthenticationHandler<BrowserAuthenticationOptions>>(BrowserAuthenticationDefault.SchemeName, BrowserAuthenticationDefault.DispayName);
});
#endregion

Loading…
Cancel
Save