1+ using System ;
2+ using System . Collections . Generic ;
3+ using System . Linq ;
4+ using System . Reflection ;
5+ using Microsoft . Extensions . DependencyInjection ;
6+ using Microsoft . OpenApi . Models ;
7+ using SimApi . Attributes ;
8+ using SimApi . ModelBinders ;
9+ using Swashbuckle . AspNetCore . SwaggerGen ;
10+
11+ namespace SimApi . SwaggerFilters ;
12+
13+ public class SimApiSignOperationFilter ( IServiceProvider serviceProvider ) : IOperationFilter
14+ {
15+ public void Apply ( OpenApiOperation operation , OperationFilterContext context )
16+ {
17+ // 1. 检查当前方法或类是否标注了 SimApiSignAttribute 及其子类
18+ var signAttribute = context . MethodInfo . GetCustomAttribute < SimApiSignAttribute > ( inherit : true )
19+ ?? context . MethodInfo . DeclaringType ? . GetCustomAttribute < SimApiSignAttribute > ( inherit : true ) ;
20+
21+ if ( signAttribute == null )
22+ {
23+ return ;
24+ }
25+
26+ var keyProviderType = signAttribute . KeyProvider ;
27+ if ( ! typeof ( SimApiSignProviderBase ) . IsAssignableFrom ( keyProviderType ) )
28+ {
29+ throw new InvalidOperationException ( $ "KeyProvider 必须继承自 { nameof ( SimApiSignProviderBase ) } ") ;
30+ }
31+
32+ SimApiSignProviderBase ? keyProvider ;
33+ try
34+ {
35+ keyProvider =
36+ serviceProvider . CreateScope ( ) . ServiceProvider . GetService ( keyProviderType ) as SimApiSignProviderBase ;
37+ }
38+ catch ( Exception ex )
39+ {
40+ throw new InvalidOperationException ( $ "无法从 DI 容器获取 { keyProviderType . Name } 实例:{ ex . Message } ") ;
41+ }
42+
43+ if ( keyProvider == null )
44+ {
45+ throw new InvalidOperationException ( $ "{ keyProviderType . Name } 未在 DI 容器中注册") ;
46+ }
47+
48+ var signStr = keyProvider . SignFields . Aggregate ( string . Empty , ( current , field ) => current + $ "{ field } =xxx&") ;
49+ if ( ! string . IsNullOrEmpty ( keyProvider . AppIdName ) )
50+ {
51+ signStr += $ "{ keyProvider . AppIdName } =xxx&";
52+ }
53+
54+ signStr += $ "{ keyProvider . TimestampName } =xxx&{ keyProvider . NonceName } =xxx&签名密钥";
55+
56+ var signParameters = new List < ( string Name , string Description , bool Required ) >
57+ {
58+ ( keyProvider . TimestampName , "时间戳(秒级)" , true ) ,
59+ ( keyProvider . NonceName , "随机字符串" , true ) ,
60+ ( keyProvider . SignName , $ "MD5签名结果,签名MD5字符串: { signStr } ", true )
61+ } ;
62+ if ( keyProvider . AppIdName != null )
63+ {
64+ signParameters . Add ( ( keyProvider . AppIdName , "应用标识" , true ) ) ;
65+ }
66+
67+ signParameters . AddRange ( keyProvider . SignFields . Where ( x => x != keyProvider . AppIdName )
68+ . Select ( f => ( f , string . Empty , true ) ) ) ;
69+
70+ foreach ( var ( name , description , required ) in signParameters )
71+ {
72+ if ( operation . Parameters ? . Any ( p => p . Name == name ) == true )
73+ {
74+ var tmp = operation . Parameters ? . FirstOrDefault ( p => p . Name == name ) ;
75+ if ( tmp != null )
76+ {
77+ tmp . Required = required ;
78+ tmp . Description = description ;
79+ }
80+ continue ;
81+ }
82+
83+ operation . Parameters ??= new List < OpenApiParameter > ( ) ;
84+ operation . Parameters . Add ( new OpenApiParameter
85+ {
86+ Name = name ,
87+ In = ParameterLocation . Query , // 指定为 Query 参数
88+ Description = description ,
89+ Required = required ,
90+ Schema = new OpenApiSchema
91+ {
92+ Type = "string" // 签名相关参数通常为字符串类型
93+ }
94+ } ) ;
95+ }
96+ }
97+ }
0 commit comments