Compare commits

...
2 Commits
4 changed files with 78 additions and 39 deletions
+4 -9
View File
@@ -13,13 +13,13 @@ namespace SimApi.Attributes;
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class SimApiAuthAttribute : ActionFilterAttribute public class SimApiAuthAttribute : ActionFilterAttribute
{ {
private string[] Types { get; } private string[]? Types { get; }
//默认是user登录类型 //默认是user登录类型
public SimApiAuthAttribute() public SimApiAuthAttribute()
{ {
Types = new[] { "user" }; Types = null;
} }
//只检测一种用户类型的快捷方式 //只检测一种用户类型的快捷方式
@@ -34,13 +34,6 @@ public class SimApiAuthAttribute : ActionFilterAttribute
Types = types; Types = types;
} }
//只检测一种用户类型的快捷方式
public SimApiAuthAttribute(string type, string url)
{
Types = new[] { type };
new HttpPostAttribute(url);
}
public override void OnActionExecuting(ActionExecutingContext context) public override void OnActionExecuting(ActionExecutingContext context)
{ {
var loginInfo = (SimApiLoginItem)context.HttpContext.Items["LoginInfo"]!; var loginInfo = (SimApiLoginItem)context.HttpContext.Items["LoginInfo"]!;
@@ -49,6 +42,8 @@ public class SimApiAuthAttribute : ActionFilterAttribute
{ {
throw new SimApiException(401); throw new SimApiException(401);
} }
if (Types == null) return;
//检测用户类型 //检测用户类型
if (!Types.Intersect(loginInfo.Type).Any()) if (!Types.Intersect(loginInfo.Type).Any())
{ {
+2 -2
View File
@@ -23,8 +23,8 @@
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="10.0.1" /> <PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="10.0.1" />
<PackageReference Include="Minio" Version="7.0.0" /> <PackageReference Include="Minio" Version="7.0.0" />
<PackageReference Include="MQTTnet" Version="5.0.1.1416"/> <PackageReference Include="MQTTnet" Version="5.0.1.1416"/>
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="10.0.1" /> <PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="10.1.0" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="10.0.1" /> <PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="10.1.0" />
</ItemGroup> </ItemGroup>
<ProjectExtensions> <ProjectExtensions>
<MonoDevelop> <MonoDevelop>
+70 -14
View File
@@ -124,7 +124,75 @@ public static class SimApiExtensions
}); });
} }
x.CustomSchemaIds(type => type.FullName?.Replace("+", ".")); x.CustomSchemaIds(type =>
{
// 递归解析类型名称(处理嵌套泛型/数组/可空 + 保证唯一性)
string GetSimpleTypeName(Type t, int depth = 0)
{
// 防止无限递归
if (depth > 5) return t.Name.Split('`')[0];
// 处理数组类型
if (t.IsArray)
{
var elementType = t.GetElementType();
return $"{GetSimpleTypeName(elementType, depth + 1)}[]";
}
// 处理可空类型
if (Nullable.GetUnderlyingType(t) != null)
{
var underlyingType = Nullable.GetUnderlyingType(t);
return GetSimpleTypeName(underlyingType, depth + 1);
}
// 处理泛型类型(递归解析嵌套泛型)
if (t.IsGenericType)
{
var genericBaseName = t.GetGenericTypeDefinition().Name.Split('`')[0];
var genericArgs = t.GetGenericArguments()
.Select(arg => GetSimpleTypeName(arg, depth + 1))
.Where(arg => !string.IsNullOrEmpty(arg))
.ToArray();
return $"{genericBaseName}<{string.Join(",", genericArgs)}>";
}
// 处理基础类型(小写)
if (t.IsPrimitive || t == typeof(string) || t == typeof(DateTime) || t == typeof(Guid))
{
return t.Name switch
{
"String" => "string",
"Int32" => "int",
"Int64" => "long",
"Boolean" => "boolean",
"DateTime" => "datetime",
"Guid" => "guid",
_ => t.Name.ToLower()
};
}
// 核心修复:生成唯一名称(处理嵌套类/同名不同类)
var typeName = t.Name;
// 步骤1:处理嵌套类(如 ApplicationDto+ApplicationEditRequest → ApplicationDto_ApplicationEditRequest
if (t.DeclaringType != null)
{
typeName = $"{GetSimpleTypeName(t.DeclaringType)}.{typeName}";
}
// 步骤2:(可选)处理同命名空间下的同名类(拼接命名空间前缀,避免全局重复)
// 如需更严格的唯一性,取消注释下面这行
// typeName = $"{t.Namespace?.Replace(".", "_")}_{typeName}";
return typeName;
}
// 根调用:解析当前类型
var uniqueSchemaId = GetSimpleTypeName(type);
// 可选:移除特殊字符(如 $、+),避免 Swagger 解析问题
return uniqueSchemaId.Replace("$", "").Replace("+", "_");
});
x.OperationFilter<SimApiResponseOperationFilter>(); x.OperationFilter<SimApiResponseOperationFilter>();
x.OperationFilter<SimApiSignOperationFilter>(); x.OperationFilter<SimApiSignOperationFilter>();
x.OperationFilter<AesBodyOperationFilter>(); x.OperationFilter<AesBodyOperationFilter>();
@@ -159,19 +227,13 @@ public static class SimApiExtensions
switch (auth) switch (auth)
{ {
case "SimApiAuth": case "SimApiAuth":
x.AddSecurityDefinition("HeaderToken", x.AddSecurityDefinition("SimApiAuth",
new OpenApiSecurityScheme new OpenApiSecurityScheme
{ {
Name = "Token", Name = "Token",
In = ParameterLocation.Header, In = ParameterLocation.Header,
Type = SecuritySchemeType.ApiKey Type = SecuritySchemeType.ApiKey
}); });
x.AddSecurityRequirement(docs => new OpenApiSecurityRequirement
{
{
new OpenApiSecuritySchemeReference("HeaderToken"), new List<string>()
}
});
break; break;
case "ClientCredentials": case "ClientCredentials":
oauthFlows.ClientCredentials = new OpenApiOAuthFlow oauthFlows.ClientCredentials = new OpenApiOAuthFlow
@@ -220,12 +282,6 @@ public static class SimApiExtensions
Description = docOptions.ApiAuth.Description, Description = docOptions.ApiAuth.Description,
In = ParameterLocation.Header In = ParameterLocation.Header
}); });
x.AddSecurityRequirement(docs => new OpenApiSecurityRequirement
{
{
new OpenApiSecuritySchemeReference("oauth2"), new List<string>()
}
});
} }
}); });
} }
+2 -14
View File
@@ -19,22 +19,10 @@ namespace SimApi.SwaggerFilters
// 控制器上有 [SimApiAuth](继承到所有方法) // 控制器上有 [SimApiAuth](继承到所有方法)
context.MethodInfo.DeclaringType?.GetCustomAttributes<SimApiAuthAttribute>(true).Any() == true; context.MethodInfo.DeclaringType?.GetCustomAttributes<SimApiAuthAttribute>(true).Any() == true;
if (!requiresAuth) return; if (!requiresAuth) return;
// 关键修复:正确构造 OpenApiSecuritySchemeReference(匹配键类型要求)
var securitySchemeRef = new OpenApiSecuritySchemeReference(
referenceId: "SimApiAuth", // 必须与 AddSecurityDefinition 的 ID 一致
hostDocument: null,
externalResource: null
);
// 给 Security 赋值(确保键类型是 OpenApiSecuritySchemeReference
operation.Security ??= new List<OpenApiSecurityRequirement>(); operation.Security ??= new List<OpenApiSecurityRequirement>();
operation.Security.Add(new OpenApiSecurityRequirement operation.Security.Add(new OpenApiSecurityRequirement()
{ {
{ { new OpenApiSecuritySchemeReference("SimApiAuth", context.Document), [] }
securitySchemeRef,
[]
}
}); });
} }
} }