1
1
package org .lowcoder .api .framework .plugin .endpoint ;
2
2
3
+ import static org .lowcoder .sdk .exception .BizError .NOT_AUTHORIZED ;
3
4
import static org .springframework .web .reactive .function .server .RequestPredicates .DELETE ;
4
5
import static org .springframework .web .reactive .function .server .RequestPredicates .GET ;
5
6
import static org .springframework .web .reactive .function .server .RequestPredicates .OPTIONS ;
8
9
import static org .springframework .web .reactive .function .server .RequestPredicates .PUT ;
9
10
import static org .springframework .web .reactive .function .server .RouterFunctions .route ;
10
11
12
+ import java .lang .reflect .AccessibleObject ;
11
13
import java .lang .reflect .InvocationTargetException ;
12
14
import java .lang .reflect .Method ;
13
15
import java .util .ArrayList ;
16
+ import java .util .Collections ;
14
17
import java .util .List ;
15
18
19
+ import org .aopalliance .intercept .MethodInvocation ;
16
20
import org .apache .commons .collections4 .CollectionUtils ;
17
21
import org .apache .commons .lang3 .StringUtils ;
22
+ import org .jetbrains .annotations .NotNull ;
23
+ import org .jetbrains .annotations .Nullable ;
18
24
import org .lowcoder .api .framework .plugin .data .PluginServerRequest ;
25
+ import org .lowcoder .api .framework .plugin .security .PluginAuthorizationManager ;
19
26
import org .lowcoder .api .framework .plugin .security .SecuredEndpoint ;
20
27
import org .lowcoder .plugin .api .EndpointExtension ;
21
28
import org .lowcoder .plugin .api .PluginEndpoint ;
22
29
import org .lowcoder .plugin .api .data .EndpointRequest ;
23
30
import org .lowcoder .plugin .api .data .EndpointResponse ;
24
31
import org .lowcoder .sdk .exception .BaseException ;
32
+ import org .lowcoder .sdk .exception .BizException ;
25
33
import org .springframework .aop .TargetSource ;
26
34
import org .springframework .aop .framework .ProxyFactoryBean ;
35
+ import org .springframework .aop .framework .ReflectiveMethodInvocation ;
27
36
import org .springframework .aop .target .SimpleBeanTargetSource ;
28
37
import org .springframework .beans .factory .support .DefaultListableBeanFactory ;
29
38
import org .springframework .context .ApplicationContext ;
30
39
import org .springframework .context .support .GenericApplicationContext ;
31
40
import org .springframework .core .ResolvableType ;
32
41
import org .springframework .http .ResponseCookie ;
33
42
import org .springframework .security .access .prepost .PreAuthorize ;
43
+ import org .springframework .security .authentication .UsernamePasswordAuthenticationToken ;
44
+ import org .springframework .security .authorization .AuthorizationDecision ;
45
+ import org .springframework .security .core .Authentication ;
34
46
import org .springframework .security .core .context .ReactiveSecurityContextHolder ;
47
+ import org .springframework .security .core .context .SecurityContext ;
35
48
import org .springframework .stereotype .Component ;
36
49
import org .springframework .web .reactive .function .server .RequestPredicate ;
37
50
import org .springframework .web .reactive .function .server .RouterFunction ;
@@ -52,6 +65,7 @@ public class PluginEndpointHandlerImpl implements PluginEndpointHandler
52
65
53
66
private final ApplicationContext applicationContext ;
54
67
private final DefaultListableBeanFactory beanFactory ;
68
+ private final PluginAuthorizationManager pluginAuthorizationManager ;
55
69
56
70
@ Override
57
71
public void registerEndpoints (String pluginUrlPrefix , List <PluginEndpoint > endpoints )
@@ -101,26 +115,69 @@ private void registerEndpointHandler(String urlPrefix, PluginEndpoint endpoint,
101
115
102
116
log .info ("Registered endpoint: {} -> {}: {}" , endpoint .getClass ().getSimpleName (), endpointMeta .method (), urlPrefix + endpointMeta .uri ());
103
117
}
104
-
105
- @ SecuredEndpoint
118
+
106
119
public Mono <ServerResponse > runPluginEndpointMethod (PluginEndpoint endpoint , EndpointExtension endpointMeta , Method handler , ServerRequest request )
107
120
{
108
- Mono <ServerResponse > result = null ;
109
- try
110
- {
111
- log .info ("Running plugin endpoint method {}\n Request: {}" , handler .getName (), request );
121
+ log .info ("Running plugin endpoint method {}\n Request: {}" , handler .getName (), request );
112
122
113
- EndpointResponse response = (EndpointResponse )handler .invoke (endpoint , PluginServerRequest .fromServerRequest (request ));
114
- result = createServerResponse (response );
115
- }
116
- catch (IllegalAccessException | InvocationTargetException cause )
117
- {
118
- throw new BaseException ("Error running handler for [ " + endpointMeta .method () + ": " + endpointMeta .uri () + "] !" );
119
- }
120
- return result ;
123
+ Mono <Authentication > monoAuthentication = ReactiveSecurityContextHolder .getContext ().map (SecurityContext ::getAuthentication ).cache ();
124
+ Mono <AuthorizationDecision > decisionMono = monoAuthentication .flatMap (authentication -> {
125
+ MethodInvocation methodInvocation = null ;
126
+ try {
127
+ methodInvocation = getMethodInvocation (endpointMeta , authentication );
128
+ } catch (NoSuchMethodException e ) {
129
+ return Mono .error (new RuntimeException (e ));
130
+ }
131
+ return pluginAuthorizationManager .check (monoAuthentication , methodInvocation );
132
+ });
133
+
134
+ return decisionMono .<EndpointResponse >handle ((authorizationDecision , sink ) -> {
135
+ if (!authorizationDecision .isGranted ()) sink .error (new BizException (NOT_AUTHORIZED , "NOT_AUTHORIZED" ));
136
+ try {
137
+ sink .next ((EndpointResponse ) handler .invoke (endpoint , PluginServerRequest .fromServerRequest (request )));
138
+ } catch (IllegalAccessException | InvocationTargetException e ) {
139
+ sink .error (new RuntimeException (e ));
140
+ }
141
+ }).flatMap (this ::createServerResponse );
121
142
}
122
-
123
-
143
+
144
+ private static @ NotNull MethodInvocation getMethodInvocation (EndpointExtension endpointMeta , Authentication authentication ) throws NoSuchMethodException {
145
+ Method method = Authentication .class .getMethod ("isAuthenticated" );
146
+ Object [] arguments = new Object []{"someString" , endpointMeta };
147
+ return new MethodInvocation () {
148
+ @ NotNull
149
+ @ Override
150
+ public Method getMethod () {
151
+ return method ;
152
+ }
153
+
154
+ @ NotNull
155
+ @ Override
156
+ public Object [] getArguments () {
157
+ return arguments ;
158
+ }
159
+
160
+ @ Nullable
161
+ @ Override
162
+ public Object proceed () throws Throwable {
163
+ return null ;
164
+ }
165
+
166
+ @ Nullable
167
+ @ Override
168
+ public Object getThis () {
169
+ return authentication ;
170
+ }
171
+
172
+ @ NotNull
173
+ @ Override
174
+ public AccessibleObject getStaticPart () {
175
+ return null ;
176
+ }
177
+ };
178
+ }
179
+
180
+
124
181
private void registerRouterFunctionMapping (String endpointName , RouterFunction <ServerResponse > routerFunction )
125
182
{
126
183
String beanName = "pluginEndpoint_" + endpointName + "_" + System .currentTimeMillis ();
0 commit comments