最后加入 权限认证

This commit is contained in:
huangsimin 2019-07-09 18:01:30 +08:00
parent 64e48bedfe
commit 3471a980b1
16 changed files with 280 additions and 90 deletions

View File

@ -0,0 +1,5 @@
{"properties": [{
"name": "yame.config",
"type": "java.lang.String",
"description": "用于配置网关的路径, 如果不填默认 gateway.yml, gateway.yaml, Gateway.yml, Gateway.yaml"
}]}

View File

@ -1,7 +1,5 @@
package cn.ecpark.service.usergw;
import java.net.URI;
import org.apache.dubbo.config.spring.context.annotation.EnableDubboConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringBootConfiguration;

View File

@ -22,8 +22,9 @@ public class VerifyFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
if(true) return chain.filter(exchange);
if (true)
return chain.filter(exchange);
ServerHttpRequest request = exchange.getRequest();
HttpHeaders header = request.getHeaders();
@ -61,8 +62,4 @@ public class VerifyFilter implements GlobalFilter {
return false;
}
}

View File

@ -4,8 +4,6 @@ import java.util.HashMap;
import org.apache.dubbo.rpc.service.GenericService;
import lombok.extern.slf4j.Slf4j;
/**
* GenericServicePool
*/

View File

@ -3,6 +3,7 @@ package cn.ecpark.service.usergw.biz.filters.factory;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import com.alibaba.fastjson.JSON;
@ -34,6 +35,8 @@ public class DubboGatewayFilterFactory extends AbstractGatewayFilterFactory<Dubb
public static final String DUBBO_URI = "dubbo_uri";
public static HashMap<String, List<String>> mehtods = new HashMap<>();
private List<String> emptyList = new LinkedList<String>();
public DubboGatewayFilterFactory() {
super(Config.class);
}
@ -57,52 +60,63 @@ public class DubboGatewayFilterFactory extends AbstractGatewayFilterFactory<Dubb
Object result = null;
ServerHttpResponse response = exchange.getResponse();
if(methodString.size() != 0) {
if (methodString.size() != 0) {
List<String> paramTypes;
//判断全部函数允许, 必须带参数类型, 而且要匹配, 否则报错
if(uri.charAt(5) == '-') {
// 判断全部函数允许, 必须带参数类型, 而且要匹配, 否则报错
if (uri.charAt(5) == '-') {
paramTypes = headers.get("param-types");
if(paramTypes == null) {
paramTypes = this.emptyList;
}
} else {
paramTypes = mehtods.get(methodString.get(0));
}
if(paramTypes != null) {
if (paramTypes != null) {
int paramsSize = 0;
if(params != null) {
if (params != null) {
paramsSize = params.size();
}
if(paramTypes.size() == paramsSize) {
if (paramTypes.size() == paramsSize) {
GenericServicePool gsPool = appContext.getBean(GenericServicePool.class);
GenericService gs = gsPool.get(uri);
if(paramsSize == 0) {
result = gs.$invoke(methodString.get(0), new String[]{}, new Object[]{});
if (paramsSize == 0) {
result = gs.$invoke(methodString.get(0), new String[] {}, new Object[] {});
} else {
result = gs.$invoke(methodString.get(0), Arrays.copyOf(paramTypes.toArray(), paramTypes.size(), String[].class), params.toArray());
result = gs.$invoke(methodString.get(0),
Arrays.copyOf(paramTypes.toArray(), paramTypes.size(), String[].class),
params.toArray());
}
if(result == null) {
if (result == null) {
return response.setComplete();
}
}else {
result = String.format("paramTypes.size %d is not equals to params size %d",
paramTypes.size(),paramsSize);
log.warn((String)result);
}
} else {
result = String.format("paramTypes.size %d is not equals to params size %d", paramTypes.size(),
paramsSize);
log.warn((String) result);
}
} else {
result = String.format("mehtod: %s, param-types: null is not exist or not allowed", methodString.get(0));
log.warn((String)result);
result = String.format("(mehtod: %s, param-types: null) is not exist or method is not allowed",
methodString.get(0));
log.warn((String) result);
}
} else {
result = String.format("queryParams.get(\"method\") is null");
log.warn((String)result);
log.warn((String) result);
}
if (result != null) {
return response.writeWith(Mono
.just(response.bufferFactory().wrap(ByteBuffer.wrap(JSON.toJSONString(result).getBytes()))));
}
if (result.getClass() == String.class) {
return response.writeWith(
Mono.just(response.bufferFactory().wrap(ByteBuffer.wrap(((String) result).getBytes()))));
} else {
return response.writeWith(Mono.just(
response.bufferFactory().wrap(ByteBuffer.wrap(JSON.toJSONString(result).getBytes()))));
}
}
return chain.filter(exchange);
};

View File

@ -1,17 +1,6 @@
package cn.ecpark.service.usergw.biz.routes;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.RequestPredicates;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerResponse;
/**
* Route
*/

View File

@ -1,7 +1,6 @@
package cn.ecpark.service.usergw.config;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
@ -16,6 +15,7 @@ import java.util.function.BiConsumer;
import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.rpc.service.GenericService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.FilterDefinition;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.cloud.gateway.route.RouteDefinition;
@ -26,8 +26,6 @@ import org.springframework.stereotype.Component;
import org.yaml.snakeyaml.Yaml;
import cn.ecpark.service.usergw.biz.filters.bean.GenericServicePool;
import cn.ecpark.service.usergw.biz.filters.factory.DubboGatewayFilterFactory;
import cn.ecpark.service.usergw.utils.Convert;
import cn.ecpark.service.usergw.utils.Extract;
import lombok.extern.slf4j.Slf4j;
import reactor.core.publisher.Flux;
@ -41,6 +39,9 @@ public class ConfigGateway implements RouteDefinitionLocator {
// List<MediaType> mediaTypes = new ArrayList<>();
@Value("${yame.config}")
private String yameConfigPath;
List<FilterDefinition> defaultFilters = new ArrayList<>();
HashMap<String, BiConsumer<ReferenceConfig<GenericService>, Object>> specialField = new HashMap<String, BiConsumer<ReferenceConfig<GenericService>, Object>>();
Set<String> ignoreKey = new HashSet<>();
@ -63,8 +64,14 @@ public class ConfigGateway implements RouteDefinitionLocator {
// WebFluxConfigurationSupport a;
defaultFilters.clear();
Object inputStream = null;
String[] gatewayConfigPathList = { "gateway.yml", "gateway.yaml", "Gateway.yml", "Gateway.yaml" };
String[] gatewayConfigPathList;
if (yameConfigPath == null) {
gatewayConfigPathList = new String[] { "gateway.yml", "gateway.yaml", "Gateway.yml", "Gateway.yaml" };
} else {
gatewayConfigPathList = new String[] { yameConfigPath };
}
for (String gatewayConfigPath : gatewayConfigPathList) {
gatewayConfigPath = gatewayConfigPath.trim();
inputStream = this.getClass().getClassLoader().getResourceAsStream(gatewayConfigPath);
if (inputStream != null) {
break;
@ -99,8 +106,6 @@ public class ConfigGateway implements RouteDefinitionLocator {
return Flux.empty();
}
@SuppressWarnings("unchecked")
private void configDefault(List<RouteDefinition> routeList, Map<String, Object> defaultYaml) {
if (defaultYaml != null) {
@ -238,14 +243,14 @@ public class ConfigGateway implements RouteDefinitionLocator {
}
iter.remove("order");
ReferenceConfig<GenericService> reference = new ReferenceConfig<GenericService>();
reference.setConnections(3);
String UriString = "dubbo://";
// TODO: 以后可以完善dubbo-{flag}形式的判断
Object methods = iter.get("methods");
if(methods == null || ((List<Object>)methods).size() == 0) {
if (methods == null || ((List<Object>) methods).size() == 0) {
UriString = "dubbo-allowed://";
} else {
UriString = "dubbo://";
@ -285,8 +290,6 @@ public class ConfigGateway implements RouteDefinitionLocator {
}
}
UriString += Extract.getReferenceConfigKey(reference);
GenericServicePool gsPool = appContext.getBean(GenericServicePool.class);
reference.setGeneric(true);
@ -323,7 +326,7 @@ public class ConfigGateway implements RouteDefinitionLocator {
List<String> filtersYaml = iter.get(yamlField);
filters.addAll(defaultFilters);
if (filtersYaml != null) {
for (String filterString : filtersYaml) {
FilterDefinition fd = new FilterDefinition(filterString);
@ -333,7 +336,7 @@ public class ConfigGateway implements RouteDefinitionLocator {
}
}
}
filters.add(new FilterDefinition("Dubbo=" + dubboUri));
}
}

View File

@ -1,23 +1,15 @@
package cn.ecpark.service.usergw.config;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Function;
import javax.el.MethodNotFoundException;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.rpc.service.GenericService;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import cn.ecpark.service.usergw.biz.filters.bean.GenericServicePool;
import cn.ecpark.service.usergw.biz.filters.factory.DubboGatewayFilterFactory;
import cn.ecpark.service.usergw.utils.Convert;
import lombok.extern.slf4j.Slf4j;
@ -28,37 +20,37 @@ import lombok.extern.slf4j.Slf4j;
@Slf4j
public class ConfigSpecialFunction {
public static void setDefault(ReferenceConfig<GenericService> ref, String methodName, Object cfgValue) throws Exception {
public static void setDefault(ReferenceConfig<GenericService> ref, String methodName, Object cfgValue)
throws Exception {
methodName = "set" + Convert.firstUpperCase(methodName);
log.info("method:{}, value:{}",methodName,cfgValue);
log.info("method:{}, value:{}", methodName, cfgValue);
Method method = ref.getClass().getMethod(methodName, cfgValue.getClass());
method.invoke(ref, cfgValue);
}
public static void setApplication(ReferenceConfig<GenericService> ref, Object cfgValue) {
ref.setApplication(new ApplicationConfig((String)cfgValue));
ref.setApplication(new ApplicationConfig((String) cfgValue));
}
public static void setRegistry(ReferenceConfig<GenericService> ref, Object cfgValue) {
ref.setRegistry(new RegistryConfig((String)cfgValue));
ref.setRegistry(new RegistryConfig((String) cfgValue));
}
@SuppressWarnings("unchecked")
public static void setMethods(ReferenceConfig<GenericService> ref, Object cfgValue) {
List<HashMap<String, Object>> cfgs = (List<HashMap<String, Object>>) cfgValue;
for(HashMap<String, Object> cfg: cfgs) {
String name = (String)cfg.get("name");
if(DubboGatewayFilterFactory.mehtods.containsKey(name)) {
for (HashMap<String, Object> cfg : cfgs) {
String name = (String) cfg.get("name");
if (DubboGatewayFilterFactory.mehtods.containsKey(name)) {
log.warn("method {} is duplicate", name);
}
List<String> params = (List<String>)cfg.get("param-types");
if(params == null) {
params = new LinkedList<>(); // 不用ArrayList 减少内存的使用.
List<String> params = (List<String>) cfg.get("param-types");
if (params == null) {
params = new LinkedList<>(); // 不用ArrayList 减少内存的使用.
}
DubboGatewayFilterFactory.mehtods.put(name, params);
}
}
}

View File

@ -11,3 +11,5 @@ server.port=8888
# logging.level.org.springframework.cloud.gateway=debug
logging.file=logs/log
yame.config=gateway.yaml

View File

@ -33,12 +33,12 @@ dubbo:
- id: test
order: 0
application: dubbo-exchange
# methods: # 如果没填就从 request拿 意味着所有接口都可以使用
methods: # 如果没填就从 request拿 意味着所有接口都可以使用
# - name: Say
# param-types:
# - java.lang.String
# - name: Hello
- name: Say
param-types:
- java.lang.String
- name: Hello
connections: 4
group: test

View File

@ -0,0 +1,50 @@
restful:
default-filters:
- AddResponseHeader=X-Response-Default-Foo, Test-Default-Bar
routes:
- id: path_route
uri: http://httpbin.org:80/*
order: 9
predicates:
- Path=/get
- Header=XX, \d+
- id: path_route12;
uri: http://httpbin.org:80/*
order: 9
predicates:
- Path=/get
- Header=XX, \d+
- id: path_route13
uri: http://httpbin.org:80/*
order: 9
predicates:
- Path=/get
- Header=XX, \d+
# - id: redirect_to
# uri: http://localhost/test/**
# order: 11
# filters:
# - RedirectTo=302, http://httpbin.org:80/get
dubbo:
routes:
- id: test
order: 0
application: dubbo-exchange
# methods: # 如果没填就从 request拿 意味着所有接口都可以使用
# - name: Say
# param-types:
# - java.lang.String
# - name: Hello
connections: 4
group: test
# registry: zookeeper://127.0.0.1:2181
interface: ocean.demo.api.IExchange
version: 1.0.0
predicates:
- Path=/dubbo/hello

View File

@ -1,20 +1,10 @@
package cn.ecpark.service.usergw.utils;
import java.net.URI;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.assertj.core.util.Arrays;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.boot.test.context.TestComponent;
import cn.ecpark.service.usergw.utils.Extract.GenericServiceBase;
import io.netty.handler.codec.http.HttpUtil;
import io.netty.handler.codec.http.QueryStringDecoder;
@TestComponent
public class TestExtract {

View File

@ -0,0 +1,88 @@
package cn.ecpark.service.usergw.utils;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
import cn.ecpark.service.usergw.App;
import reactor.netty.http.client.HttpClient;
import reactor.netty.http.client.HttpClient.ResponseReceiver;
import reactor.netty.http.client.HttpClientResponse;
@SpringBootTest(classes= App.class, webEnvironment = WebEnvironment.RANDOM_PORT)
@RunWith(SpringRunner.class)
@TestPropertySource(locations = {"application.properties"})
public class TestHttp2DubboConfig {
@LocalServerPort
private int serverPort;
@Test
public void TestRequestHttp2DubboWithoutConfigMethod() {
// Test Base Url
HttpClient client = HttpClient.create();
ResponseReceiver<?> receiver = client.baseUrl("http://localhost:" + serverPort + "/dubbo/hello").headers(
h -> h.set("method", "Say").add("param-types", "java.lang.String").add("params", "Test-MyHttp2dubbo"))
.get();
HttpClientResponse resp = receiver.response().block();
Assert.assertNotNull(resp);
String v = resp.responseHeaders().get("X-Response-Default-Foo");
Assert.assertNotNull(v);
Assert.assertEquals(v, "Test-Default-Bar");
String content = receiver.responseContent().asString().blockLast();
Assert.assertNotNull(content);
Assert.assertEquals(content, "Test-MyHttp2dubbo");
receiver = client.baseUrl("http://localhost:" + serverPort + "/dubbo/hello").headers(
h -> h.set("method", "Hello"))
.get();
resp = receiver.response().block();
Assert.assertNotNull(resp);
content = receiver.responseContent().asString().blockLast();
Assert.assertNotNull(content);
Assert.assertEquals(content, "Hello Dubbo");
}
@Test
public void TestJSONReturnWithoutConfigMethod() {
// Test Base Url
HttpClient client = HttpClient.create();
ResponseReceiver<?> receiver = client.baseUrl("http://localhost:" + serverPort + "/dubbo/hello").headers(
h -> h.set("method", "Say").add("param-types", "java.lang.String").add("params","{\"a\": 1, \"b\":\"123\"}"))
.get();
HttpClientResponse resp = receiver.response().block();
Assert.assertNotNull(resp);
String v = resp.responseHeaders().get("X-Response-Default-Foo");
Assert.assertNotNull(v);
Assert.assertEquals(v, "Test-Default-Bar");
String content = receiver.responseContent().asString().blockLast();
Assert.assertNotNull(content);
Assert.assertEquals(content, "{\"a\": 1, \"b\":\"123\"}");
receiver = client.baseUrl("http://localhost:" + serverPort + "/dubbo/hello").headers(
h -> h.set("method", "Say").add("param-types", "java.lang.String").add("params","123"))
.get();
resp = receiver.response().block();
Assert.assertNotNull(resp);
content = receiver.responseContent().asString().blockLast();
Assert.assertNotNull(content);
Assert.assertEquals(content, "123");
}
}

View File

@ -0,0 +1,15 @@
spring.application.name=gateway
dubbo.scan.base-packages=cn.ecpark.service.usergw.impl
dubbo.protocol.name=dubbo
dubbo.protocol.port=20999
dubbo.registry.address=zookeeper://127.0.0.1:2181
dubbo.config-center.address=zookeeper://127.0.0.1:2181
dubbo.metadata-report.address=zookeeper://127.0.0.1:2181
server.port=8888
# logging.level.org.springframework.cloud.gateway=debug
logging.file=logs/log
yame.config=test-gateway.yaml

View File

@ -0,0 +1,50 @@
restful:
default-filters:
- AddResponseHeader=X-Response-Default-Foo, Test-Default-Bar
routes:
- id: path_route
uri: http://httpbin.org:80/*
order: 9
predicates:
- Path=/get
- Header=XX, \d+
- id: path_route12;
uri: http://httpbin.org:80/*
order: 9
predicates:
- Path=/get
- Header=XX, \d+
- id: path_route13
uri: http://httpbin.org:80/*
order: 9
predicates:
- Path=/get
- Header=XX, \d+
# - id: redirect_to
# uri: http://localhost/test/**
# order: 11
# filters:
# - RedirectTo=302, http://httpbin.org:80/get
dubbo:
routes:
- id: test
order: 0
application: dubbo-exchange
# methods: # 如果没填就从 request拿 意味着所有接口都可以使用
# - name: Say
# param-types:
# - java.lang.String
# - name: Hello
connections: 4
group: test
# registry: zookeeper://127.0.0.1:2181
interface: ocean.demo.api.IExchange
version: 1.0.0
predicates:
- Path=/dubbo/hello

View File

@ -1,6 +1,6 @@
restful:
default-filters:
- AddResponseHeader=X-Response-Default-Foo, Default-Bar
- AddResponseHeader=X-Response-Default-Foo, Test-Default-Bar
routes:
- id: path_route
uri: http://httpbin.org:80/*
@ -34,7 +34,6 @@ dubbo:
order: 0
application: dubbo-exchange
methods: # 如果没填就从 request拿 意味着所有接口都可以使用
- name: Say
param-types:
- java.lang.String