SpringBoot是一个非常流行的Java开发框架,支持各种协议,如Http、Https等。本篇攻略将详细讲解SpringBoot中支持Https协议的实现方法。
准备工作
在SpringBoot中支持Https协议,需要准备三个文件:
- SSL证书文件(如:keystore.jks或server.crt)
- SSL证书密码(如:123456)
- 修改application.yml或application.properties文件,设置端口号、证书文件路径和证书密码
如果你没有SSL证书文件,可以通过以下命令自动生成:
$ keytool -genkey -alias tomcat -keyalg RSA -keystore keystore.jks -validity 3650
添加依赖
首先需要添加SpringBoot的Web依赖项。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
其次,需要添加javax.servlet-api的依赖项,以及SpringBoot自带的Tomcat https的依赖项。
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>${tomcat.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-logging-juli</artifactId>
<version>${tomcat.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<version>${tomcat.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-websocket</artifactId>
<version>${tomcat.version}</version>
</dependency>
其中,${tomcat.version}是Tomcat的版本号(如8.5.50)。
SpringBoot配置
配置证书
首先需要将证书文件拷贝到项目的resource目录下,然后在application.yml
或application.properties
文件中添加以下配置:
server:
port: 8000
ssl:
key-store: classpath:keystore.jks
key-store-password: 123456
key-password: 123456
其中,key-store
是证书文件的路径,使用classpath:
前缀表示在项目的resource目录下,key-store-password
是证书文件的密码,key-password
是密钥的密码。
开启Https协议
要在SpringBoot中启用HTTPS,可以使用WebServerFactoryCustomizer
或者EmbeddedServletContainerCustomizer
进行配置。
采用WebServerFactoryCustomizer方式
@Configuration
public class HttpsConfig {
@Value("${server.port}")
private int port;
@Value("${server.ssl.key-store}")
private String keyStorePath;
@Value("${server.ssl.key-store-password}")
private String keyStorePassword;
@Value("${server.ssl.key-password}")
private String keyPassword;
@Bean
public ServletWebServerFactory servletContainer() {
TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory() {
@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);
}
};
// 添加SSL配置
tomcat.addConnectorCustomizers(connector -> {
connector.setPort(port);
connector.setSecure(true);
connector.setScheme("https");
Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler();
protocol.setSSLEnabled(true);
protocol.setKeystoreFile(keyStorePath);
protocol.setKeystorePass(keyStorePassword);
protocol.setKeyPass(keyPassword);
});
return tomcat;
}
}
采用EmbeddedServletContainerCustomizer方式
@Configuration
public class HttpsConfig {
@Value("${server.port}")
private int port;
@Value("${server.ssl.key-store}")
private String keyStorePath;
@Value("${server.ssl.key-store-password}")
private String keyStorePassword;
@Value("${server.ssl.key-password}")
private String keyPassword;
@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);
}
};
// 添加SSL配置
tomcat.addConnectorCustomizers(new TomcatConnectorCustomizer() {
@Override
public void customize(Connector connector) {
connector.setPort(port);
connector.setSecure(true);
connector.setScheme("https");
Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler();
protocol.setSSLEnabled(true);
protocol.setKeystoreFile(keyStorePath);
protocol.setKeystorePass(keyStorePassword);
protocol.setKeyPass(keyPassword);
}
});
return tomcat;
}
}
启动测试
在项目的Controller中添加一个接口用于测试:
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello() {
return "Hello World!";
}
}
启动服务器,通过HTTPS请求访问接口。可以使用两种方式进行测试:
- 使用浏览器访问:在浏览器中输入
https://localhost:8000/hello
,提示证书不安全后进入网站,验证Hello World!输出是否正确。 - 使用curl命令:在命令行中输入
curl -k https://localhost:8000/hello
,使用-k
参数表示忽略证书警告,验证Hello World!输出是否正确。
示例
这里提供两个示例:
示例1
在自己的项目中使用Https协议进行数据加密,以保证数据的安全,代码示例如下:
@Configuration
public class HttpsConfig {
@Value("${server.port}")
private int port;
@Value("${server.ssl.key-store}")
private String keyStorePath;
@Value("${server.ssl.key-store-password}")
private String keyStorePassword;
@Value("${server.ssl.key-password}")
private String keyPassword;
@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);
}
};
// 添加SSL配置
tomcat.addConnectorCustomizers(new TomcatConnectorCustomizer() {
@Override
public void customize(Connector connector) {
connector.setPort(port);
connector.setSecure(true);
connector.setScheme("https");
Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler();
protocol.setSSLEnabled(true);
protocol.setKeystoreFile(keyStorePath);
protocol.setKeystorePass(keyStorePassword);
protocol.setKeyPass(keyPassword);
}
});
return tomcat;
}
}
示例2
在开发环境中使用自定义证书实现Https协议,以便进行开发调试,代码示例如下:
@Configuration
public class HttpsConfig {
@Value("${server.port}")
private int port;
@Value("${server.ssl.key-store}")
private String keyStorePath;
@Value("${server.ssl.key-store-password}")
private String keyStorePassword;
@Value("${server.ssl.key-password}")
private String keyPassword;
/**
* 配置https
*/
@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);
}
};
// 添加SSL配置
tomcat.addConnectorCustomizers(new TomcatConnectorCustomizer() {
@Override
public void customize(Connector connector) {
connector.setPort(port);
connector.setSecure(true);
connector.setScheme("https");
Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler();
protocol.setSSLEnabled(true);
String keystoreFile = keystoreBinFile().getAbsolutePath();
protocol.setKeystoreFile(keystoreFile);
protocol.setKeystorePass("password");
protocol.setKeyPass("password");
}
});
return tomcat;
}
/**
* 自定义证书路径
*/
@Bean
public File keystoreBinFile() {
String home = System.getProperty("user.home");
File file = new File(home, ".keystore");
if (file.exists()) {
return file;
}
try {
createKeyStore(file.getPath());
} catch (Exception e) {
throw new RuntimeException(e);
}
return file;
}
/**
* 通过keytool命令生成证书
* keytool -genkeypair -alias tomcat -keyalg RSA -keysize 2048 -keystore ~/.keystore -validity 365 -storepass password -keypass password
*/
public static void createKeyStore(String filename) throws Exception {
String cmd = String.format("keytool -genkeypair -alias tomcat -keyalg RSA -keysize 2048 -keystore %s -validity 365 -storepass password -keypass password", filename);
Runtime.getRuntime().exec(cmd).waitFor();
}
}
注意:在示例2中,需要先使用keytool
命令生成证书,然后将证书拷贝到$HOME/.keystore
文件中,并在HttpConfig
中指定证书路径即可。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:SpringBoot中支持Https协议的实现 - Python技术站