加密解密Util
import com.alibaba.fastjson.JSONObject; import org.apache.commons.codec.binary.Base64; import javax.crypto.Cipher; import java.io.ByteArrayOutputStream; import java.security.*; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.HashMap; import java.util.Map; public class RSAEncrypt { private static Map<Integer, String> keyMap = new HashMap<Integer, String>(); //用于封装随机产生的公钥与私钥 public static String PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDPaJOEpH+TYNrYoHhVdfxwr5JomM9OTAbC4OuPDEVCGpY9J0OTi2yG8Q2M37c6fm+4+E6vGsfZcimszKNWut/wUQ1YirSCnE7OIilwFuCnwRj+ELvwkG3CYVz9cRAUh8ospdvVwroq56AF04j2r1MgMzB/sJWV5XBWlx9So3xNOwIDAQAB"; public static String PRIVATE_KEY= "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAM9ok4Skf5Ng2tigeFV1/HCvkmiYz05MBsLg648MRUIalj0nQ5OLbIbxDYzftzp+b7j4Tq8ax9lyKazMo1a63/BRDViKtIKcTs4iKXAW4KfBGP4Qu/CQbcJhXP1xEBSHyiyl29XCuirnoAXTiPavUyAzMH+wlZXlcFaXH1KjfE07AgMBAAECgYB1UHRoSVczuEvwzctio2rXHifU6+IOKmiEoA39Cna+LiWej2/kq68GIKCGdx+/gTaWTDTNTHuP3cf+ynz1GJyC33J6BtWXp4GCv21k/ivGyFdjfX/d89OPn5n1LbImRqh9SgSc5SlvU66K7y5AqBBnI19nrh2XDaENSqHoEU22qQJBAPOYF8ZxwETI21Ntmr0Gz+e9vMP13kRduEA1U/B02LEgYjY8iqT41+4DEmQA1FNqe13GuIdI0P/RgB7zMceWlk0CQQDZ+LTJNUg2/NygMyjzm854Ru6IIrS6s2YaYEeD1Ejka/RWn4BO4CR0hVIzx4hkwUcusNOy+EzZBer5w0oyc8WnAkEAuviPryraeDFvXz7umY5kAC07eXH7s5/375i/H/6f4HzJxXV8uZmjK7ZB5G5aithdbqI8OuKiQOkOHTNvjxG/tQJBAMgNKDfHDDlTiFYLvlkfNbdUOpZ9a+wyvNIWbWyDyEbFAeMCzusVcr/yoMhfKEJ41ZD3v8RxeW5xrQCAiTeW498CQQC3gCZwMzG/laJwVnCQtychXg82r+93Lz4SxsMBQ7ygWMrqQN8WB0JtAt1f2DwoDDPR8PDDrv5KiAGxjMrzgA1O"; private static final String ALGORITHM = "RSA"; /** * RSA最大加密明文大小 */ private static final int MAX_ENCRYPT_BLOCK = 117; public static void main(String[] args) throws Exception { //生成公钥和私钥 // genKeyPair(); // //加密字符串 // //String message = "df723820"; Map<String, Object> map = new HashMap<String, Object>(); //map.put("username", "13019352001"); //map.put("password", MD5Utils.md5Hex("123456".getBytes())); map.put("userId", 1); JSONObject json = new JSONObject(map); String messageEn = encrypt(JSONObject.toJSONString(json),PUBLIC_KEY); System.out.println(messageEn + "\t加密后的字符串为:" + messageEn); String messageDe = decrypt(messageEn,PRIVATE_KEY); System.out.println("还原后的字符串为:" + messageDe); // User user = new User(); // user.setUserName("13019352002"); // user.setPassword("123456"); // user.setSex("1"); // JSONObject.toJSONString(user); // Map<String, Object> map = new HashMap<String, Object>(); // map.put("pageNum", 1); // map.put("pageSize", 10); // JSONObject json = new JSONObject(map); // String messageEn = encrypt(JSONObject.toJSONString(json),PUBLIC_KEY); // System.out.println(messageEn + "\t加密后的字符串为:" + messageEn); // String messageEn = "yS/8tswgmAXuPoW0jtzjVvQXuou+PZ7FSQ+nm/LYd3ExNKngcaDLLiCqUl4kETlAGBWcDyNaMbL0FP4IxwwmyizHCgt0Kp5ldkj3SVkOKora1PSA88LKPxXwpFJPm/z/4MTVM+0TfmeTdIXacK21DSXLfbzblqvoDuETBSDZNQVVhQKOmL62Ou1Jepakoc2pstsJq1AoSVmOPOmiKNWUGxj8UzLkR/blX71QVhA/k348zISYK+2X7Q3hyfkYL9xuDk5OfrdWi62BfOLp3hO2RbGW7Yd8TLjx/gfXfLHAMKlytsuR/ePt5s/bsl96eeKgmB9Ba/B4zI0MB0nb7Rf/naEJkEAUENu3vbNbnYjNdUhUxygzyn5T9GhHom0gvhEu/XTlUAlwQba3OL8ZInlbGoZhu5Pc1rP+OTJOGt3gYRIathT54MLbxBSm7JSAZkvfABe2cc8+AH/scJzOkUhpSbs3VJdFxcgWIKdjveDrvGA8u0bzNz/KNd1ARcOYZJrCx/SMiu8XoW0ilbc+0HfoYmSqhhYzbnYkYCH8uberwi7pA7RzNp46UNEBnqUpDZ2thQ9Xk8Z6/FiYglggIbpV6Szp/fOHsENEgrv3gfmAjltMTnoNdTXZSrirg5GXyn14koZW52tg/Zty0NO4xuD6aLLiXX42mhhiPniz5axrxCA="; // String messageDe = decrypt(messageEn,PRIVATE_KEY); // System.out.println("还原后的字符串为:" + messageDe); } /** * 随机生成密钥对 * @throws NoSuchAlgorithmException */ public static void genKeyPair() throws NoSuchAlgorithmException { // KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象 KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA"); // 初始化密钥对生成器,密钥大小为96-1024位 keyPairGen.initialize(1024,new SecureRandom()); // 生成一个密钥对,保存在keyPair中 KeyPair keyPair = keyPairGen.generateKeyPair(); RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); // 得到私钥 RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); // 得到公钥 String publicKeyString = new String(Base64.encodeBase64(publicKey.getEncoded())); // 得到私钥字符串 String privateKeyString = new String(Base64.encodeBase64((privateKey.getEncoded()))); // 将公钥和私钥保存到Map keyMap.put(0,publicKeyString); //0表示公钥 keyMap.put(1,privateKeyString); //1表示私钥 } /** * RSA公钥加密 * * @param input * 加密字符串 * @param rsaPublicKey * 公钥 * @return 密文 * @throws Exception * 加密过程中的异常信息 */ public static String encrypt( String input, String rsaPublicKey ) throws Exception{ byte[] decoded = Base64.decodeBase64(rsaPublicKey); RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded)); //RSA加密 Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.ENCRYPT_MODE, pubKey); byte[] data = input.getBytes(); X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(decoded); KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM); Key key = keyFactory.generatePublic(x509EncodedKeySpec); // 加密数据,分段加密 int inputLength = data.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offset = 0; byte[] cache; int i = 0; while (inputLength - offset > 0) { if (inputLength - offset > MAX_ENCRYPT_BLOCK) { cache = cipher.doFinal(data, offset, MAX_ENCRYPT_BLOCK); } else { cache = cipher.doFinal(data, offset, inputLength - offset); } out.write(cache, 0, cache.length); i++; offset = i * MAX_ENCRYPT_BLOCK; } byte[] encryptedData = out.toByteArray(); out.close(); return Base64.encodeBase64String(encryptedData); } /** * RSA私钥解密 * * @param str * 加密字符串 * @param privateKey * 私钥 * @return 铭文 * @throws Exception * 解密过程中的异常信息 */ public static String decrypt(String str, String privateKey) throws Exception{ // 得到私钥 byte[] data = Base64.decodeBase64(str.getBytes("UTF-8")); byte[] decoded = Base64.decodeBase64(privateKey); RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded)); // 解密数据,分段解密 Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.DECRYPT_MODE, priKey); int inputLength = data.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offset = 0; byte[] cache; int i = 0; byte[] tmp; Integer MAX_DECRYPT_BLOCK = 128; while (inputLength - offset > 0) { if (inputLength - offset > MAX_DECRYPT_BLOCK) { cache = cipher.doFinal(data, offset, MAX_DECRYPT_BLOCK); } else { cache = cipher.doFinal(data, offset, inputLength - offset); } out.write(cache); i++; offset = i * MAX_DECRYPT_BLOCK; } byte[] decryptedData = out.toByteArray(); out.close(); String result = new String(decryptedData); return result; } }
gateway请求参数统一处理
postman
Content-Type:application/x-www-form-urlencoded
参数例如:
请求参数解密拦截器
import com.ruoyi.common.core.constant.CacheConstants;
import com.ruoyi.gateway.Utils.GatewayContext;
import com.ruoyi.gateway.Utils.RSAEncrypt;
import io.netty.buffer.ByteBufAllocator;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.filter.factory.rewrite.CachedBodyOutputMessage;
import org.springframework.cloud.gateway.support.BodyInserterContext;
import org.springframework.cloud.gateway.support.DefaultServerRequest;
import org.springframework.core.Ordered;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.core.io.buffer.NettyDataBufferFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.reactive.function.BodyInserter;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
/**
* 网关鉴权
*
* @author ruoyi
*/
@Component
public class ReqEncryptRequestFilter implements GlobalFilter, Ordered
{
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
// TODO 如果请求的后台管理系统,则直接放行,不做加解密处理
if (request.getMethod() != HttpMethod.POST && request.getMethod() != HttpMethod.PUT && request.getMethod() != HttpMethod.PATCH) {
// 如果不是post(新增)、put(全量修改)、patch(部分字段修改)操作,则直接放行
return chain.filter(exchange);
}
// 对增/改操作,实现入参解密操作
return operationExchange(exchange, chain);
}
@Override
public int getOrder() {
return Integer.MIN_VALUE;
}
private Mono<Void> operationExchange(ServerWebExchange exchange, GatewayFilterChain chain) {
// 缓存请求路径
ServerHttpRequest request = exchange.getRequest();
String path = request.getPath().pathWithinApplication().value();
GatewayContext gatewayContext = new GatewayContext();
gatewayContext.setPath(path);
// 保存网关上下文到exchange中
exchange.getAttributes().put(GatewayContext.CACHE_GATEWAY_CONTEXT, gatewayContext);
HttpHeaders headers = request.getHeaders();
MediaType contentType = headers.getContentType();
Mono<Void> voidMono = null;
if (MediaType.APPLICATION_JSON.equals(contentType) || MediaType.APPLICATION_JSON_UTF8.equals(contentType)) {
// 对applicationjson类型数据做解密操作
voidMono = readBody(exchange, chain);
}
if (MediaType.APPLICATION_FORM_URLENCODED.equals(contentType)
|| (contentType != null && contentType.toString().startsWith(MediaType.MULTIPART_FORM_DATA_VALUE)) ) {
// form data
voidMono = readFormData(exchange, chain, gatewayContext);
}
if(voidMono == null){
voidMono = chain.filter(exchange);
}
return voidMono;
}
private Mono<Void> readFormData(
ServerWebExchange exchange,
GatewayFilterChain chain,
GatewayContext gatewayContext) {
final ServerHttpRequest request = exchange.getRequest();
HttpHeaders headers = request.getHeaders();
String userid = headers.getFirst("token");
return exchange.getFormData()
.doOnNext(multiValueMap -> {
gatewayContext.setFormData(multiValueMap);
})
.then(Mono.defer(() -> {
Charset charset = headers.getContentType().getCharset();
charset = charset == null ? StandardCharsets.UTF_8 : charset;
String charsetName = charset.name();
MultiValueMap<String, String> formData =
gatewayContext.getFormData();
/** formData is empty just return */
if (null == formData || formData.isEmpty()) {
return chain.filter(exchange);
}
StringBuilder formDataBodyBuilder = new StringBuilder();
String entryKey;
List<String> entryValue;
try {
/* repackage form data */
for (Map.Entry<String, List<String>> entry : formData
.entrySet()) {
entryKey = entry.getKey();
entryValue = entry.getValue();
if (entryValue.size() > 1) {
for (String value : entryValue) {
formDataBodyBuilder.append(entryKey).append("=")
.append(
URLEncoder.encode(value, charsetName))
.append("&");
}
} else {
formDataBodyBuilder
.append(entryKey).append("=").append(URLEncoder
.encode(decodeBody(entryValue.get(0)), charsetName))
.append("&");
}
}
} catch (UnsupportedEncodingException e) {
// ignore URLEncode Exception
}
/* substring with the last char '&' */
String formDataBodyString = "";
if (formDataBodyBuilder.length() > 0) {
formDataBodyString = formDataBodyBuilder.substring(0,
formDataBodyBuilder.length() - 1);
}
// date data bytes
byte[] bodyBytes = formDataBodyString.getBytes(charset);
int contentLength = bodyBytes.length;
ServerHttpRequestDecorator decorator =
new ServerHttpRequestDecorator(
request) {
@Override
public HttpHeaders getHeaders() {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.putAll(super.getHeaders());
httpHeaders.set(CacheConstants.DETAILS_USER_ID, userid);
if (contentLength > 0) {
httpHeaders.setContentLength(contentLength);
} else {
httpHeaders.set(HttpHeaders.TRANSFER_ENCODING,
"chunked");
}
return httpHeaders;
}
@Override
public Flux<DataBuffer> getBody() {
return DataBufferUtils
.read(new ByteArrayResource(bodyBytes),
new NettyDataBufferFactory(
ByteBufAllocator.DEFAULT),
contentLength);
}
};
ServerWebExchange mutateExchange =
exchange.mutate().request(decorator).build();
return chain.filter(mutateExchange);
}));
}
private Mono<Void> readBody(ServerWebExchange exchange, GatewayFilterChain chain) {
final ServerHttpRequest request = exchange.getRequest();
MediaType mediaType = request.getHeaders().getContentType();
// 修改响应体
ServerRequest serverRequest = new DefaultServerRequest(exchange);
Mono<String> modifiedBody = serverRequest.bodyToMono(String.class)
.flatMap(body -> {
// if (MediaType.APPLICATION_JSON.isCompatibleWith(mediaType)) {
// // 拿到公钥加密后的数据
// return Mono.just(decodeBody(body));
// }
// return Mono.empty();
// TODO 加解密暂未联调,先屏蔽掉
return Mono.just(body);
});
BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, String.class);
HttpHeaders headers = new HttpHeaders();
headers.putAll(request.getHeaders());
headers.remove(HttpHeaders.CONTENT_LENGTH);
CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(exchange, headers);
return bodyInserter.insert(outputMessage, new BodyInserterContext())
.then(Mono.defer(() -> {
ServerHttpRequestDecorator decorator = new ServerHttpRequestDecorator(
request) {
@Override
public HttpHeaders getHeaders() {
long contentLength = headers.getContentLength();
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.putAll(super.getHeaders());
if (contentLength > 0) {
httpHeaders.setContentLength(contentLength);
} else {
httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked");
}
return httpHeaders;
}
@Override
public Flux<DataBuffer> getBody() {
return outputMessage.getBody();
}
};
return chain.filter(exchange.mutate().request(decorator).build());
}));
}
private String decodeBody(String body){
// 拿到公钥加密后的数据
String newBoday = null;
try {
newBoday = RSAEncrypt.decrypt(body,RSAEncrypt.PRIVATE_KEY);
} catch (Exception e) {
e.printStackTrace();
}
return newBoday;
}
}
返回参数加密处理:
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.gateway.Utils.RSAEncrypt;
import org.reactivestreams.Publisher;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.nio.charset.Charset;
/**
* 网关鉴权
*
* @author ruoyi
*/
@Component
public class ReqFilter implements GlobalFilter, Ordered {
private int order;
// 设置到 exchange.getAttributes()中的key
public final static String CACHED_REQUEST_BODY_OBJECT_KEY = "CACHED_REQUEST_BODY_OBJECT_KEY";
// 设置到 exchange.getAttributes()中的key
public final static String BG_DEBUG_KEY = "BG_DEBUG";
// 请求参数,返回参数 加密
public final static String REQ_RES_ENCRYPT = "0";
// 请求参出,返回结果 无需加密
public final static String REQ_RES_NALMORE = "1";
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String bgDebug = exchange.getAttributeOrDefault(BG_DEBUG_KEY, REQ_RES_ENCRYPT);
ServerHttpResponse originalResponse = exchange.getResponse();
DataBufferFactory bufferFactory = originalResponse.bufferFactory();
ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(originalResponse) {
@Override
public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
if (body instanceof Flux) {
Flux<? extends DataBuffer> fluxBody = (Flux<? extends DataBuffer>) body;
return super.writeWith(fluxBody.buffer().map(dataBuffer -> {
DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory();
DataBuffer join = dataBufferFactory.join(dataBuffer);
byte[] content = new byte[join.readableByteCount()];
join.read(content);
//释放掉内存
DataBufferUtils.release(join);
// 正常返回的数据
String rootData = new String(content, Charset.forName("UTF-8"));
byte[] respData = rootData.getBytes();
if(REQ_RES_ENCRYPT.equals(bgDebug)){
// 对数据进行加密
String randomKey = RSAEncrypt.PUBLIC_KEY;
String encryptData = null;
try {
encryptData = RSAEncrypt.encrypt(rootData, randomKey);
} catch (Exception e) {
e.printStackTrace();
}
String encryptRandomKey = "999";
JSONObject json = new JSONObject();
json.put("k", encryptRandomKey);
json.put("v", encryptData);
respData = json.toJSONString().getBytes();
}
// 加密后的数据返回给客户端
byte[] uppedContent = new String(respData, Charset.forName("UTF-8")).getBytes();
return bufferFactory.wrap(uppedContent);
}));
}
return super.writeWith(body);
}
};
return chain.filter(exchange.mutate().response(decoratedResponse).build());
}
@Override
public int getOrder() {
return -1;
}
}