SpringBoot配置使用SSL、使用Https

1.首先去腾讯云或者阿里云申请免费ssl证书,以腾讯云为例,不建议自己生成,因为没办法测试发布环境的效果,填写个人信息,最后提示审核中才是申请成功,审核比较快,半小时就通过了。

 

2.下载已经通过审核的证书文件夹,解压文件如下,根据项目选择使用:

3.因为springboot使用的是内置tomcat,所以我这边选择tomcat文件,在resources目录下导入xxx.jks

 4.接下来配置properties文件,密码在同文件夹的keystorePass.txt中(腾讯云)

 

 5.个人比较喜欢yml格式,简洁直观(阿里云)

6.到这个时候基本配置完成,但不能使用https后就通知所有人重新保存网址,这时候就需要增加请求转发,自动从http转到https

   写法一:在启动类也就是@SpringBootApplication注解类中加上使用

/**
 * http重定向到https
 * @return
 */
@Bean
public TomcatServletWebServerFactory servletContainer() {
    TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory() {
        @Override
        protected void postProcessContext(Context context) {
            SecurityConstraint constraint = new SecurityConstraint();
            constraint.setUserConstraint("CONFIDENTIAL");
            SecurityCollection collection = new SecurityCollection();
            collection.addPattern("/*");
            constraint.addCollection(collection);
            context.addConstraint(constraint);
        }
    };
    tomcat.addAdditionalTomcatConnectors(httpConnector());
    return tomcat;
}

@Bean
public Connector httpConnector() {
    Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
    connector.setScheme("http");
    //Connector监听的http的默认端口号
    connector.setPort(8080);
    connector.setSecure(false);
    //监听到http的端口号后转向到的https的端口号,也就是项目配置的port
    connector.setRedirectPort(8089);
    return connector;
}

写法二:另外新建一个配置类,加上@Configuration注解声明

@Configuration
public class TomcatConfig {
    @Bean
    TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory() {
        TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory(){
            @Override
            protected void postProcessContext(Context context) {
                SecurityConstraint constraint = new SecurityConstraint();
                constraint.setUserConstraint("CONFIDENTIAL");
                SecurityCollection collection = new SecurityCollection();
                collection.addPattern("/*");
                constraint.addCollection(collection);
                context.addConstraint(constraint);
            }
        };
        factory.addAdditionalTomcatConnectors(createTomcatConnector());
        return factory;
    }

    private Connector createTomcatConnector() {
        Connector connector = new
                Connector("org.apache.coyote.http11.Http11NioProtocol");
        connector.setScheme("http");
        connector.setPort(5001);
        connector.setSecure(false);
        connector.setRedirectPort(443);
        return connector;
    }
}

7.现在可以通过https://域名:8089/index访问,这样就看到熟悉的小锁了

注意:RestTemplate设置headers,访问https实现ssl请求参考:https://www.jianshu.com/p/beafe38428c7

application.properties配置:

 

#远程调用uri及ssl设置
httpClientUri=https://192.168.3.110:8081
#类型
httpClientSSL.keyStoreType=JKS
#classpath下的文件名
httpClientSSL.keyFile= easyView.keystore
#证书密码
httpClientSSL.keyPassword=xxxx

 

 

下面是自己封装的调用方法:

import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.*;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import javax.net.ssl.SSLContext;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.KeyStore;
import java.util.Objects;
import java.util.function.Consumer;

/**
 * @date 2020/11/04
 */
@Component
public class HttpsUtil {

    private static Logger logger = LoggerFactory.getLogger(HttpsUtil.class);


    @Value("${httpClientSSL.keyStoreType}")
    private String keyStoreType;
    @Value("${httpClientSSL.keyFile}")
    private String keyFile;
    @Value("${httpClientSSL.keyPassword}")
    private String keyPassword;
    @Value("${httpClientUri}")
    private String url;

    public static final String GET = "GET";

    public static final String POST = "POST";

    public static final String PUT = "PUT";
    
    

    /**
     * RestTemplate访问https请求
     *
     * @param data
     * @param addHeader
     * @return
     */
    public String transferRestTemplate(String path, String data, String httpMethod, Consumer<HttpHeaders> addHeader) {
        String body = null;
        try {
            KeyStore keyStore = KeyStore.getInstance(keyStoreType);
            ClassPathResource resource = new ClassPathResource(keyFile);
            InputStream inputStream = new FileInputStream(resource.getFile());
            keyStore.load(inputStream,keyPassword.toCharArray());
            SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(keyStore, TrustSelfSignedStrategy.INSTANCE).build();
            // Allow TLSv1 protocol only
            SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslcontext);
            CloseableHttpClient httpclient = HttpClients.custom()
                    .setSSLSocketFactory(socketFactory)
                    .build();
            HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(httpclient);
            RestTemplate restTemplate = new RestTemplate(clientHttpRequestFactory);
            HttpHeaders requestHeaders = new HttpHeaders();
            addHeader.accept(requestHeaders);
            requestHeaders.setContentType(MediaType.APPLICATION_JSON);
            HttpEntity<String> httpEntity = new HttpEntity<>(data, requestHeaders);
            ResponseEntity<String> response = null;
            switch(httpMethod){
                case HttpsUtil.GET :
                    response = restTemplate.exchange(url+ path, HttpMethod.GET, httpEntity, String.class);
                    break;
                case HttpsUtil.POST :
                    response = restTemplate.exchange(url+ path, HttpMethod.POST, httpEntity, String.class);
                    break;
                case HttpsUtil.PUT :
                    response = restTemplate.exchange(url+ path, HttpMethod.PUT, httpEntity, String.class);
                    break;
                default:
                    logger.error("非法请求方式:", new IllegalStateException(httpMethod));
            }
            if (Objects.nonNull(response)) {
                if (response.getStatusCode().is2xxSuccessful()) {
                    body = response.getBody();
                }
                logger.info("返回状态码: {}, 返回数据: {}", response.getStatusCodeValue(), body);
            }else {
                logger.info("response is null");
            }
        }catch (Exception e) {
            logger.error("https请求错误:", e);
        }
        return body;
    }

}

 

 

8.通过域名访问失败原因及解决办法

  1. 域名未配置解析,去域名管理配置解析,10分钟后通过ping 域名看是否显示ip,显示则解析成功!
  2. 域名未认证,去域名管理上传个人信息进行域名实名!
  3. 域名已实名但未网站未备案,解决办法
    1. 去进行网站实名,使用腾讯云小程序认证进行icp备案即可!
    2. 可以通过域名访问但必须加上自定义端口才行,不能使用8080或443等默认端口,否则提示连接已重置! 
posted @ 2020-11-04 11:25  47号Gamer丶  阅读(1179)  评论(0编辑  收藏  举报