SpringCloudGateway配置https
一.生成证书证书本应是花钱买,客户端才能通过根CA仓库识别证书。如果是自定义生成的证书,客户端访问时,会提示不安全的链接 是否继续访问,或者客户端可以将证书导入自己的本地CA仓库。生成证书可以通过 openssl,或者jdk的工具keytool生成。使用openssl,参考:https://www.jianshu.com/p/0e9ee7ed6c1d,先生成虚拟的CA,再生成证书,再用CA为证书签
一.生成证书
证书本应是花钱买,客户端才能通过根CA仓库识别证书。
如果是自定义生成的证书,客户端访问时,会提示不安全的链接 是否继续访问,或者客户端可以将证书导入自己的本地CA仓库。
生成证书可以通过 openssl,或者jdk的工具keytool生成。
使用openssl,参考:https://www.jianshu.com/p/0e9ee7ed6c1d ,先生成虚拟的CA,再生成证书,再用CA为证书签名
使用keytool:
keytool -genkeypair -alias client -keyalg RSA -keysize 2048 -storetype PKCS12 -keystore keystore.p12 -validity 3650
证书不同格式之间转换 参考:https://blog.csdn.net/qq_37049781/article/details/84837342
二.gateway配置
将证书放在 resources文件夹下
server:
port: 9000
ssl:
enabled: true
key-alias: client //证书别名
key-store: classpath:keystore.p12 //证书位置
key-store-password: 123456 //生成证书时的密码
key-store-type: PKCS12 //证书类型
如果是JKS类型证书:
server:
ssl:
key-alias: spring
enabled: true
key-password: spring
key-store: classpath:selfsigned.jks
key-store-type: JKS
key-store-provider: SUN
key-store-password: spring
一般下游服务使用http,只有网关使用https,所以网关路由下游服务时,需要将https修改为http。以下是拦截器,在路由过滤器LoadBalancerClientFilter前 将请求修改。
这个参考《重新定义springcloud一书》,github地址:https://github.com/SpringCloud/spring-cloud-code/tree/master/ch18-4
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.net.URI;
/**
* 在LoadBalancerClientFilter执行之前将Https修改为Http
* https://github.com/spring-cloud/spring-cloud-gateway/issues/378
*/
@Component
public class HttpsToHttpFilter implements GlobalFilter, Ordered {
private static final int HTTPS_TO_HTTP_FILTER_ORDER = 10099;
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
URI originalUri = exchange.getRequest().getURI();
ServerHttpRequest request = exchange.getRequest();
ServerHttpRequest.Builder mutate = request.mutate();
String forwardedUri = request.getURI().toString();
if (forwardedUri != null && forwardedUri.startsWith("https")) {
try {
URI mutatedUri = new URI("http",
originalUri.getUserInfo(),
originalUri.getHost(),
originalUri.getPort(),
originalUri.getPath(),
originalUri.getQuery(),
originalUri.getFragment());
mutate.uri(mutatedUri);
} catch (Exception e) {
throw new IllegalStateException(e.getMessage(), e);
}
}
ServerHttpRequest build = mutate.build();
return chain.filter(exchange.mutate().request(build).build());
}
/**
* 由于LoadBalancerClientFilter的order是10100,
* 要在LoadBalancerClientFilter执行之前将Https修改为Http,需要设置
* order为10099
* @return
*/
@Override
public int getOrder() {
return HTTPS_TO_HTTP_FILTER_ORDER;
}
}
三.问题
以上操作后,确实可以再浏览器以 https访问成功,但gateway报一个错误。
javax.net.ssl.SSLException: Received fatal alert: certificate_unknown
这个应该是客户端问题,客户端不信任这个证书,如果将证书添加到浏览器信任证书中,ie浏览器访问就不会报错,但谷歌浏览器还会。如果是正式证书应该不会有问题。
更多推荐
所有评论(0)