添加wvp过滤

This commit is contained in:
孙小云 2026-02-02 13:19:15 +08:00
parent 095d9d257f
commit 3ad0509eb0
2 changed files with 246 additions and 0 deletions

View File

@ -0,0 +1,97 @@
package com.ruoyi.gateway.filter;
import com.ruoyi.gateway.utils.WvpTokenClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
/**
* WVP Access Token 过滤器
* 用于为 WVP 请求添加或替换 access-token 请求头
*/
@Component
public class WvpAccessTokenFilter extends AbstractGatewayFilterFactory<WvpAccessTokenFilter.Config> {
private static final Logger log = LoggerFactory.getLogger(WvpAccessTokenFilter.class);
private static String cachedAccessToken = null;
private static final Object LOCK = new Object();
public WvpAccessTokenFilter() {
super(Config.class);
}
@Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
try {
// 获取 access token
String accessToken = getAccessToken();
log.info("WVP 请求 - 原始路径: {}", exchange.getRequest().getURI().getPath());
log.info("WVP 请求 - 添加 access-token");
// 修改请求添加或替换 access-token 请求头
ServerHttpRequest modifiedRequest = exchange.getRequest().mutate()
.header("access-token", accessToken)
.build();
// 创建新的 exchange
ServerWebExchange modifiedExchange = exchange.mutate()
.request(modifiedRequest)
.build();
return chain.filter(modifiedExchange).then(Mono.fromRunnable(() -> {
log.info("WVP 响应 - Status: {}", modifiedExchange.getResponse().getStatusCode());
}));
} catch (Exception e) {
log.error("获取 WVP access token 失败", e);
// 即使获取 token 失败也继续转发请求
return chain.filter(exchange);
}
};
}
/**
* 获取 access token使用缓存机制
* 如果缓存为空则调用 WvpTokenClient.login 获取新的 token
*/
private String getAccessToken() throws Exception {
if (cachedAccessToken == null) {
synchronized (LOCK) {
if (cachedAccessToken == null) {
log.info("缓存中没有 access token正在登录 WVP...");
WvpTokenClient.LoginResponse loginResponse = WvpTokenClient.login("admin", "admin");
if (loginResponse.getCode() == 0 && loginResponse.getData() != null) {
cachedAccessToken = loginResponse.getData().getAccessToken();
log.info("WVP 登录成功,获取到 access token");
} else {
throw new Exception("WVP 登录失败: " + loginResponse.getMsg());
}
}
}
}
return cachedAccessToken;
}
/**
* 清除缓存的 access token可用于 token 过期时重新获取
*/
public static void clearCachedToken() {
synchronized (LOCK) {
cachedAccessToken = null;
log.info("已清除缓存的 WVP access token");
}
}
/**
* 配置类
*/
public static class Config {
}
}

View File

@ -0,0 +1,149 @@
package com.ruoyi.gateway.utils;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
/**
* WVP Token 客户端
* 用于获取 WVP-PRO access token
*/
public class WvpTokenClient {
private static final Logger log = LoggerFactory.getLogger(WvpTokenClient.class);
// WVP 服务地址 - 使用容器名称进行容器间通信
private static final String WVP_BASE_URL = "http://wvp-pro:18978";
private static final ObjectMapper objectMapper = new ObjectMapper();
/**
* WVP登录响应对象
*/
public static class LoginResponse {
private int code;
private String msg;
private LoginData data;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public LoginData getData() {
return data;
}
public void setData(LoginData data) {
this.data = data;
}
}
/**
* 登录数据对象
*/
public static class LoginData {
private String accessToken;
private String username;
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
/**
* 计算MD5哈希值
*
* @param input 输入字符串
* @return MD5哈希值小写
* @throws Exception 如果计算失败
*/
private static String md5(String input) throws Exception {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] messageDigest = md.digest(input.getBytes(StandardCharsets.UTF_8));
StringBuilder hexString = new StringBuilder();
for (byte b : messageDigest) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
}
/**
* WVP用户登录
*
* @param username 用户名
* @param password 密码明文
* @return 登录响应对象
* @throws Exception 如果请求失败
*/
public static LoginResponse login(String username, String password) throws Exception {
// 计算密码的MD5值
String passwordMd5 = md5(password);
// 构建 URL 参数
StringBuilder urlBuilder = new StringBuilder(WVP_BASE_URL);
urlBuilder.append("/api/user/login?");
urlBuilder.append("username=").append(URLEncoder.encode(username, StandardCharsets.UTF_8.name()));
urlBuilder.append("&password=").append(passwordMd5);
// 创建 HTTP 连接
URL url = new URL(urlBuilder.toString());
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(10000);
connection.setReadTimeout(10000);
// 获取响应
int responseCode = connection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
BufferedReader reader = new BufferedReader(
new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8));
StringBuilder response = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
response.append(line);
}
reader.close();
// 解析JSON响应
return objectMapper.readValue(response.toString(), LoginResponse.class);
} else {
throw new Exception("HTTP 请求失败,状态码: " + responseCode);
}
}
}