SpringCloud系列之自定义GatewayFilterFactory
学习目的:
- 知道创建一个网关sample
- 知道网关的基本配置
- 知道自定义GatewayFilterFactory类
环境准备:
- JDK 1.8
- SpringBoot2.2.3
- SpringCloud(Hoxton.SR7)
- Maven 3.2+
- 开发工具
- IntelliJ IDEA
- smartGit
新增SpringBoot Initializer项目:New Module->Spring Initializer,选择jdk版本,至少jdk8
packaging选择jar,java version选择jdk8的,然后点next
选择Gateway的依赖,选择之后会自动加上对应pom配置
新建项目之后,检查pom是否有spring-cloud-starter-gateway
org.springframework.cloud spring-cloud-starter-gateway
如果不通过idea的Spring Initializer新建项目的,需要自己加上:
org.springframework.cloud spring-cloud-dependencies${spring-cloud.version} pom import
网关配置,业务场景,一个第三方的接口,经过网关路由之后需要在request header里加上一些校验参数
spring: application: name: api-gateway # 指定application name cloud: gateway: routes: - id: get_user_info uri: http://127.0.0.1:8083 predicates: - Path=/api/findUser filters: - AddRequestHeader=passToken,a68f3eac-5b9c-4fc1-a900-98ee18574576 # FilterFactory名为自定义类名前几个 - name: Custom args: passid: 7a11600c-403c-4260-9165-659e138ada9c serviceId: d8c6ce4c-1b2c-4826-9044-4197d17aad87
自定义一个GatewayFilterFactory,命名后面统一加上GatewayFilterFactory,自定义的字段配在yml的filters.name
package com.example.springcloud.gateway.filter.factories; import com.example.springcloud.gateway.util.EncryptUtils; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.springframework.cloud.gateway.filter.GatewayFilter; import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory; import org.springframework.core.Ordered; import org.springframework.http.server.reactive.ServerHttpRequest; import java.util.Date; @Slf4j public class CustomGatewayFilterFactory extends AbstractGatewayFilterFactoryimplements Ordered { public CustomGatewayFilterFactory() { super(Config.class); } @Override public GatewayFilter apply(Config config) { return ((exchange, chain) -> { String passToken = exchange.getRequest().getHeaders().getFirst("passToken"); log.info("passToken:{}" , passToken); long now = new Date().getTime(); String timestamp = Long.toString((long)Math.floor(now/1000)); String signature = ""; try { signature = EncryptUtils.toSHA256(timestamp + passToken + timestamp); } catch (Exception e) { e.printStackTrace(); } log.info("signature:{}" , signature); ServerHttpRequest request = exchange.getRequest().mutate() .header("passid", config.getPassid()) .header("serviceId", config.getServiceId()) .header("signature", signature) .build(); log.info("passid:{}" , config.getPassid()); log.info("serviceId:{}" , config.getServiceId()); return chain.filter(exchange.mutate().request(request).build()); }); } @Override public int getOrder() { return Ordered.HIGHEST_PRECEDENCE; } @Data public static class Config { private String passid; private String serviceId; } }
过滤器将在较早的阶段执行其“pre”逻辑,但稍后会调用它的“post”实现:
官网的图例:首先客户端请求都会先经过Gateway Handler Mapping,匹配上就通过Gateway Web Handler转给过滤器处理,过滤器分为PreFilter(前置过滤器)、PostFilter(后置过滤器)。过滤器由虚线分隔的原因是,筛选器可以在发送代理请求之前和之后运行逻辑。所有“前置”过滤器逻辑均被执行。然后发出代理请求。发出代理请求后,将运行“后置”过滤器逻辑
import java.security.MessageDigest; public class EncryptUtils { public static String toSHA256(String str) throws Exception { MessageDigest messageDigest; String encodeStr = ""; try { messageDigest = MessageDigest.getInstance("SHA-256"); messageDigest.update(str.getBytes("UTF-8")); encodeStr = byte2Hex(messageDigest.digest()); } catch (Exception e) { throw e; } return encodeStr; } protected static String byte2Hex(byte[] bytes) { StringBuffer stringBuffer = new StringBuffer(); String temp = null; for (int i = 0; i < bytes.length; i++) { temp = Integer.toHexString(bytes[i] & 0xFF); if (temp.length() == 1) { stringBuffer.append("0"); } stringBuffer.append(temp); } return stringBuffer.toString(); } }
控制台打印:
signature:72bdd60d2fc6f115eabda1ced766c0c0aa7397521d653977b2fd15d6c6978587 passid:7a11600c-403c-4260-9165-659e138ada9c serviceId:d8c6ce4c-1b2c-4826-9044-4197d17aad87
然后去第三方接口看请求header参数,可以带过来
注意:如果网关配置不起效,可以尝试设置ordered确定优先级,有多个配置,可以将配置位置适当挪前点
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)