Skip to content

Commit 9a02215

Browse files
SaberSolazhanglei06469
andauthored
[type:refactor] add an authentication on shenyu admin when register by http (#2723)
* fix ShenyuClientRegisterService buildHandle method * fix init ratelimiter redis script thread safe * add accessToken when use http register center * add accessToken when use http register center * add accessToken when use http register center * Long polling with admin token * merge master * remove white path * fix config Co-authored-by: zhanglei06469 <zhanglei06469@hellobike.com>
1 parent 6ca0074 commit 9a02215

40 files changed

Lines changed: 627 additions & 56 deletions

File tree

shenyu-admin/src/main/java/org/apache/shenyu/admin/shiro/bean/StatelessAuthFilter.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import org.apache.commons.lang3.StringUtils;
2121
import org.apache.shenyu.admin.model.result.ShenyuAdminResult;
2222
import org.apache.shenyu.admin.utils.ShenyuResultMessage;
23+
import org.apache.shenyu.common.constant.Constants;
2324
import org.apache.shenyu.common.exception.CommonErrorCode;
2425
import org.apache.shenyu.common.utils.GsonUtils;
2526
import org.apache.shiro.subject.Subject;
@@ -41,8 +42,6 @@ public class StatelessAuthFilter extends AccessControlFilter {
4142

4243
private static final Logger LOG = LoggerFactory.getLogger(StatelessAuthFilter.class);
4344

44-
private static final String HEAD_TOKEN = "X-Access-Token";
45-
4645
@Override
4746
protected boolean isAccessAllowed(final ServletRequest servletRequest,
4847
final ServletResponse servletResponse,
@@ -58,7 +57,7 @@ protected boolean onAccessDenied(final ServletRequest servletRequest,
5857
return true;
5958
}
6059

61-
String tokenValue = httpServletRequest.getHeader(HEAD_TOKEN);
60+
String tokenValue = httpServletRequest.getHeader(Constants.X_ACCESS_TOKEN);
6261
if (StringUtils.isBlank(tokenValue)) {
6362
LOG.error("token is null.");
6463
unionFailResponse(servletResponse);

shenyu-admin/src/main/resources/application.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,6 @@ shenyu:
8888
- /index**
8989
- /platform/login
9090
- /websocket
91-
- /configs/**
92-
- /shenyu-client/**
9391
- /error
9492
- /actuator/health
9593
- /swagger-ui.html

shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/shutdown/ShenyuClientShutdownHook.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import java.util.concurrent.TimeUnit;
2626
import java.util.concurrent.atomic.AtomicBoolean;
2727
import java.util.concurrent.atomic.AtomicInteger;
28+
2829
import org.apache.shenyu.register.client.api.ShenyuClientRegisterRepository;
2930
import org.apache.shenyu.register.common.config.ShenyuRegisterCenterConfig;
3031
import org.slf4j.Logger;
@@ -49,10 +50,11 @@ public class ShenyuClientShutdownHook {
4950

5051
private static IdentityHashMap<Thread, Thread> delayedHooks = new IdentityHashMap<>();
5152

52-
public ShenyuClientShutdownHook() { }
53+
public ShenyuClientShutdownHook() {
54+
}
5355

5456
public ShenyuClientShutdownHook(final ShenyuClientRegisterRepository repository, final ShenyuRegisterCenterConfig config) {
55-
String name = hookNamePrefix + "-" + hookId.incrementAndGet();
57+
String name = String.join("-", hookNamePrefix, String.valueOf(hookId.incrementAndGet()));
5658
Runtime.getRuntime().addShutdownHook(new Thread(repository::close, name));
5759
LOG.info("Add hook {}", name);
5860
ShenyuClientShutdownHook.props = config.getProps();
@@ -65,7 +67,7 @@ public ShenyuClientShutdownHook(final ShenyuClientRegisterRepository repository,
6567
* @param props Properties
6668
*/
6769
public static void set(final ShenyuClientRegisterRepository result, final Properties props) {
68-
String name = hookNamePrefix + "-" + hookId.incrementAndGet();
70+
String name = String.join("-", hookNamePrefix, String.valueOf(hookId.incrementAndGet()));
6971
Runtime.getRuntime().addShutdownHook(new Thread(result::close, name));
7072
LOG.info("Add hook {}", name);
7173
ShenyuClientShutdownHook.props = props;
@@ -113,7 +115,8 @@ public void run() {
113115
LOG.info("sleep {}ms", shutdownWaitTime);
114116
try {
115117
TimeUnit.MILLISECONDS.sleep(shutdownWaitTime);
116-
} catch (InterruptedException ignore) { }
118+
} catch (InterruptedException ignore) {
119+
}
117120
hook.run();
118121
}, hook.getName());
119122
delayHooks.put(delayHook, delayHook);

shenyu-client/shenyu-client-http/shenyu-client-springcloud/src/test/java/org/apache/shenyu/client/springcloud/init/SpringCloudClientBeanPostProcessorTest.java

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import org.springframework.web.bind.annotation.RequestMapping;
3838
import org.springframework.web.bind.annotation.RestController;
3939

40+
import java.util.Optional;
4041
import java.util.Properties;
4142

4243
import static org.hamcrest.Matchers.equalTo;
@@ -51,9 +52,12 @@
5152
@RunWith(MockitoJUnitRunner.class)
5253
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
5354
public final class SpringCloudClientBeanPostProcessorTest {
55+
5456
@Mock
5557
private static Environment env;
5658

59+
private MockedStatic<RegisterUtils> registerUtilsMockedStatic = mockStatic(RegisterUtils.class);
60+
5761
private final SpringCloudClientTestBean springCloudClientTestBean = new SpringCloudClientTestBean();
5862

5963
@Before
@@ -63,27 +67,31 @@ public void init() {
6367

6468
@Test
6569
public void testShenyuBeanProcess() {
70+
registerUtilsMockedStatic.when(() -> RegisterUtils.doLogin(any(), any(), any())).thenReturn(Optional.of("token"));
6671
// config with full
6772
SpringCloudClientBeanPostProcessor springCloudClientBeanPostProcessor = buildSpringCloudClientBeanPostProcessor(true);
6873
assertThat(springCloudClientTestBean, equalTo(springCloudClientBeanPostProcessor.postProcessAfterInitialization(springCloudClientTestBean, "springCloudClientTestBean")));
74+
registerUtilsMockedStatic.close();
6975
}
7076

7177
@Test
7278
public void testNormalBeanProcess() {
79+
registerUtilsMockedStatic.when(() -> RegisterUtils.doLogin(any(), any(), any())).thenReturn(Optional.of("token"));
7380
SpringCloudClientBeanPostProcessor springCloudClientBeanPostProcessor = buildSpringCloudClientBeanPostProcessor(false);
7481
Object normalBean = new Object();
7582

7683
assertThat(normalBean, equalTo(springCloudClientBeanPostProcessor.postProcessAfterInitialization(normalBean, "normalBean")));
84+
registerUtilsMockedStatic.close();
7785
}
7886

7987
@Test
8088
public void testWithShenyuClientAnnotation() {
81-
try (MockedStatic mocked = mockStatic(RegisterUtils.class)) {
82-
mocked.when(() -> RegisterUtils.doRegister(any(), any(), any()))
83-
.thenAnswer((Answer<Void>) invocation -> null);
84-
SpringCloudClientBeanPostProcessor springCloudClientBeanPostProcessor = buildSpringCloudClientBeanPostProcessor(false);
85-
assertThat(springCloudClientTestBean, equalTo(springCloudClientBeanPostProcessor.postProcessAfterInitialization(springCloudClientTestBean, "normalBean")));
86-
}
89+
registerUtilsMockedStatic.when(() -> RegisterUtils.doLogin(any(), any(), any())).thenReturn(Optional.of("token"));
90+
registerUtilsMockedStatic.when(() -> RegisterUtils.doRegister(any(), any(), any()))
91+
.thenAnswer((Answer<Void>) invocation -> null);
92+
SpringCloudClientBeanPostProcessor springCloudClientBeanPostProcessor = buildSpringCloudClientBeanPostProcessor(false);
93+
assertThat(springCloudClientTestBean, equalTo(springCloudClientBeanPostProcessor.postProcessAfterInitialization(springCloudClientTestBean, "normalBean")));
94+
registerUtilsMockedStatic.close();
8795
}
8896

8997
private SpringCloudClientBeanPostProcessor buildSpringCloudClientBeanPostProcessor(final boolean full) {
@@ -92,11 +100,14 @@ private SpringCloudClientBeanPostProcessor buildSpringCloudClientBeanPostProcess
92100
properties.setProperty("isFull", full + "");
93101
properties.setProperty("ip", "127.0.0.1");
94102
properties.setProperty("port", "8081");
103+
properties.setProperty("username", "admin");
104+
properties.setProperty("password", "123456");
95105
PropertiesConfig config = new PropertiesConfig();
96106
config.setProps(properties);
97107
ShenyuRegisterCenterConfig mockRegisterCenter = new ShenyuRegisterCenterConfig();
98108
mockRegisterCenter.setServerLists("http://127.0.0.1:8080");
99109
mockRegisterCenter.setRegisterType("http");
110+
mockRegisterCenter.setProps(properties);
100111
return new SpringCloudClientBeanPostProcessor(config, ShenyuClientRegisterRepositoryFactory.newInstance(mockRegisterCenter), env);
101112
}
102113

shenyu-client/shenyu-client-tars/src/test/java/org/apache/shenyu/client/tars/TarsServiceBeanPostProcessorTest.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,23 @@
2121
import org.apache.shenyu.client.core.register.ShenyuClientRegisterRepositoryFactory;
2222
import org.apache.shenyu.client.tars.common.annotation.ShenyuTarsClient;
2323
import org.apache.shenyu.client.tars.common.annotation.ShenyuTarsService;
24+
import org.apache.shenyu.register.client.http.utils.RegisterUtils;
2425
import org.apache.shenyu.register.common.config.PropertiesConfig;
2526
import org.apache.shenyu.register.common.config.ShenyuRegisterCenterConfig;
2627
import org.junit.BeforeClass;
2728
import org.junit.FixMethodOrder;
2829
import org.junit.Test;
2930
import org.junit.runner.RunWith;
3031
import org.junit.runners.MethodSorters;
32+
import org.mockito.MockedStatic;
3133
import org.mockito.junit.MockitoJUnitRunner;
3234

35+
import java.util.Optional;
3336
import java.util.Properties;
3437

38+
import static org.mockito.ArgumentMatchers.any;
39+
import static org.mockito.Mockito.mockStatic;
40+
3541
/**
3642
* Test case for {@link TarsServiceBeanPostProcessor}.
3743
*/
@@ -46,14 +52,20 @@ public static void init() {
4652
properties.setProperty("contextPath", "/tars");
4753
properties.setProperty("port", "8080");
4854
properties.setProperty("host", "localhost");
55+
properties.setProperty("username", "admin");
56+
properties.setProperty("password", "123456");
4957

5058
PropertiesConfig config = new PropertiesConfig();
5159
config.setProps(properties);
5260

5361
ShenyuRegisterCenterConfig mockRegisterCenter = new ShenyuRegisterCenterConfig();
5462
mockRegisterCenter.setServerLists("http://localhost:58080");
5563
mockRegisterCenter.setRegisterType("http");
64+
mockRegisterCenter.setProps(properties);
65+
MockedStatic<RegisterUtils> registerUtilsMockedStatic = mockStatic(RegisterUtils.class);
66+
registerUtilsMockedStatic.when(() -> RegisterUtils.doLogin(any(), any(), any())).thenReturn(Optional.of("token"));
5667
tarsServiceBeanPostProcessor = new TarsServiceBeanPostProcessor(config, ShenyuClientRegisterRepositoryFactory.newInstance(mockRegisterCenter));
68+
registerUtilsMockedStatic.close();
5769
}
5870

5971
@Test

shenyu-common/src/main/java/org/apache/shenyu/common/constant/Constants.java

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,81 @@ public interface Constants {
487487
*/
488488
String TRANSMIT_HEADER_TO_GENERAL_CONTEXT_TYPE = "transmitHeaderToGeneralContext";
489489

490+
/**
491+
* When register by http, the meta register path.
492+
*/
493+
String META_PATH = "/shenyu-client/register-metadata";
494+
495+
/**
496+
* When register by http, the meta type.
497+
*/
498+
String META_TYPE = "metadata";
499+
500+
/**
501+
* When register by http, the uri path.
502+
*/
503+
String URI_PATH = "/shenyu-client/register-uri";
504+
505+
/**
506+
* When register by http, the login path.
507+
*/
508+
String LOGIN_PATH = "/platform/login";
509+
510+
/**
511+
* When register by http, admin username.
512+
*/
513+
String USER_NAME = "username";
514+
515+
/**
516+
* Login name.
517+
*/
518+
String LOGIN_NAME = "userName";
519+
520+
/**
521+
* When register by http, admin password.
522+
*/
523+
String PASS_WORD = "password";
524+
525+
/**
526+
* X-Access-Token.
527+
*/
528+
String X_ACCESS_TOKEN = "X-Access-Token";
529+
530+
/**
531+
* The admin return result code.
532+
*/
533+
String ADMIN_RESULT_CODE = "code";
534+
535+
/**
536+
* The admin return result data.
537+
*/
538+
String ADMIN_RESULT_DATA = "data";
539+
540+
/**
541+
* The admin return result token.
542+
*/
543+
String ADMIN_RESULT_TOKEN = "token";
544+
545+
/**
546+
* The admin userName.
547+
*/
548+
String ADMIN_RESULT_USERNAME = "userName";
549+
550+
/**
551+
* The admin password.
552+
*/
553+
String ADMIN_RESULT_PASSWORD = "password";
554+
555+
/**
556+
* shenyu admin path configs fetch.
557+
*/
558+
String SHENYU_ADMIN_PATH_CONFIGS_FETCH = "/configs/fetch";
559+
560+
/**
561+
* shenyu admin path configs listener.
562+
*/
563+
String SHENYU_ADMIN_PATH_CONFIGS_LISTENER = "/configs/listener";
564+
490565
/**
491566
* String q.
492567
*/
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.shenyu.common.utils;
19+
20+
import java.util.function.Function;
21+
22+
public class FreshBeanHolder<E, O> implements Function<E, O> {
23+
24+
private final Function<E, O> function;
25+
26+
private volatile O o;
27+
28+
public FreshBeanHolder(final Function<E, O> function) {
29+
this.function = function;
30+
}
31+
32+
/**
33+
* Apply.
34+
*
35+
* @param e e
36+
* @return O o
37+
*/
38+
@Override
39+
public O apply(final E e) {
40+
if (o != null) {
41+
return o;
42+
}
43+
return init(e);
44+
}
45+
46+
/**
47+
* Init.
48+
*
49+
* @return bean
50+
*/
51+
synchronized O init(final E e) {
52+
if (o != null) {
53+
return o;
54+
}
55+
O res = function.apply(e);
56+
o = res;
57+
return res;
58+
}
59+
60+
/**
61+
* Fresh.
62+
*
63+
* @param e e
64+
*/
65+
public void doFresh(final E e) {
66+
O fresh = function.apply(e);
67+
if (fresh != null) {
68+
synchronized (this) {
69+
this.o = fresh;
70+
}
71+
}
72+
}
73+
}

shenyu-examples/shenyu-examples-dubbo/shenyu-examples-alibaba-dubbo-service-annotation/src/main/resources/application.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ shenyu:
2727
registerType: http #zookeeper #etcd #nacos #consul
2828
serverLists: http://localhost:9095 #localhost:2181 #http://localhost:2379 #localhost:8848
2929
props:
30+
username: admin
31+
password: 123456
3032
client:
3133
dubbo:
3234
props:

shenyu-examples/shenyu-examples-dubbo/shenyu-examples-alibaba-dubbo-service/src/main/resources/application.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ shenyu:
2929
registerType: http #zookeeper #etcd #nacos #consul
3030
serverLists: http://localhost:9095 #localhost:2181 #http://localhost:2379 #localhost:8848
3131
props:
32+
username: admin
33+
password: 123456
3234
client:
3335
dubbo:
3436
props:

shenyu-examples/shenyu-examples-dubbo/shenyu-examples-apache-dubbo-service-annotation/src/main/resources/application.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ shenyu:
2626
register:
2727
registerType: http #zookeeper #etcd #nacos #consul
2828
serverLists: http://localhost:9095 #localhost:2181 #http://localhost:2379 #localhost:8848
29+
props:
30+
username: admin
31+
password: 123456
2932
client:
3033
dubbo:
3134
props:

0 commit comments

Comments
 (0)