Introduction
À mon avis, dans les microservices, la passerelle est en fait la chose la plus importante. Il ne se contente pas de répartir les routes et d'équilibrer la charge pour chaque service. Il peut également garantir la sécurité de l'ensemble de notre microservice. Tels que : attaque xxs , injection sql . Certaines données doivent également être vérifiées dans la demande de requête, la gestion interdomaine, la gestion des exceptions globales, etc., qui doivent toutes être écrites dans la passerelle.
La passerelle fournit non seulement une simultanéité élevée et une haute disponibilité pour les microservices. Et haute sécurité. Cette fois, je vais régler pour vous l'utilisation simple de Gateway. (Je ne peux pas venir si c'est trop compliqué).
Attaque xxs : Il s'agit de modifier les pages de notre site internet en injectant du langage html ou JavaScript dans la requête pour compléter le but des hackers.
Nous savons tous que les pages Web sont complétées par un langage de balises html, et il est facile à apprendre. Imaginons que nous n'ayons pas d'interception xxs dans les applications Web. Ensuite, une personne au hasard place une étiquette A à côté de son nom lorsqu'elle enregistre son nom. comme:
<a href="xxxx.com">Daniel Wu</a>
Ensuite, à ce moment, notre site Web deviendra un lieu de rassemblement pour les p totaux. Ils font la publicité, mais nous marchons sur la machine à coudre. Comment effrayant.
C'est ma compréhension de xxs. Je ne sais pas exactement ce que c'est.
------------------------------------------
Injection SQL : similaire à xxs ci-dessus, mais l'injection SQL est plus difficile à distinguer. Étant donné que select est utilisé comme nom d'utilisateur pour les utilisateurs anglais, il est normal qu'il apparaisse dans les paramètres d'entrée de la demande. Vous ne pouvez pas tuer toutes les demandes avec un seul bâton. Donc, à ce stade, il est nécessaire d'utiliser des expressions régulières pour juger si les paramètres de la requête de l'utilisateur constituent un crime, non, si la configuration constitue une instruction SQL pouvant être exécutée.
2. Construction de l'environnement
1. Dépendance 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. Fichier de configuration
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
Troisièmement, l'utilisation de filtres globaux
GateWay a intimement créé l'interface GlobalFilter pour nous. Il nous suffit d'implémenter cette interface pour terminer le filtrage de toutes les requêtes.
Code:
Créez le package de filtre correspondant dans notre projet de passerelle. Utilisé pour écrire tous les filtres.
@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;
}
}
Un tel filtre global est écrit. Réaliser les releases correspondantes et filtrer en fonction de l'activité réelle
//Obtenir la requête à partir des informations d'interaction ServerHttpRequest request = exchange.getRequest();//Obtenir la réponse à partir des informations d'interaction
Réponse ServerHttpResponse = exchange.getResponse();//Exemple : prendre les informations de jeton de l'échange
Jeton de chaîne = exchange.getRequest().getHeaders().getFirst("token");
Contrôle d'accès (liste noire et liste blanche)
Certaines requêtes du projet ne nécessitent pas de filtrage des autorisations, car le filtrage des autorisations de ces interfaces entraînera l'échec du processus principal. Tels que : enregistrement, connexion et autres interfaces. J'ai toutes les autorisations et le jeton et je m'inscris toujours, pourquoi dois-je me connecter ? Donc, à ce stade, nous devons configurer l'URL de la liste blanche dans notre fichier yml. directement dans la classe. yml. Ou les données feront l'affaire. Regardez le projet, tant que la collection de la liste blanche peut être lue. Généralement, il est configuré dans le centre de configuration, n'a pas besoin de redémarrer le service et est pratique pour la gestion. Utilisez l'annotation @ConfigurationProperties pour la lire à partir du fichier yml et la comparer avec la demande d'URL actuelle. Si elle correspond, elle sera publiée directement sans filtrage des autorisations.
Les filtres globaux peuvent être utilisés pour empêcher les attaques xss, les listes noires et les listes blanches. Pour configurer les informations inter-domaines, elles doivent être implémentées via le filtre WebFilter.
Configuration inter-domaines : reportez-vous à 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;
}
}
Résumer:
En fait, les fonctions qui doivent être configurées dans la passerelle sont plus que celles que j'ai mentionnées ci-dessus. La configuration dans la passerelle est également lourde. Avec ma force actuelle, c'est difficile de bien dire. Apprenons au fur et à mesure.