tomcat方案配置
证书生成:使用jdk提供的keytool命令,例如:
keytool -genkeypair -alias "tomcat" -keyalg "RSA" -keystore "E:\tomcat.keystore"
非springboot项目
修改tomcat下conf/server.xml,加入:
<Connector SSLEnabled="true" acceptCount="100" clientAuth="false" URIEncoding="UTF-8"
disableUploadTimeout="true" enableLookups="false" maxThreads="25"
port="8443" keystoreFile="E:\tomcat.keystore" keystorePass="123456"
protocol="org.apache.coyote.http11.Http11NioProtocol" scheme="https"
secure="true" sslProtocol="TLS" />
其中keystoreFile为证书存放路径,keystorePass为证书密码
springboot项目
修改application.yml文件:
server.port: 8443 #https端口
server.ssl.key-store: E:/keystore.p12 #证书路径
server.ssl.key-store-password: 123456 #证书密码
server.ssl.keyStoreType: PKCS12
server.ssl.keyAlias: tomcat
http.port: 8080#http端口
上述配置包含http端口8080和https端口8443
若要既支持http请求又支持https请求,则需要添加类如下:
@Configuration
public class HttpSupport {
@Value("${http.port}")
private int port;
@Bean
public EmbeddedServletContainerFactory servletContainer() {
TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory();
tomcat.addAdditionalTomcatConnectors(createHttpConnector());
return tomcat;
}
private Connector createHttpConnector() {
Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
connector.setScheme("http");
connector.setPort(port);
connector.setSecure(false);
return connector;
}
}
如果只支持https请求的话可以考虑将http请求强转成https,需添加类如下:
@Configuration
public class HttpsConfiguration {
@Value("${http.port}")
private int httpPort;
@Value("${server.port}")
private int httpsPort;
@Bean
public EmbeddedServletContainerFactory servletContainer() {
TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory() {
@Override
protected void postProcessContext(Context context) {
SecurityConstraint securityConstraint = new SecurityConstraint();
securityConstraint.setUserConstraint("CONFIDENTIAL");
SecurityCollection collection = new SecurityCollection();
collection.addPattern("/*");
securityConstraint.addCollection(collection);
context.addConstraint(securityConstraint);
}
};
tomcat.addAdditionalTomcatConnectors(initiateHttpConnector());
return tomcat;
}
private Connector initiateHttpConnector() {
Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
connector.setScheme("http");
connector.setPort(httpPort);
connector.setSecure(false);
connector.setRedirectPort(httpsPort);
return connector;
}
}
nginx方案配置
证书生成:使用openssl命令
修改nginx.conf文件:
server {
listen 443;
server_name localhost;
ssl on;
ssl_certificate D:/nginx/ssl/lee.crt;
ssl_certificate_key D:/nginx/ssl/lee.key;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 5m;
ssl_protocols SSLv3 TLSv1;
ssl_ciphers HIGH:!ADH:!EXPORT56:RC4+RSA:+MEDIUM;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://xxx.xx.x.xx:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-Ip $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
修改server.xml配置,在模块下添加:
<Valve className="org.apache.catalina.valves.RemoteIpValve"
remoteIpHeader="X-Forwarded-For"
protocolHeader="X-Forwarded-Proto"
protocolHeaderHttpsValue="https"/>
注意:由于反向代理用了7层转发,所以:
request.getScheme() //总是 http,而不是实际的http或https
request.isSecure() //总是false(因为总是http)
request.getRemoteAddr() //总是 nginx 请求的 IP,而不是用户的IP
request.getRequestURL() //总是 nginx 请求的URL 而不是用户实际请求的 URL
response.sendRedirect( 相对url ) //总是重定向到 http 上 (因为认为当前是 http 请求)
解决方案为:如上nginx和tomcat配置
proxy_set_header Host $host;
proxy_set_header X-Real-Ip $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
<Valve className="org.apache.catalina.valves.RemoteIpValve"
remoteIpHeader="X-Forwarded-For"
protocolHeader="X-Forwarded-Proto"
protocolHeaderHttpsValue="https"/>
通常在反向代理那边配X-Forwarded-For,Tomcat这边用request.getHeader("X-Forwarded-For")拿到用户真实IP地址。在反向代理那边配X-Forwarded-Proto这种Header,Tomcat这边用request.getHeader("X-Forwarded-Proto")来判断用户是否处于https状态。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。