一、前言
在我看来微服务中,网关其实才是重中之重。它不仅仅是做了每个服务的路由分发、负载均衡。他还可以保障我们的整个微服务的安全。如:xxs攻击、sql注入。还有一些需要对Request请求里的数据做校验、跨域、全局异常处理等,处理都需要在网关里进行编写。
网关不仅给微服务提供了高并发、高可用。还有高安全。本次就为大家整理Gateway网关的简单使用。(太复杂的俺也来不了)。
xxs攻击:就是通过请求里注入html语言或者JavaScript来改变我们网站的页面,来完成黑客的目的。
我们都知道网页是由html标签语言完成,而且简单好学。我们试想一下我们没有web应用中没有做xxs拦截。那么随便一个人在注册名称时给自己的名称旁边加个A标签。如:
<a href="xxxx.com"> 吴彦祖 </a>
那么这个时候我们的网站就会成为p总的聚集地。广告他们来做,缝纫机我们去踩。这多恐怖啊。
这是我对xxs的理解。具体是咋样的我也不清楚。
------------------------------------------
sql注入:也类似上面的xxs,但是sql注入更加难辨别。因为select这种英文用户拿来做用户名活着在请求入参出现也很正常把。不能一棒子打死所有请求。所以此时需要用正则表达式的方式来判断用户的请求里的参数构不构成犯罪,不,构不构成可以运行的sql语句。
二、环境搭建
1、Maven依赖
<!-- Nacos服务注册发现-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- gateway依赖 没有版本,因为在父工程已指定springBoot版本 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- 因为我的配置文件是 bootstrap.yml 文件,spring boot版本高后不能自动读取需要这个依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
<!-- yml文件中无法通过lb 分发请求问题 解决依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
2、配置文件
server:
port: 8000 # 指定gateway网关服务端口
spring:
application:
name: spring-myself-gateway #拟定服务名称
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848 #nacos服务注册地址
gateway:
routes: #Routes 路由分发功能
- id: spring-myself-user #拟定路由名称,可任意。最好与对应服务,服务名称一致
uri: lb://spring-myself-user # lb:负载均衡。后面对应的那nacos注册服务名称。实则URL
predicates: #前言
- Path=/user/** #当我们请求gateway服务时前缀如果是这个就会转发上面uri
filters:
- StripPrefix=1 # 过滤到一层请求 也就是 /user/
# 我user服务模块端口是8001。 当我们请求 127.0.0.1:8000/user/System/doLogin 时他会通过网关进行转发,转发真实地址: 127.0.0.1:8001/System/doLogin
三、全局过滤器的使用
GateWay贴心的为我们创建好了 GlobalFilter 接口。我们至需要去实现这个接口,就可以完成所有的请求过滤。
代码实现:
在我们gateway工程创建好对应filter包。用来编写所有过滤器。
@Component //注入容器
@Slf4j //日志打印(需要Lombok依赖) 全局过滤,优先等级(值越小越先执行)
public class TestFilter implements GlobalFilter, Ordered {
//GlobalFilter接口的重写方法
@Override //入参理解: 本次请求交互信息,request等 管道
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//根据实际业务条件判断此请求是否继续执行
if(1==1){
//return chain.filter(exchange) 正常执行请求
return chain.filter(exchange);
}
//返回null则是对此请求做了过滤,无效了。
return null;
}
//Ordered接口重写,返回int值,值越小越先执行
@Override
public int getOrder() {
return -1;
}
}
这样一个全局过滤器就写好了。根据实际业务进行对应的放行、过滤
//从交互信息中获取request ServerHttpRequest request = exchange.getRequest();//从交互信息中得到response
ServerHttpResponse response = exchange.getResponse();//示例:从exchange中取出token信息
String token = exchange.getRequest().getHeaders().getFirst("token");
权限控制(黑、白名单)
项目中有些请求时不需要进行权限过滤的,因为对此类接口权限过滤会导致主流程就走不通了。如:注册,登录等接口。我都有权限了有token了还注册,登录干啥呢?所以此时就需要在我们的yml文件中配置白名单URL。直接写在类里。yml里。或者数据都行。看项目,只要能读取到白名单list集合。一般都是配置在配置中心,不需要重启服务,且方便管理。用 @ConfigurationProperties注解从yml文件中读取出来,与当前URL请求进行对比,如果匹配上就直接放行,就不用权限过滤了。
像我们的防止xss攻击、黑名单、白名单都可以使用全局过滤器完成。像配置跨域信息则需要通过WebFilter 过滤器实现。
跨域配置:参考ruoyi-plus
@Component
public class GlobalCorsFilter implements WebFilter, Ordered {
/**
* 这里为支持的请求头,如果有自定义的header字段请自己添加
*/
private static final String ALLOWED_HEADERS = "X-Requested-With, Content-Language, Content-Type, Authorization, credential, X-XSRF-TOKEN, isToken, token, Admin-Token, App-Token";
private static final String ALLOWED_METHODS = "GET,POST,PUT,DELETE,OPTIONS,HEAD";
private static final String ALLOWED_ORIGIN = "*";
private static final String ALLOWED_EXPOSE = "*";
private static final String MAX_AGE = "18000L";
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
if (CorsUtils.isCorsRequest(request)) {
ServerHttpResponse response = exchange.getResponse();
HttpHeaders headers = response.getHeaders();
headers.add("Access-Control-Allow-Headers", ALLOWED_HEADERS);
headers.add("Access-Control-Allow-Methods", ALLOWED_METHODS);
headers.add("Access-Control-Allow-Origin", ALLOWED_ORIGIN);
headers.add("Access-Control-Expose-Headers", ALLOWED_EXPOSE);
headers.add("Access-Control-Max-Age", MAX_AGE);
headers.add("Access-Control-Allow-Credentials", "true");
if (request.getMethod() == HttpMethod.OPTIONS) {
response.setStatusCode(HttpStatus.OK);
return Mono.empty();
}
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE;
}
}
总结:
其实gateway网关里需要配置的功能还不止我上面所述的那些。gateway里配置也比较繁琐。以我现在的实力也很难讲的好。咋们边走边学吧。