飞出JWT,新增FalconClaim用于api的Token认证
This commit is contained in:
		
							parent
							
								
									ce77072812
								
							
						
					
					
						commit
						2488b15532
					
				@ -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
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// JwtTokenBuilderTest
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [TestClass]
 | 
			
		||||
    public class JwtTokenBuilderTest
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Token获取测试
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        [TestMethod]
 | 
			
		||||
        public void GetTokenTest() {
 | 
			
		||||
            var loginTime = DateTime.Now;
 | 
			
		||||
            var playload = new LoginUserInfo {
 | 
			
		||||
                UserName = "abdc",
 | 
			
		||||
                LoginTime = loginTime,
 | 
			
		||||
                Roles = new List<string> { "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"));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										44
									
								
								Falcon.SugarApi/FalconClaim/AddFalconClaimHeaderFilter.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								Falcon.SugarApi/FalconClaim/AddFalconClaimHeaderFilter.cs
									
									
									
									
									
										Normal file
									
								
							@ -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
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 为swagger openapi接口增加验证选项
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class AddFalconClaimHeaderFilter:IOperationFilter
 | 
			
		||||
    {
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        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<OpenApiParameter>();
 | 
			
		||||
 | 
			
		||||
                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),
 | 
			
		||||
                    },
 | 
			
		||||
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										56
									
								
								Falcon.SugarApi/FalconClaim/AesTokenBuilder.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								Falcon.SugarApi/FalconClaim/AesTokenBuilder.cs
									
									
									
									
									
										Normal file
									
								
							@ -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
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 利用AES生成token
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class AesTokenBuilder:ITokenBuilter
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 构造基于AES算法的token生成器
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="aes">aes算法</param>
 | 
			
		||||
        /// <param name="factory">json工厂</param>
 | 
			
		||||
        public AesTokenBuilder(IAESEncryption aes,JsonSerializeFactory factory) {
 | 
			
		||||
            Aes = aes;
 | 
			
		||||
            this.Json = factory.CreateJsonSerialize();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public IAESEncryption Aes { get; }
 | 
			
		||||
 | 
			
		||||
        public IJsonSerialize Json { get; set; }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public List<Claim>? GetClaims(string token) {
 | 
			
		||||
            var str = this.Aes.Decrypt(FalconClaimOption.SecKey,token);
 | 
			
		||||
            if(str.IsNullOrEmpty()) {
 | 
			
		||||
                return new List<Claim>();
 | 
			
		||||
            }
 | 
			
		||||
            return this.Json.Deserialize<List<ClaimSerModel>>(str)
 | 
			
		||||
                .Select(m => new Claim(m.Type,m.Value)).ToList();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public string? GetToken(List<Claim> 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; }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										23
									
								
								Falcon.SugarApi/FalconClaim/ClaimsIdentityExtend.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								Falcon.SugarApi/FalconClaim/ClaimsIdentityExtend.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,23 @@
 | 
			
		||||
using System.Security.Claims;
 | 
			
		||||
 | 
			
		||||
namespace Falcon.SugarApi.FalconClaim
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 身份扩展
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public static class ClaimsIdentityExtend
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 象身份中增加声明
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="cid">身份</param>
 | 
			
		||||
        /// <param name="ClaimTypes">声明类型</param>
 | 
			
		||||
        /// <param name="value">声明值</param>
 | 
			
		||||
        /// <returns>身份</returns>
 | 
			
		||||
        public static ClaimsIdentity AddClaim(this ClaimsIdentity cid,string ClaimTypes,string value) {
 | 
			
		||||
            cid.AddClaim(new Claim(ClaimTypes,value));
 | 
			
		||||
            return cid;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										108
									
								
								Falcon.SugarApi/FalconClaim/FalconAuthenticationHandler.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								Falcon.SugarApi/FalconClaim/FalconAuthenticationHandler.cs
									
									
									
									
									
										Normal file
									
								
							@ -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
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 自定义验证方式
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class FalconAuthenticationHandler:IAuthenticationHandler
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 构造自定义身份验证方式
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="tokenBuilter">token工具</param>
 | 
			
		||||
        public FalconAuthenticationHandler(ITokenBuilter tokenBuilter) {
 | 
			
		||||
            this.Scheme = null;
 | 
			
		||||
            this.Context = null;
 | 
			
		||||
            TokenBuilter = tokenBuilter;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 验证计划,模式
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public AuthenticationScheme? Scheme { get; set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// HttpContext 上下文
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public HttpContext? Context { get; set; }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc />
 | 
			
		||||
        public Task<AuthenticateResult> 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;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc />
 | 
			
		||||
        public Task ChallengeAsync(AuthenticationProperties? properties) {
 | 
			
		||||
            this.Context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
 | 
			
		||||
            return Task.CompletedTask;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc />
 | 
			
		||||
        public Task ForbidAsync(AuthenticationProperties? properties) {
 | 
			
		||||
            this.Context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
 | 
			
		||||
            return Task.CompletedTask;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc />
 | 
			
		||||
        public Task InitializeAsync(AuthenticationScheme scheme,HttpContext context) {
 | 
			
		||||
            this.Scheme = scheme; this.Context = context;
 | 
			
		||||
            return Task.CompletedTask;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 根据登录token获取票据
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private AuthenticationTicket? GetTicket(string token) {
 | 
			
		||||
            token.ThrowNullExceptionWhenNull();
 | 
			
		||||
            List<Claim>? 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);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 验证失败任务
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        //public static Task<AuthenticateResult> UnLoginResultTask => throw new ApiDefinistions.ApiException("未登录");
 | 
			
		||||
        public static Task<AuthenticateResult> UnLoginResultTask => Task.FromResult(AuthenticateResult.Fail("未登录"));
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Token工具
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public ITokenBuilter TokenBuilter { get; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										27
									
								
								Falcon.SugarApi/FalconClaim/FalconClaimAuthorizeAttribute.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								Falcon.SugarApi/FalconClaim/FalconClaimAuthorizeAttribute.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,27 @@
 | 
			
		||||
using Microsoft.AspNetCore.Authorization;
 | 
			
		||||
 | 
			
		||||
namespace Falcon.SugarApi.FalconClaim
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 根据角色验证
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class FalconClaimAuthorizeAttribute:AuthorizeAttribute
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 通过提供的角色进行验证
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public FalconClaimAuthorizeAttribute() {
 | 
			
		||||
            base.AuthenticationSchemes = FalconClaimOption.SchemeName;
 | 
			
		||||
        }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 通过提供的角色进行验证
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="roles">,号分割的角色列表</param>
 | 
			
		||||
        public FalconClaimAuthorizeAttribute(string roles) {
 | 
			
		||||
            base.AuthenticationSchemes = FalconClaimOption.SchemeName;
 | 
			
		||||
            base.Roles = roles;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										40
									
								
								Falcon.SugarApi/FalconClaim/FalconClaimOption.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								Falcon.SugarApi/FalconClaim/FalconClaimOption.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,40 @@
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
 | 
			
		||||
namespace Falcon.SugarApi.FalconClaim
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// FalconClaim验证选项
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class FalconClaimOption
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 自定义验证方式名
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public static string SchemeName { get; set; } = "FalconClaimSchemeName";
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 用于提供验证token的键
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public static string FalconAuthenticationKey { get; set; } = "Falcon_WWW_Authenticate";
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 用于加密的key
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public static string SecKey { get; set; } = "E9319792CB7249AD8E432000E9F2FE7A";
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 验证头说明
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public static string Description { get; set; } = "FalconClaim验证的Token。";
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 请求Token前缀
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public static string TokenPrefix { get; set; } = "";
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 二次认证方法
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public List<IUserValidate> UserValidates { get; set; } = new List<IUserValidate>();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										18
									
								
								Falcon.SugarApi/FalconClaim/IApplicationBuilderExtend.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								Falcon.SugarApi/FalconClaim/IApplicationBuilderExtend.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,18 @@
 | 
			
		||||
using Microsoft.AspNetCore.Builder;
 | 
			
		||||
 | 
			
		||||
namespace Falcon.SugarApi.FalconClaim
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 扩展IApplicationBuilder
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public static class IApplicationBuilderExtend
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 使用认证UseAuthentication和授权UseAuthorization。需要加在在UseRouting后UseEndpoints前
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public static IApplicationBuilder UseFalconClaim(this IApplicationBuilder app) {
 | 
			
		||||
            app.UseAuthentication().UseAuthorization();
 | 
			
		||||
            return app;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										33
									
								
								Falcon.SugarApi/FalconClaim/IServiceCollectionExtend.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								Falcon.SugarApi/FalconClaim/IServiceCollectionExtend.cs
									
									
									
									
									
										Normal file
									
								
							@ -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
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 扩展IServiceCollection
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public static class IServiceCollectionExtend
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 增加FalconCalom相关服务
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public static IServiceCollection AddFalconClaim(this IServiceCollection services,Action<FalconClaimOption>? optionBuilder = null) {
 | 
			
		||||
            optionBuilder?.Invoke(new FalconClaimOption());
 | 
			
		||||
            services.TryAddSingleton<JsonSerializeFactory>();
 | 
			
		||||
            services.TryAddSingleton<ITokenBuilter,AesTokenBuilder>();
 | 
			
		||||
            services.TryAddSingleton<AESConfig>();
 | 
			
		||||
            services.TryAddSingleton<IAESEncryption,AESProvider>();
 | 
			
		||||
            services.AddAuthentication(b => {
 | 
			
		||||
                b.DefaultAuthenticateScheme = FalconClaimOption.SchemeName;
 | 
			
		||||
                b.DefaultChallengeScheme = FalconClaimOption.SchemeName;
 | 
			
		||||
                b.DefaultForbidScheme = FalconClaimOption.SchemeName;
 | 
			
		||||
                b.AddScheme<FalconAuthenticationHandler>(FalconClaimOption.SchemeName,FalconClaimOption.SchemeName);
 | 
			
		||||
            });
 | 
			
		||||
            return services;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										24
									
								
								Falcon.SugarApi/FalconClaim/ITokenBuilter.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								Falcon.SugarApi/FalconClaim/ITokenBuilter.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,24 @@
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Security.Claims;
 | 
			
		||||
 | 
			
		||||
namespace Falcon.SugarApi.FalconClaim
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 通过声明生成token
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public interface ITokenBuilter
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 根据声称组生成token
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="claims">一组声明</param>
 | 
			
		||||
        /// <returns>token</returns>
 | 
			
		||||
        string? GetToken(List<Claim> claims);
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 通过token获取声明组
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="token">token</param>
 | 
			
		||||
        /// <returns>声明组</returns>
 | 
			
		||||
        List<Claim>? GetClaims(string token);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										16
									
								
								Falcon.SugarApi/FalconClaim/IUserValidate.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								Falcon.SugarApi/FalconClaim/IUserValidate.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,16 @@
 | 
			
		||||
using System.Security.Claims;
 | 
			
		||||
 | 
			
		||||
namespace Falcon.SugarApi.FalconClaim
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 认证时候提供二次验证方法
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public interface IUserValidate
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 在认证时候提供二次认证的方法
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="identity">身份</param>
 | 
			
		||||
        void UserLogin(ClaimsIdentity identity);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										16
									
								
								Falcon.SugarApi/FalconClaim/NameClaim.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								Falcon.SugarApi/FalconClaim/NameClaim.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,16 @@
 | 
			
		||||
using System.Security.Claims;
 | 
			
		||||
 | 
			
		||||
namespace Falcon.SugarApi.FalconClaim
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 名字声明
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class NameClaim:Claim
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 提供名字实现名字声明
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="name">名字</param>
 | 
			
		||||
        public NameClaim(string name) : base(ClaimTypes.Name,name) { }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										7
									
								
								Falcon.SugarApi/FalconClaim/Readme.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								Falcon.SugarApi/FalconClaim/Readme.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
			
		||||
FalconClaim 使用说明:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
1. 用户登录:模块提供了UserLoginModel和UserLoginResult类,分别负责提供登录凭据和登录结果,可以扩展使用,当然也可以使用自己的模型类。
 | 
			
		||||
> 1.通过UserLoginModel提供的凭据验证用户合法性。   
 | 
			
		||||
> 2.通过ITokenBuilter.GetToken方法获取登录token。该方法需要一个Claim列表,该列表至少应包含一个name和role声明,表示登录的用户名和角色,也可以根据需要增加其他声明。  
 | 
			
		||||
> 3.构造UserLoginResult对象返回token。
 | 
			
		||||
							
								
								
									
										18
									
								
								Falcon.SugarApi/FalconClaim/SidClaim.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								Falcon.SugarApi/FalconClaim/SidClaim.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,18 @@
 | 
			
		||||
using System.Security.Claims;
 | 
			
		||||
 | 
			
		||||
namespace Falcon.SugarApi.FalconClaim
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 安全标识声明
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class SidClaim:Claim
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 提供名字实现名字声明
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="sid">安全标识</param>
 | 
			
		||||
        public SidClaim(string sid) : base(ClaimTypes.Sid,sid) { }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										51
									
								
								Falcon.SugarApi/FalconClaim/SwaggerGenOptionsExtend.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								Falcon.SugarApi/FalconClaim/SwaggerGenOptionsExtend.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,51 @@
 | 
			
		||||
using Microsoft.Extensions.DependencyInjection;
 | 
			
		||||
using Microsoft.OpenApi.Models;
 | 
			
		||||
using Swashbuckle.AspNetCore.SwaggerGen;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
 | 
			
		||||
namespace Falcon.SugarApi.FalconClaim
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// SwaggerGenOptions扩展
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public static class SwaggerGenOptionsExtend
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 在swaggerUI中为有FalconClaimAuthorizeAttribute特性的Action增加token头
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="options">SwaggerGenOptions</param>
 | 
			
		||||
        /// <returns>SwaggerGenOptions</returns>
 | 
			
		||||
        public static SwaggerGenOptions AddHeaderForFalconClaim(this SwaggerGenOptions options) {
 | 
			
		||||
            options.OperationFilter<AddFalconClaimHeaderFilter>();
 | 
			
		||||
            return options;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 在swaggerUI中为所有api请求增加token头
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="options">SwaggerGenOptions</param>
 | 
			
		||||
        /// <returns>SwaggerGenOptions</returns>
 | 
			
		||||
        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<string>()
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
            return options;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										18
									
								
								Falcon.SugarApi/FalconClaim/UserLoginModel.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								Falcon.SugarApi/FalconClaim/UserLoginModel.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,18 @@
 | 
			
		||||
namespace Falcon.SugarApi.FalconClaim
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 用户登录凭据模板
 | 
			
		||||
    /// <para>用于验证用户登录,可以实现自己的类进行验证</para>
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class UserLoginModel
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 用户名
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public string? UserName { get; set; }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 密码
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public string? Password { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										44
									
								
								Falcon.SugarApi/FalconClaim/UserLoginResult.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								Falcon.SugarApi/FalconClaim/UserLoginResult.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,44 @@
 | 
			
		||||
using System;
 | 
			
		||||
 | 
			
		||||
namespace Falcon.SugarApi.FalconClaim
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 用户登录凭据模板
 | 
			
		||||
    /// <para>登录结果,Token作为票据返回。</para>
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class UserLoginResult
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 登录结果。成功返回True,失败返回False
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public bool Success { get; set; } = false;
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 登录结果信息
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public string? Msg { get; set; }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 登录票据Token
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public string? Token { get; set; }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 登录时间。默认当前系统时间
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public DateTime? LoginTime { get; set; } = DateTime.Now;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 获取一条成功的登录信息
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="token">成功登录Token</param>
 | 
			
		||||
        /// <returns>成功登录结果</returns>
 | 
			
		||||
        public static UserLoginResult LoginSuccess(string token)
 | 
			
		||||
            => new UserLoginResult { Success = true,Token = token,Msg = "ok" };
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 登录失败。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="msg">失败原因</param>
 | 
			
		||||
        /// <returns>失败的登录结果</returns>
 | 
			
		||||
        public static UserLoginResult LoginFail(string? msg)
 | 
			
		||||
           => new UserLoginResult { Success = false,Msg = msg };
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1,42 +0,0 @@
 | 
			
		||||
using Falcon.SugarApi.Encryption;
 | 
			
		||||
 | 
			
		||||
namespace Falcon.SugarApi.JWT
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 使用AES算法生成Token
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class AESTokenbuilder : IJwtTokenBuilder
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// AES加密算法
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public IAESEncryption AES { get; set; }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// jwt生成参数
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public JwtContext Jwt { get; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 构造AES的Token
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="config">AES参数</param>
 | 
			
		||||
        /// <param name="jwt">jwt生成参数</param>
 | 
			
		||||
        public AESTokenbuilder(AESConfig config, JwtContext jwt) {
 | 
			
		||||
            Jwt = jwt;
 | 
			
		||||
            AES = new AESProvider(config);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc>/
 | 
			
		||||
        public LoginUserInfo GetPlayload(string token) {
 | 
			
		||||
            token.ThrowNullExceptionWhenNull();
 | 
			
		||||
            return this.AES.Decrypt<LoginUserInfo>(Jwt.SecKey, token);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc>/
 | 
			
		||||
        public string GetToken(LoginUserInfo playload) {
 | 
			
		||||
            playload.ThrowNullExceptionWhenNull();
 | 
			
		||||
            return this.AES.Encrypt(Jwt.SecKey, playload);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -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
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 验证
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
 | 
			
		||||
    public class ApiAuthorizationAttribute : Attribute, IAuthorizationFilter
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 用户需要具有的角色
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public string[] Roles { get; set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 只需要登录即可通过验证
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public ApiAuthorizationAttribute() {
 | 
			
		||||
            this.Roles = new string[] { };
 | 
			
		||||
        }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 需要登录并且具有一定的角色
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="roles">角色组</param>
 | 
			
		||||
        public ApiAuthorizationAttribute(params string[] roles) {
 | 
			
		||||
            this.Roles = roles;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public void OnAuthorization(AuthorizationFilterContext context) {
 | 
			
		||||
            if (context.Filters.Any(f => f is IAllowAnonymousFilter)) {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            var option = context.HttpContext.RequestServices.GetRequiredService<JwtContext>();
 | 
			
		||||
            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;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 返回授权失败
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="context">上下文</param>
 | 
			
		||||
        private static void Unauthorized(AuthorizationFilterContext context) {
 | 
			
		||||
            context.HttpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1,22 +0,0 @@
 | 
			
		||||
namespace Falcon.SugarApi.JWT
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// jwt token 生成器
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public interface IJwtTokenBuilder
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 获取Token负载
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="token">登录Token</param>
 | 
			
		||||
        /// <returns>负载信息</returns>
 | 
			
		||||
        LoginUserInfo GetPlayload(string token);
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 获取Token
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="playload">负载</param>
 | 
			
		||||
        /// <returns>Token对象</returns>
 | 
			
		||||
        string GetToken(LoginUserInfo playload);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1,56 +0,0 @@
 | 
			
		||||
using Falcon.SugarApi.Encryption;
 | 
			
		||||
using Microsoft.Extensions.DependencyInjection;
 | 
			
		||||
using Microsoft.Extensions.DependencyInjection.Extensions;
 | 
			
		||||
using System;
 | 
			
		||||
 | 
			
		||||
namespace Falcon.SugarApi.JWT
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 服务扩展
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public static class IServiceCollectionExtend
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 注册Falcon.SqlSugar.JWT
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="services">服务集合</param>
 | 
			
		||||
        /// <returns>服务集合</returns>
 | 
			
		||||
        public static IServiceCollection AddFalconJWT(this IServiceCollection services)
 | 
			
		||||
            => services.AddFalconJWT(null);
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 注册Falcon.SqlSugar.JWT.JwtContext,并配置相关参数
 | 
			
		||||
        /// <para>消费端通过JwtContext注入</para>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="services">服务集合</param>
 | 
			
		||||
        /// <param name="OptionBuilder">参数创建器</param>
 | 
			
		||||
        /// <returns>服务集合</returns>
 | 
			
		||||
        public static IServiceCollection AddFalconJWT(this IServiceCollection services, Action<JwtContext>? OptionBuilder) {
 | 
			
		||||
            services.AddSingleton<JwtContext>(sp => {
 | 
			
		||||
                var option = new JwtContext();
 | 
			
		||||
                var jtb = sp.GetService<IJwtTokenBuilder>();
 | 
			
		||||
                if (jtb == null) {
 | 
			
		||||
                    var aesc = sp.GetService<AESConfig>() ?? new AESConfig();
 | 
			
		||||
                    jtb = new AESTokenbuilder(aesc, option);
 | 
			
		||||
                }
 | 
			
		||||
                option.JwtTokenBuilder = jtb;
 | 
			
		||||
 | 
			
		||||
                var ulj = sp.GetService<IUserLogin>();
 | 
			
		||||
                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;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1,39 +0,0 @@
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
 | 
			
		||||
namespace Falcon.SugarApi.JWT
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 用户登录验证接口
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public interface IUserLogin
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 登录是否成功
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="login">登录凭据</param>
 | 
			
		||||
        /// <returns>成功返回用户信息,否则返回null</returns>
 | 
			
		||||
        LoginUserInfo? Login(LoginDto login);
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 用户登出
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="userInfo">用户名</param>
 | 
			
		||||
        /// <returns>True成功,False失败</returns>
 | 
			
		||||
        bool LogOut(LoginUserInfo userInfo);
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 登录用户验证。检查客户端提供的已登录用户是否仍然处于登录中。
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="userInfo">登录凭据</param>
 | 
			
		||||
        /// <returns>登录中返回True,否则返回False</returns>
 | 
			
		||||
        bool CheckUserLogin(LoginUserInfo userInfo);
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 用户是否具有某个角色
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="userInfo">用户信息</param>
 | 
			
		||||
        /// <param name="roles">需要具有的角色组</param>
 | 
			
		||||
        /// <returns>True具有,False不具有</returns>
 | 
			
		||||
        bool UserInRoles(LoginUserInfo userInfo, params string[] roles);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1,29 +0,0 @@
 | 
			
		||||
namespace Falcon.SugarApi.JWT
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// JWT认证上下文
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class JwtContext
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 验证头的键值
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public string AuthHeaderKey { get; set; } = "auth";
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 用户Token加密的秘钥
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public string SecKey { get; set; } = "fefafwefwf464664f64e64f63";
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// jwtToken生成器
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public IJwtTokenBuilder? JwtTokenBuilder { get; set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 用户登录管理
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public IUserLogin? UserLogin { get; set; }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -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
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// jwt token 生成器
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class JwtTokenBuilder : IJwtTokenBuilder
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 使用默认配置实例化
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public JwtTokenBuilder() : this(new JwtContext()) { }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 实例化
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="options">JWT认证配置</param>
 | 
			
		||||
        public JwtTokenBuilder(JwtContext options) {
 | 
			
		||||
            Options = options;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// JWT认证配置
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public JwtContext Options { get; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 获取Token
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="playload">负载</param>
 | 
			
		||||
        /// <returns>Token对象</returns>
 | 
			
		||||
        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);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 获取Token负载
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="token">登录Token</param>
 | 
			
		||||
        /// <returns>负载信息</returns>
 | 
			
		||||
        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<LoginUserInfo>(token, key, true);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1,52 +0,0 @@
 | 
			
		||||
using System;
 | 
			
		||||
 | 
			
		||||
namespace Falcon.SugarApi.JWT
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// JwtTokenBuilder扩展
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public static class JwtTokenBuilderExtend
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 尝试获取Token
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="builder">生成器</param>
 | 
			
		||||
        /// <param name="userInfo">用户信息</param>
 | 
			
		||||
        /// <param name="token">生成的token</param>
 | 
			
		||||
        /// <param name="exception">失败异常</param>
 | 
			
		||||
        /// <returns>成功True,失败False</returns>
 | 
			
		||||
        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;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 尝试获取用户信息
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="builder">jwt创建器</param>
 | 
			
		||||
        /// <param name="token">token</param>
 | 
			
		||||
        /// <param name="userInfo">用户信息</param>
 | 
			
		||||
        /// <param name="exception">异常</param>
 | 
			
		||||
        /// <returns>True成功,False失败</returns>
 | 
			
		||||
        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;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1,17 +0,0 @@
 | 
			
		||||
namespace Falcon.SugarApi.JWT
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 登录信息
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class LoginDto
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 用户名
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public string UserName { get; set; }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 密码
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public string Password { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1,29 +0,0 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
 | 
			
		||||
namespace Falcon.SugarApi.JWT
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// JWT载荷信息
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class LoginUserInfo
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 登录用户名
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public string? UserName { get; set; }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 用户角色
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public List<string> Roles { get; set; } = new List<string>();
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 其他扩展用户信息
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public Dictionary<string, object> UserInfoExtend { get; set; } = new Dictionary<string, object>();
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 登录时间
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public DateTime? LoginTime { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1,21 +0,0 @@
 | 
			
		||||
namespace Falcon.SugarApi.JWT
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 登录凭据
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class TokenDto
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 登录结果
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public bool Success { get; set; }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 信息
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public string Message { get; set; }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 凭据
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public string Token { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1,7 +0,0 @@
 | 
			
		||||
初始化过程:
 | 
			
		||||
1. 初始化相关表:
 | 
			
		||||
2. 初始化用户系统:检查是否存在用户,如果没有用户插入默认管理员用户,后期可以删除。
 | 
			
		||||
2. 初始化角色系统:   
 | 
			
		||||
> 1. 检查系统所有控制器,查询是否标注ApiExplorerSettings特性,如果标注查询是否定义GroupName,不为空则列为角色之一。    
 | 
			
		||||
> 2. 检查角色表,如果发现缺少某角色则插入。检查是否存在超管角色,如果不存在则插入
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user