前言
本篇文章继续上一篇gateway的鉴权使用说明。主要包含全局过滤器的设置和多路由跳转,附带做一下配置中心的讲解。
一、全局过滤器
在gateway的官方文档中,分两种过滤器:全局过滤和路由过滤。本次采用全局过滤来辅助完成鉴权
@Component
public class Filter implements GlobalFilter {
/*白名单暂时不做,只提一个登录接口*/
private final static String LOGIN_PATH = "/user/login";
@Autowired
private StringRedisTemplate redisTemplate;
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
if(LOGIN_PATH.equals(exchange.getRequest().getPath().toString())) {
exchange.getResponse().setStatusCode(HttpStatus.OK);
return chain.filter(exchange);
}
/*暂时定义鉴权逻辑:有token就通过并刷新,没有就直接不允许*/
exchange.getResponse().setStatusCode(HttpStatus.FAILED_DEPENDENCY);
String token = exchange.getRequest().getHeaders().getFirst("Authorization");
if(StringUtils.isNotEmpty(token)) {
String str = redisTemplate.opsForValue().get(token);
if(StringUtils.isNotEmpty(str)) {
@SuppressWarnings("unchecked")
Map<String,Object> map = (Map)JSONObject.parse(str);
long timestamp = Long.parseLong(map.get("outTime").toString());
LocalDateTime time =LocalDateTime.ofEpochSecond(timestamp/1000,0, ZoneOffset.ofHours(8));
map.put("outTime",time.plusMinutes(10).toInstant(ZoneOffset.of("+8")).toEpochMilli());
String jsonString = JSONObject.toJSONString(map);
redisTemplate.opsForValue().set(token,jsonString);
exchange.getResponse().setStatusCode(HttpStatus.OK);
}
}
return chain.filter(exchange);
}
}
这里借助了GlobalFilter来实现全局的一个请求过滤,主要复写了filter,当中定义了我设想的token校验逻辑;对于白名单暂时只是将登录接口做免校验。。。
二、路由转发
在gateway的官方说明中,是提供两种方式的路由转发的。一是在配置文件中配置,如:
routes:
# =====================================
# to run server
# $ wscat --listen 9000
# to run client
# $ wscat --connect ws://localhost:8080/echo
- id: websocket_test
uri: ws://localhost:9000
order: 9000
predicates:
- Path=/echo
# =====================================
- id: default_path_to_httpbin
uri: ${test.uri}
order: 10000
predicates:
- Path=/**
另一种方式是api做路由转发,如:
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route (r -> r.path ("/u/**")
.filters (f -> f.stripPrefix (1))
.uri ("lb://user")
.order (0)
.id ("user-route")
)
.route (r -> r.path ("/db/**")
.filters (f -> f.stripPrefix (1))
.uri ("lb://dbmanagement")
.order (0)
.id ("db-route")
)
.build();
}
这里简单的阐述一下两种方式的共同的参数意义
id:路由的唯一标识
uri:转发的地址
order:序号(越大优先级越高)
filter:url断言规则
(其实在配置文件中的路由转发,本人并没有实现,不知道是哪里配出了问题,所以采用的是api的方式,望有大佬路过告知)
三、配置中心
关于springcloud config的配置和说明网上已经太多了,我这里只是附带提一下。
1、jar
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
2、启动项注解
@EnableConfigServer
3、配置文件集中管理
类似如此的文件配置,丢在config服务下静态资源处。
server:
port: 19000
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
spring:
application:
name: config
profiles:
active: native
cloud:
config:
fail-fast: true
server:
native:
search-locations: classpath:/config/
指定config读取本地(profiles:active: native)
4、其他服务获取配置文件
spring:
cloud:
config:
profile: user
discovery:
enabled: true
service-id: CONFIG
fail-fast: true
指定配置中心服务的为 CONFIG
文件名为 user的配置文件
如此就可以在服务启动时从配置中心拉取配置文件,eg: