From 2488b155321810b6f562215fb8bf658a3e74a4f9 Mon Sep 17 00:00:00 2001
From: falcon <9504402@qq.com>
Date: Wed, 7 Dec 2022 10:37:23 +0800
Subject: [PATCH] =?UTF-8?q?=E9=A3=9E=E5=87=BAJWT=EF=BC=8C=E6=96=B0?=
=?UTF-8?q?=E5=A2=9EFalconClaim=E7=94=A8=E4=BA=8Eapi=E7=9A=84Token?=
=?UTF-8?q?=E8=AE=A4=E8=AF=81?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Falcon.SugarApi.Test/JwtTokenBuilderTest.cs | 51 ---------
.../FalconClaim/AddFalconClaimHeaderFilter.cs | 44 +++++++
.../FalconClaim/AesTokenBuilder.cs | 56 +++++++++
.../FalconClaim/ClaimsIdentityExtend.cs | 23 ++++
.../FalconAuthenticationHandler.cs | 108 ++++++++++++++++++
.../FalconClaimAuthorizeAttribute.cs | 27 +++++
.../FalconClaim/FalconClaimOption.cs | 40 +++++++
.../FalconClaim/IApplicationBuilderExtend.cs | 18 +++
.../FalconClaim/IServiceCollectionExtend.cs | 33 ++++++
Falcon.SugarApi/FalconClaim/ITokenBuilter.cs | 24 ++++
Falcon.SugarApi/FalconClaim/IUserValidate.cs | 16 +++
Falcon.SugarApi/FalconClaim/NameClaim.cs | 16 +++
Falcon.SugarApi/FalconClaim/Readme.md | 7 ++
Falcon.SugarApi/FalconClaim/SidClaim.cs | 18 +++
.../FalconClaim/SwaggerGenOptionsExtend.cs | 51 +++++++++
Falcon.SugarApi/FalconClaim/UserLoginModel.cs | 18 +++
.../FalconClaim/UserLoginResult.cs | 44 +++++++
Falcon.SugarApi/JWT/AESTokenbuilder.cs | 42 -------
.../JWT/ApiAuthorizationAttribute.cs | 73 ------------
Falcon.SugarApi/JWT/IJwtTokenBuilder.cs | 22 ----
.../JWT/IServiceCollectionExtend.cs | 56 ---------
Falcon.SugarApi/JWT/IUserLogin.cs | 39 -------
Falcon.SugarApi/JWT/JwtContext.cs | 29 -----
Falcon.SugarApi/JWT/JwtTokenBuilder.cs | 64 -----------
Falcon.SugarApi/JWT/JwtTokenBuilderExtend.cs | 52 ---------
Falcon.SugarApi/JWT/LoginDto.cs | 17 ---
Falcon.SugarApi/JWT/LoginUserInfo.cs | 29 -----
Falcon.SugarApi/JWT/TokenDto.cs | 21 ----
Falcon.SugarApi/JWT/readme.md | 7 --
29 files changed, 543 insertions(+), 502 deletions(-)
delete mode 100644 Falcon.SugarApi.Test/JwtTokenBuilderTest.cs
create mode 100644 Falcon.SugarApi/FalconClaim/AddFalconClaimHeaderFilter.cs
create mode 100644 Falcon.SugarApi/FalconClaim/AesTokenBuilder.cs
create mode 100644 Falcon.SugarApi/FalconClaim/ClaimsIdentityExtend.cs
create mode 100644 Falcon.SugarApi/FalconClaim/FalconAuthenticationHandler.cs
create mode 100644 Falcon.SugarApi/FalconClaim/FalconClaimAuthorizeAttribute.cs
create mode 100644 Falcon.SugarApi/FalconClaim/FalconClaimOption.cs
create mode 100644 Falcon.SugarApi/FalconClaim/IApplicationBuilderExtend.cs
create mode 100644 Falcon.SugarApi/FalconClaim/IServiceCollectionExtend.cs
create mode 100644 Falcon.SugarApi/FalconClaim/ITokenBuilter.cs
create mode 100644 Falcon.SugarApi/FalconClaim/IUserValidate.cs
create mode 100644 Falcon.SugarApi/FalconClaim/NameClaim.cs
create mode 100644 Falcon.SugarApi/FalconClaim/Readme.md
create mode 100644 Falcon.SugarApi/FalconClaim/SidClaim.cs
create mode 100644 Falcon.SugarApi/FalconClaim/SwaggerGenOptionsExtend.cs
create mode 100644 Falcon.SugarApi/FalconClaim/UserLoginModel.cs
create mode 100644 Falcon.SugarApi/FalconClaim/UserLoginResult.cs
delete mode 100644 Falcon.SugarApi/JWT/AESTokenbuilder.cs
delete mode 100644 Falcon.SugarApi/JWT/ApiAuthorizationAttribute.cs
delete mode 100644 Falcon.SugarApi/JWT/IJwtTokenBuilder.cs
delete mode 100644 Falcon.SugarApi/JWT/IServiceCollectionExtend.cs
delete mode 100644 Falcon.SugarApi/JWT/IUserLogin.cs
delete mode 100644 Falcon.SugarApi/JWT/JwtContext.cs
delete mode 100644 Falcon.SugarApi/JWT/JwtTokenBuilder.cs
delete mode 100644 Falcon.SugarApi/JWT/JwtTokenBuilderExtend.cs
delete mode 100644 Falcon.SugarApi/JWT/LoginDto.cs
delete mode 100644 Falcon.SugarApi/JWT/LoginUserInfo.cs
delete mode 100644 Falcon.SugarApi/JWT/TokenDto.cs
delete mode 100644 Falcon.SugarApi/JWT/readme.md
diff --git a/Falcon.SugarApi.Test/JwtTokenBuilderTest.cs b/Falcon.SugarApi.Test/JwtTokenBuilderTest.cs
deleted file mode 100644
index 6a69a56..0000000
--- a/Falcon.SugarApi.Test/JwtTokenBuilderTest.cs
+++ /dev/null
@@ -1,51 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Falcon.SugarApi.JWT;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-
-namespace Falcon.SugarApi.Test
-{
- ///
- /// JwtTokenBuilderTest
- ///
- [TestClass]
- public class JwtTokenBuilderTest
- {
- ///
- /// Token获取测试
- ///
- [TestMethod]
- public void GetTokenTest() {
- var loginTime = DateTime.Now;
- var playload = new LoginUserInfo {
- UserName = "abdc",
- LoginTime = loginTime,
- Roles = new List { "admin", "user" },
- };
- if (new JwtTokenBuilder().TryGetToken(playload, out var token, out var exception)) {
- Console.WriteLine("token:{0}", token);
- }
- else {
- Console.WriteLine(exception.ToString());
- Assert.Fail("获取token失败");
- }
- Assert.IsNotNull(token);
- if (new JwtTokenBuilder().TryGetPlayload(token, out var pl, out var exception1)) {
-
- }
- else {
- Console.WriteLine(exception1.ToString());
- Assert.Fail("获取Playload失败");
- }
- Assert.IsNotNull(pl);
- Assert.AreEqual(playload.UserName, pl.UserName);
- Assert.IsTrue(pl.Roles != null);
- Assert.IsTrue(pl.Roles.Count == 2);
- Assert.IsTrue(pl.Roles.Any(m => m == "admin"));
- Assert.IsTrue(pl.Roles.Any(m => m == "user"));
- }
- }
-}
diff --git a/Falcon.SugarApi/FalconClaim/AddFalconClaimHeaderFilter.cs b/Falcon.SugarApi/FalconClaim/AddFalconClaimHeaderFilter.cs
new file mode 100644
index 0000000..4fafaa3
--- /dev/null
+++ b/Falcon.SugarApi/FalconClaim/AddFalconClaimHeaderFilter.cs
@@ -0,0 +1,44 @@
+using Microsoft.AspNetCore.Mvc.Authorization;
+using Microsoft.OpenApi.Any;
+using Microsoft.OpenApi.Models;
+using Swashbuckle.AspNetCore.SwaggerGen;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Falcon.SugarApi.FalconClaim
+{
+ ///
+ /// 为swagger openapi接口增加验证选项
+ ///
+ public class AddFalconClaimHeaderFilter:IOperationFilter
+ {
+ ///
+ public void Apply(OpenApiOperation operation,OperationFilterContext context) {
+ var filterPipeline = context.ApiDescription.ActionDescriptor.FilterDescriptors;
+ //var isAuthorized = filterPipeline.Select(filterInfo => filterInfo.Filter)
+ // .Any(filter => filter is FalconClaimAuthorizeAttribute);
+
+
+ var metedata = context.ApiDescription.ActionDescriptor.EndpointMetadata;
+ var isAuthorized = metedata.Any(m => m is FalconClaimAuthorizeAttribute);
+ var allowAnonymous = filterPipeline.Select(filterInfo => filterInfo.Filter)
+ .Any(filter => filter is IAllowAnonymousFilter);
+
+ if(isAuthorized && !allowAnonymous) {
+ operation.Parameters = operation.Parameters ?? new List();
+
+ operation.Parameters.Add(new OpenApiParameter {
+ Name = FalconClaimOption.FalconAuthenticationKey,
+ In = ParameterLocation.Header,
+ Description = FalconClaimOption.Description,
+ Required = true,
+ Schema = new OpenApiSchema {
+ Type = "string",
+ Default = new OpenApiString(FalconClaimOption.TokenPrefix),
+ },
+
+ });
+ }
+ }
+ }
+}
diff --git a/Falcon.SugarApi/FalconClaim/AesTokenBuilder.cs b/Falcon.SugarApi/FalconClaim/AesTokenBuilder.cs
new file mode 100644
index 0000000..f0a2c1a
--- /dev/null
+++ b/Falcon.SugarApi/FalconClaim/AesTokenBuilder.cs
@@ -0,0 +1,56 @@
+using Falcon.SugarApi.Encryption;
+using Falcon.SugarApi.JsonSerialize;
+using System.Collections.Generic;
+using System.Linq;
+using System.Security.Claims;
+
+namespace Falcon.SugarApi.FalconClaim
+{
+ ///
+ /// 利用AES生成token
+ ///
+ public class AesTokenBuilder:ITokenBuilter
+ {
+ ///
+ /// 构造基于AES算法的token生成器
+ ///
+ /// aes算法
+ /// json工厂
+ public AesTokenBuilder(IAESEncryption aes,JsonSerializeFactory factory) {
+ Aes = aes;
+ this.Json = factory.CreateJsonSerialize();
+ }
+
+ public IAESEncryption Aes { get; }
+
+ public IJsonSerialize Json { get; set; }
+
+ ///
+ public List? GetClaims(string token) {
+ var str = this.Aes.Decrypt(FalconClaimOption.SecKey,token);
+ if(str.IsNullOrEmpty()) {
+ return new List();
+ }
+ return this.Json.Deserialize>(str)
+ .Select(m => new Claim(m.Type,m.Value)).ToList();
+ }
+
+ ///
+ public string? GetToken(List claims) {
+ var obj = claims.Select(m => new ClaimSerModel(m.Type,m.Value));
+ return this.Aes.Encrypt(FalconClaimOption.SecKey,this.Json.Serialize(obj));
+ }
+ class ClaimSerModel
+ {
+ public ClaimSerModel(string type,string value) {
+ Type = type;
+ Value = value;
+ }
+
+ public string Type { get; set; }
+ public string Value { get; set; }
+ }
+
+ }
+
+}
diff --git a/Falcon.SugarApi/FalconClaim/ClaimsIdentityExtend.cs b/Falcon.SugarApi/FalconClaim/ClaimsIdentityExtend.cs
new file mode 100644
index 0000000..e2c9b77
--- /dev/null
+++ b/Falcon.SugarApi/FalconClaim/ClaimsIdentityExtend.cs
@@ -0,0 +1,23 @@
+using System.Security.Claims;
+
+namespace Falcon.SugarApi.FalconClaim
+{
+ ///
+ /// 身份扩展
+ ///
+ public static class ClaimsIdentityExtend
+ {
+
+ ///
+ /// 象身份中增加声明
+ ///
+ /// 身份
+ /// 声明类型
+ /// 声明值
+ /// 身份
+ public static ClaimsIdentity AddClaim(this ClaimsIdentity cid,string ClaimTypes,string value) {
+ cid.AddClaim(new Claim(ClaimTypes,value));
+ return cid;
+ }
+ }
+}
diff --git a/Falcon.SugarApi/FalconClaim/FalconAuthenticationHandler.cs b/Falcon.SugarApi/FalconClaim/FalconAuthenticationHandler.cs
new file mode 100644
index 0000000..3de4595
--- /dev/null
+++ b/Falcon.SugarApi/FalconClaim/FalconAuthenticationHandler.cs
@@ -0,0 +1,108 @@
+using Microsoft.AspNetCore.Authentication;
+using Microsoft.AspNetCore.Http;
+using System;
+using System.Collections.Generic;
+using System.Net;
+using System.Security.Claims;
+using System.Threading.Tasks;
+
+namespace Falcon.SugarApi.FalconClaim
+{
+ ///
+ /// 自定义验证方式
+ ///
+ public class FalconAuthenticationHandler:IAuthenticationHandler
+ {
+ ///
+ /// 构造自定义身份验证方式
+ ///
+ /// token工具
+ public FalconAuthenticationHandler(ITokenBuilter tokenBuilter) {
+ this.Scheme = null;
+ this.Context = null;
+ TokenBuilter = tokenBuilter;
+ }
+
+ ///
+ /// 验证计划,模式
+ ///
+ public AuthenticationScheme? Scheme { get; set; }
+
+ ///
+ /// HttpContext 上下文
+ ///
+ public HttpContext? Context { get; set; }
+
+ ///
+ public Task AuthenticateAsync() {
+ if(!this.Context.Request.Headers.TryGetValue(FalconClaimOption.FalconAuthenticationKey,out var val)) {
+ return UnLoginResultTask;
+ }
+ var token = val.ToString();
+ if(token.IsNullOrEmpty()) {
+ return UnLoginResultTask;
+ }
+ if(FalconClaimOption.TokenPrefix.IsNotNullOrEmpty() && !token.StartsWith(FalconClaimOption.TokenPrefix)) {
+ return UnLoginResultTask;
+ }
+ try {
+ var ticket = GetTicket(token);
+ if(ticket == null) {
+ return UnLoginResultTask;
+ }
+ return Task.FromResult(AuthenticateResult.Success(ticket));
+ } catch(Exception) {
+ return UnLoginResultTask;
+ }
+ }
+
+ ///
+ public Task ChallengeAsync(AuthenticationProperties? properties) {
+ this.Context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
+ return Task.CompletedTask;
+ }
+
+ ///
+ public Task ForbidAsync(AuthenticationProperties? properties) {
+ this.Context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
+ return Task.CompletedTask;
+ }
+
+ ///
+ public Task InitializeAsync(AuthenticationScheme scheme,HttpContext context) {
+ this.Scheme = scheme; this.Context = context;
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// 根据登录token获取票据
+ ///
+ private AuthenticationTicket? GetTicket(string token) {
+ token.ThrowNullExceptionWhenNull();
+ List? claims = null;
+ try {
+ claims = this.TokenBuilter.GetClaims(token);
+ } catch(Exception) {
+ return null;
+ }
+ if(claims == null || claims.Count == 0) {
+ return null;
+ }
+ var cid = new ClaimsIdentity(FalconClaimOption.SchemeName);
+ cid.AddClaims(claims);
+ var principal = new ClaimsPrincipal(cid);
+ return new AuthenticationTicket(principal,this.Scheme.Name);
+ }
+
+ ///
+ /// 验证失败任务
+ ///
+ //public static Task UnLoginResultTask => throw new ApiDefinistions.ApiException("未登录");
+ public static Task UnLoginResultTask => Task.FromResult(AuthenticateResult.Fail("未登录"));
+
+ ///
+ /// Token工具
+ ///
+ public ITokenBuilter TokenBuilter { get; }
+ }
+}
diff --git a/Falcon.SugarApi/FalconClaim/FalconClaimAuthorizeAttribute.cs b/Falcon.SugarApi/FalconClaim/FalconClaimAuthorizeAttribute.cs
new file mode 100644
index 0000000..16c9e2e
--- /dev/null
+++ b/Falcon.SugarApi/FalconClaim/FalconClaimAuthorizeAttribute.cs
@@ -0,0 +1,27 @@
+using Microsoft.AspNetCore.Authorization;
+
+namespace Falcon.SugarApi.FalconClaim
+{
+ ///
+ /// 根据角色验证
+ ///
+ public class FalconClaimAuthorizeAttribute:AuthorizeAttribute
+ {
+ ///
+ /// 通过提供的角色进行验证
+ ///
+ public FalconClaimAuthorizeAttribute() {
+ base.AuthenticationSchemes = FalconClaimOption.SchemeName;
+ }
+ ///
+ /// 通过提供的角色进行验证
+ ///
+ /// ,号分割的角色列表
+ public FalconClaimAuthorizeAttribute(string roles) {
+ base.AuthenticationSchemes = FalconClaimOption.SchemeName;
+ base.Roles = roles;
+ }
+
+ }
+
+}
diff --git a/Falcon.SugarApi/FalconClaim/FalconClaimOption.cs b/Falcon.SugarApi/FalconClaim/FalconClaimOption.cs
new file mode 100644
index 0000000..ec3af52
--- /dev/null
+++ b/Falcon.SugarApi/FalconClaim/FalconClaimOption.cs
@@ -0,0 +1,40 @@
+using System.Collections.Generic;
+
+namespace Falcon.SugarApi.FalconClaim
+{
+ ///
+ /// FalconClaim验证选项
+ ///
+ public class FalconClaimOption
+ {
+ ///
+ /// 自定义验证方式名
+ ///
+ public static string SchemeName { get; set; } = "FalconClaimSchemeName";
+
+ ///
+ /// 用于提供验证token的键
+ ///
+ public static string FalconAuthenticationKey { get; set; } = "Falcon_WWW_Authenticate";
+
+ ///
+ /// 用于加密的key
+ ///
+ public static string SecKey { get; set; } = "E9319792CB7249AD8E432000E9F2FE7A";
+
+ ///
+ /// 验证头说明
+ ///
+ public static string Description { get; set; } = "FalconClaim验证的Token。";
+
+ ///
+ /// 请求Token前缀
+ ///
+ public static string TokenPrefix { get; set; } = "";
+
+ ///
+ /// 二次认证方法
+ ///
+ public List UserValidates { get; set; } = new List();
+ }
+}
diff --git a/Falcon.SugarApi/FalconClaim/IApplicationBuilderExtend.cs b/Falcon.SugarApi/FalconClaim/IApplicationBuilderExtend.cs
new file mode 100644
index 0000000..57e2ac8
--- /dev/null
+++ b/Falcon.SugarApi/FalconClaim/IApplicationBuilderExtend.cs
@@ -0,0 +1,18 @@
+using Microsoft.AspNetCore.Builder;
+
+namespace Falcon.SugarApi.FalconClaim
+{
+ ///
+ /// 扩展IApplicationBuilder
+ ///
+ public static class IApplicationBuilderExtend
+ {
+ ///
+ /// 使用认证UseAuthentication和授权UseAuthorization。需要加在在UseRouting后UseEndpoints前
+ ///
+ public static IApplicationBuilder UseFalconClaim(this IApplicationBuilder app) {
+ app.UseAuthentication().UseAuthorization();
+ return app;
+ }
+ }
+}
diff --git a/Falcon.SugarApi/FalconClaim/IServiceCollectionExtend.cs b/Falcon.SugarApi/FalconClaim/IServiceCollectionExtend.cs
new file mode 100644
index 0000000..12472c0
--- /dev/null
+++ b/Falcon.SugarApi/FalconClaim/IServiceCollectionExtend.cs
@@ -0,0 +1,33 @@
+using Falcon.SugarApi.Encryption;
+using Falcon.SugarApi.JsonSerialize;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.DependencyInjection.Extensions;
+using System;
+using System.Text.Json;
+
+namespace Falcon.SugarApi.FalconClaim
+{
+ ///
+ /// 扩展IServiceCollection
+ ///
+ public static class IServiceCollectionExtend
+ {
+ ///
+ /// 增加FalconCalom相关服务
+ ///
+ public static IServiceCollection AddFalconClaim(this IServiceCollection services,Action? optionBuilder = null) {
+ optionBuilder?.Invoke(new FalconClaimOption());
+ services.TryAddSingleton();
+ services.TryAddSingleton();
+ services.TryAddSingleton();
+ services.TryAddSingleton();
+ services.AddAuthentication(b => {
+ b.DefaultAuthenticateScheme = FalconClaimOption.SchemeName;
+ b.DefaultChallengeScheme = FalconClaimOption.SchemeName;
+ b.DefaultForbidScheme = FalconClaimOption.SchemeName;
+ b.AddScheme(FalconClaimOption.SchemeName,FalconClaimOption.SchemeName);
+ });
+ return services;
+ }
+ }
+}
diff --git a/Falcon.SugarApi/FalconClaim/ITokenBuilter.cs b/Falcon.SugarApi/FalconClaim/ITokenBuilter.cs
new file mode 100644
index 0000000..5c60568
--- /dev/null
+++ b/Falcon.SugarApi/FalconClaim/ITokenBuilter.cs
@@ -0,0 +1,24 @@
+using System.Collections.Generic;
+using System.Security.Claims;
+
+namespace Falcon.SugarApi.FalconClaim
+{
+ ///
+ /// 通过声明生成token
+ ///
+ public interface ITokenBuilter
+ {
+ ///
+ /// 根据声称组生成token
+ ///
+ /// 一组声明
+ /// token
+ string? GetToken(List claims);
+ ///
+ /// 通过token获取声明组
+ ///
+ /// token
+ /// 声明组
+ List? GetClaims(string token);
+ }
+}
diff --git a/Falcon.SugarApi/FalconClaim/IUserValidate.cs b/Falcon.SugarApi/FalconClaim/IUserValidate.cs
new file mode 100644
index 0000000..657b167
--- /dev/null
+++ b/Falcon.SugarApi/FalconClaim/IUserValidate.cs
@@ -0,0 +1,16 @@
+using System.Security.Claims;
+
+namespace Falcon.SugarApi.FalconClaim
+{
+ ///
+ /// 认证时候提供二次验证方法
+ ///
+ public interface IUserValidate
+ {
+ ///
+ /// 在认证时候提供二次认证的方法
+ ///
+ /// 身份
+ void UserLogin(ClaimsIdentity identity);
+ }
+}
diff --git a/Falcon.SugarApi/FalconClaim/NameClaim.cs b/Falcon.SugarApi/FalconClaim/NameClaim.cs
new file mode 100644
index 0000000..2cf0107
--- /dev/null
+++ b/Falcon.SugarApi/FalconClaim/NameClaim.cs
@@ -0,0 +1,16 @@
+using System.Security.Claims;
+
+namespace Falcon.SugarApi.FalconClaim
+{
+ ///
+ /// 名字声明
+ ///
+ public class NameClaim:Claim
+ {
+ ///
+ /// 提供名字实现名字声明
+ ///
+ /// 名字
+ public NameClaim(string name) : base(ClaimTypes.Name,name) { }
+ }
+}
diff --git a/Falcon.SugarApi/FalconClaim/Readme.md b/Falcon.SugarApi/FalconClaim/Readme.md
new file mode 100644
index 0000000..5f44ba9
--- /dev/null
+++ b/Falcon.SugarApi/FalconClaim/Readme.md
@@ -0,0 +1,7 @@
+FalconClaim 使用说明:
+
+
+1. 用户登录:模块提供了UserLoginModel和UserLoginResult类,分别负责提供登录凭据和登录结果,可以扩展使用,当然也可以使用自己的模型类。
+> 1.通过UserLoginModel提供的凭据验证用户合法性。
+> 2.通过ITokenBuilter.GetToken方法获取登录token。该方法需要一个Claim列表,该列表至少应包含一个name和role声明,表示登录的用户名和角色,也可以根据需要增加其他声明。
+> 3.构造UserLoginResult对象返回token。
\ No newline at end of file
diff --git a/Falcon.SugarApi/FalconClaim/SidClaim.cs b/Falcon.SugarApi/FalconClaim/SidClaim.cs
new file mode 100644
index 0000000..7cdf25a
--- /dev/null
+++ b/Falcon.SugarApi/FalconClaim/SidClaim.cs
@@ -0,0 +1,18 @@
+using System.Security.Claims;
+
+namespace Falcon.SugarApi.FalconClaim
+{
+ ///
+ /// 安全标识声明
+ ///
+ public class SidClaim:Claim
+ {
+
+ ///
+ /// 提供名字实现名字声明
+ ///
+ /// 安全标识
+ public SidClaim(string sid) : base(ClaimTypes.Sid,sid) { }
+
+ }
+}
diff --git a/Falcon.SugarApi/FalconClaim/SwaggerGenOptionsExtend.cs b/Falcon.SugarApi/FalconClaim/SwaggerGenOptionsExtend.cs
new file mode 100644
index 0000000..8b8b2c5
--- /dev/null
+++ b/Falcon.SugarApi/FalconClaim/SwaggerGenOptionsExtend.cs
@@ -0,0 +1,51 @@
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.OpenApi.Models;
+using Swashbuckle.AspNetCore.SwaggerGen;
+using System.Collections.Generic;
+
+namespace Falcon.SugarApi.FalconClaim
+{
+ ///
+ /// SwaggerGenOptions扩展
+ ///
+ public static class SwaggerGenOptionsExtend
+ {
+ ///
+ /// 在swaggerUI中为有FalconClaimAuthorizeAttribute特性的Action增加token头
+ ///
+ /// SwaggerGenOptions
+ /// SwaggerGenOptions
+ public static SwaggerGenOptions AddHeaderForFalconClaim(this SwaggerGenOptions options) {
+ options.OperationFilter();
+ return options;
+ }
+
+ ///
+ /// 在swaggerUI中为所有api请求增加token头
+ ///
+ /// SwaggerGenOptions
+ /// SwaggerGenOptions
+ public static SwaggerGenOptions AddHeaderForAllApi(this SwaggerGenOptions options) {
+ options.AddSecurityDefinition(FalconClaimOption.SchemeName,new OpenApiSecurityScheme {
+ Description = FalconClaimOption.Description,
+ Name = FalconClaimOption.FalconAuthenticationKey,
+ In = ParameterLocation.Header,
+ Type = SecuritySchemeType.ApiKey,
+ Scheme = FalconClaimOption.SchemeName,
+ });
+ options.AddSecurityRequirement(new OpenApiSecurityRequirement {
+ {
+ new OpenApiSecurityScheme
+ {
+ Reference = new OpenApiReference {
+ Type = ReferenceType.SecurityScheme,
+ Id =FalconClaimOption.SchemeName,
+ }
+ },
+ new List()
+ }
+ });
+ return options;
+ }
+ }
+}
diff --git a/Falcon.SugarApi/FalconClaim/UserLoginModel.cs b/Falcon.SugarApi/FalconClaim/UserLoginModel.cs
new file mode 100644
index 0000000..70cf7b5
--- /dev/null
+++ b/Falcon.SugarApi/FalconClaim/UserLoginModel.cs
@@ -0,0 +1,18 @@
+namespace Falcon.SugarApi.FalconClaim
+{
+ ///
+ /// 用户登录凭据模板
+ /// 用于验证用户登录,可以实现自己的类进行验证
+ ///
+ public class UserLoginModel
+ {
+ ///
+ /// 用户名
+ ///
+ public string? UserName { get; set; }
+ ///
+ /// 密码
+ ///
+ public string? Password { get; set; }
+ }
+}
diff --git a/Falcon.SugarApi/FalconClaim/UserLoginResult.cs b/Falcon.SugarApi/FalconClaim/UserLoginResult.cs
new file mode 100644
index 0000000..5270f1e
--- /dev/null
+++ b/Falcon.SugarApi/FalconClaim/UserLoginResult.cs
@@ -0,0 +1,44 @@
+using System;
+
+namespace Falcon.SugarApi.FalconClaim
+{
+ ///
+ /// 用户登录凭据模板
+ /// 登录结果,Token作为票据返回。
+ ///
+ public class UserLoginResult
+ {
+ ///
+ /// 登录结果。成功返回True,失败返回False
+ ///
+ public bool Success { get; set; } = false;
+ ///
+ /// 登录结果信息
+ ///
+ public string? Msg { get; set; }
+ ///
+ /// 登录票据Token
+ ///
+ public string? Token { get; set; }
+ ///
+ /// 登录时间。默认当前系统时间
+ ///
+ public DateTime? LoginTime { get; set; } = DateTime.Now;
+
+ ///
+ /// 获取一条成功的登录信息
+ ///
+ /// 成功登录Token
+ /// 成功登录结果
+ public static UserLoginResult LoginSuccess(string token)
+ => new UserLoginResult { Success = true,Token = token,Msg = "ok" };
+
+ ///
+ /// 登录失败。
+ ///
+ /// 失败原因
+ /// 失败的登录结果
+ public static UserLoginResult LoginFail(string? msg)
+ => new UserLoginResult { Success = false,Msg = msg };
+ }
+}
diff --git a/Falcon.SugarApi/JWT/AESTokenbuilder.cs b/Falcon.SugarApi/JWT/AESTokenbuilder.cs
deleted file mode 100644
index 141f44b..0000000
--- a/Falcon.SugarApi/JWT/AESTokenbuilder.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-using Falcon.SugarApi.Encryption;
-
-namespace Falcon.SugarApi.JWT
-{
- ///
- /// 使用AES算法生成Token
- ///
- public class AESTokenbuilder : IJwtTokenBuilder
- {
- ///
- /// AES加密算法
- ///
- public IAESEncryption AES { get; set; }
- ///
- /// jwt生成参数
- ///
- public JwtContext Jwt { get; }
-
- ///
- /// 构造AES的Token
- ///
- /// AES参数
- /// jwt生成参数
- public AESTokenbuilder(AESConfig config, JwtContext jwt) {
- Jwt = jwt;
- AES = new AESProvider(config);
- }
-
- /// /
- public LoginUserInfo GetPlayload(string token) {
- token.ThrowNullExceptionWhenNull();
- return this.AES.Decrypt(Jwt.SecKey, token);
- }
-
- /// /
- public string GetToken(LoginUserInfo playload) {
- playload.ThrowNullExceptionWhenNull();
- return this.AES.Encrypt(Jwt.SecKey, playload);
- }
- }
-
-}
diff --git a/Falcon.SugarApi/JWT/ApiAuthorizationAttribute.cs b/Falcon.SugarApi/JWT/ApiAuthorizationAttribute.cs
deleted file mode 100644
index 9a908ea..0000000
--- a/Falcon.SugarApi/JWT/ApiAuthorizationAttribute.cs
+++ /dev/null
@@ -1,73 +0,0 @@
-using Microsoft.AspNetCore.Mvc.Authorization;
-using Microsoft.AspNetCore.Mvc.Filters;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.DependencyInjection.Extensions;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Net;
-
-namespace Falcon.SugarApi.JWT
-{
- ///
- /// 验证
- ///
- [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
- public class ApiAuthorizationAttribute : Attribute, IAuthorizationFilter
- {
- ///
- /// 用户需要具有的角色
- ///
- public string[] Roles { get; set; }
-
- ///
- /// 只需要登录即可通过验证
- ///
- public ApiAuthorizationAttribute() {
- this.Roles = new string[] { };
- }
- ///
- /// 需要登录并且具有一定的角色
- ///
- /// 角色组
- public ApiAuthorizationAttribute(params string[] roles) {
- this.Roles = roles;
- }
-
- ///
- public void OnAuthorization(AuthorizationFilterContext context) {
- if (context.Filters.Any(f => f is IAllowAnonymousFilter)) {
- return;
- }
- var option = context.HttpContext.RequestServices.GetRequiredService();
- var key = option?.AuthHeaderKey;
- key.ThrowNullExceptionWhenNull();
- var token = context.HttpContext.Request.Headers[key].ToString();
- if (token.IsNullOrEmpty()) {
- Unauthorized(context);
- return;
- }
- var jwt = option?.JwtTokenBuilder;
- jwt.ThrowNullExceptionWhenNull();
- var user = jwt.GetPlayload(token);
- var userLogin = option?.UserLogin;
- if (userLogin != null && !userLogin.CheckUserLogin(user)) {
- Unauthorized(context);
- return;
- }
- if (this.Roles != null && this.Roles.Length > 0 && !userLogin.UserInRoles(user, this.Roles)) {
- Unauthorized(context);
- return;
- }
- return;
- }
-
- ///
- /// 返回授权失败
- ///
- /// 上下文
- private static void Unauthorized(AuthorizationFilterContext context) {
- context.HttpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
- }
- }
-}
diff --git a/Falcon.SugarApi/JWT/IJwtTokenBuilder.cs b/Falcon.SugarApi/JWT/IJwtTokenBuilder.cs
deleted file mode 100644
index 19ba5e5..0000000
--- a/Falcon.SugarApi/JWT/IJwtTokenBuilder.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-namespace Falcon.SugarApi.JWT
-{
-
- ///
- /// jwt token 生成器
- ///
- public interface IJwtTokenBuilder
- {
- ///
- /// 获取Token负载
- ///
- /// 登录Token
- /// 负载信息
- LoginUserInfo GetPlayload(string token);
- ///
- /// 获取Token
- ///
- /// 负载
- /// Token对象
- string GetToken(LoginUserInfo playload);
- }
-}
\ No newline at end of file
diff --git a/Falcon.SugarApi/JWT/IServiceCollectionExtend.cs b/Falcon.SugarApi/JWT/IServiceCollectionExtend.cs
deleted file mode 100644
index a598a30..0000000
--- a/Falcon.SugarApi/JWT/IServiceCollectionExtend.cs
+++ /dev/null
@@ -1,56 +0,0 @@
-using Falcon.SugarApi.Encryption;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.DependencyInjection.Extensions;
-using System;
-
-namespace Falcon.SugarApi.JWT
-{
- ///
- /// 服务扩展
- ///
- public static class IServiceCollectionExtend
- {
- ///
- /// 注册Falcon.SqlSugar.JWT
- ///
- /// 服务集合
- /// 服务集合
- public static IServiceCollection AddFalconJWT(this IServiceCollection services)
- => services.AddFalconJWT(null);
-
- ///
- /// 注册Falcon.SqlSugar.JWT.JwtContext,并配置相关参数
- /// 消费端通过JwtContext注入
- ///
- /// 服务集合
- /// 参数创建器
- /// 服务集合
- public static IServiceCollection AddFalconJWT(this IServiceCollection services, Action? OptionBuilder) {
- services.AddSingleton(sp => {
- var option = new JwtContext();
- var jtb = sp.GetService();
- if (jtb == null) {
- var aesc = sp.GetService() ?? new AESConfig();
- jtb = new AESTokenbuilder(aesc, option);
- }
- option.JwtTokenBuilder = jtb;
-
- var ulj = sp.GetService();
- if (ulj != null) {
- option.UserLogin = ulj;
- }
-
- OptionBuilder?.Invoke(option);
-
- if (option.UserLogin == null) {
- throw new Exception("必须为JwtOptions提供UserLogin属性!");
- }
- if (option.JwtTokenBuilder == null) {
- throw new Exception("必须为JwtOptions提供JwtTokenBuilder属性!");
- }
- return option;
- });
- return services;
- }
- }
-}
diff --git a/Falcon.SugarApi/JWT/IUserLogin.cs b/Falcon.SugarApi/JWT/IUserLogin.cs
deleted file mode 100644
index a8118db..0000000
--- a/Falcon.SugarApi/JWT/IUserLogin.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-using System.Collections.Generic;
-
-namespace Falcon.SugarApi.JWT
-{
- ///
- /// 用户登录验证接口
- ///
- public interface IUserLogin
- {
- ///
- /// 登录是否成功
- ///
- /// 登录凭据
- /// 成功返回用户信息,否则返回null
- LoginUserInfo? Login(LoginDto login);
-
- ///
- /// 用户登出
- ///
- /// 用户名
- /// True成功,False失败
- bool LogOut(LoginUserInfo userInfo);
-
- ///
- /// 登录用户验证。检查客户端提供的已登录用户是否仍然处于登录中。
- ///
- /// 登录凭据
- /// 登录中返回True,否则返回False
- bool CheckUserLogin(LoginUserInfo userInfo);
-
- ///
- /// 用户是否具有某个角色
- ///
- /// 用户信息
- /// 需要具有的角色组
- /// True具有,False不具有
- bool UserInRoles(LoginUserInfo userInfo, params string[] roles);
- }
-}
diff --git a/Falcon.SugarApi/JWT/JwtContext.cs b/Falcon.SugarApi/JWT/JwtContext.cs
deleted file mode 100644
index 1e8a1c0..0000000
--- a/Falcon.SugarApi/JWT/JwtContext.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-namespace Falcon.SugarApi.JWT
-{
- ///
- /// JWT认证上下文
- ///
- public class JwtContext
- {
- ///
- /// 验证头的键值
- ///
- public string AuthHeaderKey { get; set; } = "auth";
-
- ///
- /// 用户Token加密的秘钥
- ///
- public string SecKey { get; set; } = "fefafwefwf464664f64e64f63";
-
- ///
- /// jwtToken生成器
- ///
- public IJwtTokenBuilder? JwtTokenBuilder { get; set; }
-
- ///
- /// 用户登录管理
- ///
- public IUserLogin? UserLogin { get; set; }
-
- }
-}
diff --git a/Falcon.SugarApi/JWT/JwtTokenBuilder.cs b/Falcon.SugarApi/JWT/JwtTokenBuilder.cs
deleted file mode 100644
index 8016c48..0000000
--- a/Falcon.SugarApi/JWT/JwtTokenBuilder.cs
+++ /dev/null
@@ -1,64 +0,0 @@
-using JWT;
-using JWT.Algorithms;
-using JWT.Serializers;
-using Microsoft.AspNetCore.Server.IIS.Core;
-using System;
-using System.Text;
-
-namespace Falcon.SugarApi.JWT
-{
- ///
- /// jwt token 生成器
- ///
- public class JwtTokenBuilder : IJwtTokenBuilder
- {
- ///
- /// 使用默认配置实例化
- ///
- public JwtTokenBuilder() : this(new JwtContext()) { }
-
- ///
- /// 实例化
- ///
- /// JWT认证配置
- public JwtTokenBuilder(JwtContext options) {
- Options = options;
- }
-
- ///
- /// JWT认证配置
- ///
- public JwtContext Options { get; }
-
- ///
- /// 获取Token
- ///
- /// 负载
- /// Token对象
- public string GetToken(LoginUserInfo playload) {
- playload = playload ?? throw new ArgumentNullException(nameof(playload));
- var key = Encoding.UTF8.GetBytes(this.Options.SecKey);
- var algorithm = new HMACSHA256Algorithm();
- var serializer = new JsonNetSerializer();
- var urlEncoder = new JwtBase64UrlEncoder();
- var encoder = new JwtEncoder(algorithm, serializer, urlEncoder);
- return encoder.Encode(playload, key);
- }
-
- ///
- /// 获取Token负载
- ///
- /// 登录Token
- /// 负载信息
- public LoginUserInfo GetPlayload(string token) {
- var key = Encoding.UTF8.GetBytes(this.Options.SecKey);
- var serializer = new JsonNetSerializer();
- var dtProvider = new UtcDateTimeProvider();
- var validator = new JwtValidator(serializer, dtProvider);
- var urlEncoder = new JwtBase64UrlEncoder();
- var algorithm = new HMACSHA256Algorithm();
- var decoder = new JwtDecoder(serializer, validator, urlEncoder, algorithm);
- return decoder.DecodeToObject(token, key, true);
- }
- }
-}
diff --git a/Falcon.SugarApi/JWT/JwtTokenBuilderExtend.cs b/Falcon.SugarApi/JWT/JwtTokenBuilderExtend.cs
deleted file mode 100644
index b16b5da..0000000
--- a/Falcon.SugarApi/JWT/JwtTokenBuilderExtend.cs
+++ /dev/null
@@ -1,52 +0,0 @@
-using System;
-
-namespace Falcon.SugarApi.JWT
-{
- ///
- /// JwtTokenBuilder扩展
- ///
- public static class JwtTokenBuilderExtend
- {
- ///
- /// 尝试获取Token
- ///
- /// 生成器
- /// 用户信息
- /// 生成的token
- /// 失败异常
- /// 成功True,失败False
- public static bool TryGetToken(this JwtTokenBuilder builder, LoginUserInfo userInfo, out string? token, out Exception? exception) {
- try {
- token = builder.GetToken(userInfo);
- exception = null;
- return true;
- }
- catch (Exception ex) {
- token = null;
- exception = ex;
- return false;
- }
- }
-
- ///
- /// 尝试获取用户信息
- ///
- /// jwt创建器
- /// token
- /// 用户信息
- /// 异常
- /// True成功,False失败
- public static bool TryGetPlayload(this JwtTokenBuilder builder, string token, out LoginUserInfo? userInfo, out Exception? exception) {
- try {
- userInfo = builder.GetPlayload(token);
- exception = null;
- return true;
- }
- catch (Exception ex) {
- userInfo = null;
- exception = ex;
- return false;
- }
- }
- }
-}
diff --git a/Falcon.SugarApi/JWT/LoginDto.cs b/Falcon.SugarApi/JWT/LoginDto.cs
deleted file mode 100644
index 4a7d67e..0000000
--- a/Falcon.SugarApi/JWT/LoginDto.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-namespace Falcon.SugarApi.JWT
-{
- ///
- /// 登录信息
- ///
- public class LoginDto
- {
- ///
- /// 用户名
- ///
- public string UserName { get; set; }
- ///
- /// 密码
- ///
- public string Password { get; set; }
- }
-}
diff --git a/Falcon.SugarApi/JWT/LoginUserInfo.cs b/Falcon.SugarApi/JWT/LoginUserInfo.cs
deleted file mode 100644
index 9ea2c65..0000000
--- a/Falcon.SugarApi/JWT/LoginUserInfo.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-using System;
-using System.Collections.Generic;
-
-namespace Falcon.SugarApi.JWT
-{
- ///
- /// JWT载荷信息
- ///
- public class LoginUserInfo
-
- {
- ///
- /// 登录用户名
- ///
- public string? UserName { get; set; }
- ///
- /// 用户角色
- ///
- public List Roles { get; set; } = new List();
- ///
- /// 其他扩展用户信息
- ///
- public Dictionary UserInfoExtend { get; set; } = new Dictionary();
- ///
- /// 登录时间
- ///
- public DateTime? LoginTime { get; set; }
- }
-}
diff --git a/Falcon.SugarApi/JWT/TokenDto.cs b/Falcon.SugarApi/JWT/TokenDto.cs
deleted file mode 100644
index 0871d21..0000000
--- a/Falcon.SugarApi/JWT/TokenDto.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-namespace Falcon.SugarApi.JWT
-{
- ///
- /// 登录凭据
- ///
- public class TokenDto
- {
- ///
- /// 登录结果
- ///
- public bool Success { get; set; }
- ///
- /// 信息
- ///
- public string Message { get; set; }
- ///
- /// 凭据
- ///
- public string Token { get; set; }
- }
-}
diff --git a/Falcon.SugarApi/JWT/readme.md b/Falcon.SugarApi/JWT/readme.md
deleted file mode 100644
index ecc3437..0000000
--- a/Falcon.SugarApi/JWT/readme.md
+++ /dev/null
@@ -1,7 +0,0 @@
-初始化过程:
-1. 初始化相关表:
-2. 初始化用户系统:检查是否存在用户,如果没有用户插入默认管理员用户,后期可以删除。
-2. 初始化角色系统:
-> 1. 检查系统所有控制器,查询是否标注ApiExplorerSettings特性,如果标注查询是否定义GroupName,不为空则列为角色之一。
-> 2. 检查角色表,如果发现缺少某角色则插入。检查是否存在超管角色,如果不存在则插入
-