springboot 项目开启https

132 阅读3分钟

需求背景: 《产品安全技术白皮书》中“保密性和完整性”章节说明,哪些重要数据在传输过程中进行了检验加密,并描述校验方案和加密方案;采用HTTPS或基于TLS的通信方案,则视为满足该项要求;重要数据至少包括用户口令密码/个人隐私信息/敏感信息
需要做到两点:

1.项目网关服务开启https
2.由于由于正规的ssl证书需要CA认证颁发,目前用于测试,自己制作,使用jdk自签ssl证书。

前言:实际工作中为了提高数据传输的安全性,采用HTTPS通讯,简单来说,HTTPS协议是由SSL+HTTP协议构建的可进行加密传输,相比http协议安全。SSL证书需要到CA机构申请证书,仅为测试可以使用jdk生成自签证书。

配置步骤如下:

由于没有从相关机构申请证书,使用jdk自带的证书管理工具进行生成,方法如下:

一、JDK生成自签证书,以管理员身份运行CMD窗口(根据需要生成不同类型的证书 JKS/PKCS12)

**命令:**keytool -genkey -alias testhttps -keyalg RSA -keysize 2048 -validity 36500 -keystore “D:/tmp/ssl/testhttps.keystore”

或者 keytool -genkey -alias tomcat -storetype PKCS12 -keyalg RSA -keysize 2048 -keystore keystore.p12 -validity 3650

命令解释:

-genkey 表示要创建一个新的密钥。

-alias 表示 keystore 的别名。

-keyalg 表示使用的加密算法是 RSA。

-keysize 表示密钥的长度.。

-keystore 表示生成的密钥存放位直。

-validity 表示密钥的有效时间,单位为天。

二、在springboot 中项目配置证书

  1. 将第一步生成的 testhttps.keystore 文件放入 /resource 目录下(即classpath目录)
也可以直接放到自己想放的路径下,在application.properties配置中对应绝对路径就好。
  1. 如果是application.yml 配置文件中添加ssl 相关配置:
server:
 port: 9090
 servlet:
 context-path: /ssl-service

  ssl:
    key-store: classpath:testhttps.keystore  #类路径下的自签证书(可绝对路径或相对路径)
    key-alias: testhttps # 证书别名
    key-store-password: 123456 #证书密码
    key-store-type: JKS # 证书类型
    enabled: true  # 开启证书验证

如果是application.properties配置文件中添加ssl 相关配置:

#https

server.ssl.enabled=true

server.ssl.key-store= classpath:keystore.p12

server.ssl.protocol=TLS

server.ssl.key-store-password= 自定义

server.ssl.keyStoreType= PKCS12

server.ssl.keyAlias= tomcat

配置跳转

创建下面的配置类

import org.apache.catalina.Context;
import org.apache.catalina.connector.Connector;
import org.apache.tomcat.util.descriptor.web.SecurityCollection;
import org.apache.tomcat.util.descriptor.web.SecurityConstraint;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
 
/**
 * 设置将访问80端口的请求跳转到指定的端口上去,这样用户就可以直接输入设备地址访问而不需要输入前缀和端口了
 *
 * @author 阿信sxq
 *
 */
@Configuration
public class ContainerCustomizer {
 
    @Value("${server.port}")
    private Integer webPort;
 
    /**
     * 构建servlet容器的工厂类
     * 将80端口跳转到{@linkplain #webPort}端口
     *
     * @return 内置servlet容器类的工厂实例
     */
    @Bean
    public EmbeddedServletContainerFactory servletContainer() {
        TomcatEmbeddedServletContainerFactory factory = 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);
            }
        };
        factory.addAdditionalTomcatConnectors(createConnector());
        return factory;
    }
 
    /**
     * 创建tomcat连接器。
     * 该连接器将会接收http的80端口的访问,并且重定向到指定的端口上去,{@linkplain #webPort}
     *
     * @return tomcat连接器
     */
    private Connector createConnector() {
        final Connector connector = new Connector();
 
        connector.setPort(80);
        connector.setRedirectPort(webPort);
        return connector;
    }
}

这个是使用内置的tomcat做容器的配置方式,使用jetty需要使用另外的方式。

jetty配置跳转

下面的代码来自stackoverflow.com/questions/2…](so.csdn.net/so/search?q…
由于没有使用jetty,所以没有进行验证

import org.eclipse.jetty.security.ConstraintMapping;
import org.eclipse.jetty.security.ConstraintSecurityHandler;
import org.eclipse.jetty.util.security.Constraint;
import org.eclipse.jetty.webapp.AbstractConfiguration;
import org.eclipse.jetty.webapp.WebAppContext;
 
class HttpToHttpsJettyConfiguration extends AbstractConfiguration {
    // http://wiki.eclipse.org/Jetty/Howto/Configure_SSL#Redirecting_http_requests_to_https
    @Override
    public void configure(WebAppContext context) throws Exception {
        Constraint constraint = new Constraint();
        constraint.setDataConstraint(2);
 
        ConstraintMapping constraintMapping = new ConstraintMapping();
        constraintMapping.setPathSpec("/*");
        constraintMapping.setConstraint(constraint);
 
        ConstraintSecurityHandler constraintSecurityHandler = new ConstraintSecurityHandler();
        constraintSecurityHandler.addConstraintMapping(constraintMapping);
 
        context.setSecurityHandler(constraintSecurityHandler);
    }
}
@Configuration
public class HttpToHttpsJettyCustomizer implements EmbeddedServletContainerCustomizer{
    @Override
    public void customize(ConfigurableEmbeddedServletContainer container) {
        JettyEmbeddedServletContainerFactory containerFactory = (JettyEmbeddedServletContainerFactory) container;
        //Add a plain HTTP connector and a WebAppContext config to force redirect from http->https
        containerFactory.addConfigurations(new HttpToHttpsJettyConfiguration());
 
        containerFactory.addServerCustomizers(server -> {
            HttpConfiguration http = new HttpConfiguration();
            http.setSecurePort(443);
            http.setSecureScheme("https");
 
            ServerConnector connector = new ServerConnector(server);
            connector.addConnectionFactory(new HttpConnectionFactory(http));
            connector.setPort(80);
 
            server.addConnector(connector);
        });
    }
}

特别说明

使用上面的方法配置的https由于证书不是受信的,所以浏览器会报警告,需要手工确认,这个没办法

附获取阿里云/腾讯云ssl证书方式开启https: blog.csdn.net/m0_49683806…

转载于:my.oschina.net/songxinqian…