美文网首页
[Java] SSL 证书使用

[Java] SSL 证书使用

作者: 巨馍蘸酱 | 来源:发表于2022-11-24 14:30 被阅读0次

SSL 证书创建

Springboot

适用于 jar 直接运行

单向

  • yml
mydefine:
  port: 8081
server:
  port: 8011
  ssl:
    enabled: true
    key-store: classpath:certificate/server.p12 # src/main/resources/certificate/server.p12
    key-store-password: 123456
    key-store-type: PKCS12
  • SSLConfig
@Configuration
public class SSLConfig {

    // http 请求端口
    @Value("${mydefine.port}")
    private int serverPortHttp;

    // HTTPS 请求端口
    @Value("${server.port}")
    private int serverPortHttps;


    @Bean
    public Connector connector (){
        Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
        connector.setScheme("http");
        //Connector监听的http的端口号
        connector.setPort(serverPortHttp);
        connector.setSecure(false);
        //监听到http的端口号后转向到的https的端口号
        connector.setRedirectPort(serverPortHttps);
        return connector;
    }

    //springboot 2.x 可用
    @Bean
    public TomcatServletWebServerFactory tomcatServletWebServerFactory(Connector connector){
        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);
            }
        };
        tomcat.addAdditionalTomcatConnectors(connector);
        return tomcat;
    }
}

双向

  • yml
mydefine:
  port: 8082
server:
  port: 8022
  ssl:
    enabled: true
    key-store-type: PKCS12 # PKCS12 #JKS
    key-store: classpath:certificate/server.p12
    key-store-password: 123456
    key-alias: server
    client-auth: none
    #trust-store-provider: SUN
    trust-store-type: PKCS12
    trust-store: classpath:certificate/server.p12
    trust-store-password: 123456
  • SSLConfig
@Configuration
public class SSLConfig {

    // http 请求端口
    @Value("${mydefine.port}")
    private int serverPortHttp;

    // HTTPS 请求端口
    @Value("${server.port}")
    private int serverPortHttps;

    @Bean
    public Connector connector (){
        Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
        connector.setScheme("http");
        //Connector监听的http的端口号
        connector.setPort(serverPortHttp);
        connector.setSecure(false);
        //监听到http的端口号后转向到的https的端口号
        connector.setRedirectPort(serverPortHttps);
        return connector;
    }

    //springboot 2.x 可用
    @Bean
    public TomcatServletWebServerFactory tomcatServletWebServerFactory(Connector connector){
        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);
            }
        };
        tomcat.addAdditionalTomcatConnectors(connector);
        return tomcat;
    }
}
  • RestTemplateConfig
@Configuration
public class RestTemplateConfig {
    @Value("${server.ssl.key-store-type}")
    String clientKeyType;
    @Value("${server.ssl.key-store}")
    String clientPath;
    @Value("${server.ssl.key-store-password}")
    String clientPass;

    @Value("${server.ssl.trust-store-type}")
    String trustKeyType;
    @Value("${server.ssl.trust-store}")
    String trustPath;
    @Value("${server.ssl.trust-store-password}")
    String trustPass;

    @Bean
    public RestTemplate restTemplate() {
        RestTemplate restTemplate = null;
        try {
            HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
            // 客户端证书类型
            KeyStore clientStore = KeyStore.getInstance(clientKeyType);
            // 加载客户端证书,即自己的私钥
            InputStream keyStream = getClass().getClassLoader().getResourceAsStream(clientPath);
            clientStore.load(keyStream, clientPass.toCharArray());
            // 创建密钥管理工厂实例
            KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
            // 初始化客户端密钥库
            keyManagerFactory.init(clientStore, clientPass.toCharArray());
            KeyManager[] keyManagers = keyManagerFactory.getKeyManagers();

            // 创建信任库管理工厂实例
            TrustManagerFactory trustManagerFactory = TrustManagerFactory
                    .getInstance(TrustManagerFactory.getDefaultAlgorithm());
            KeyStore trustStore = KeyStore.getInstance(trustKeyType);
            InputStream trustStream = getClass().getClassLoader().getResourceAsStream(trustPath);
            trustStore.load(trustStream, trustPass.toCharArray());

            // 初始化信任库
            trustManagerFactory.init(trustStore);
            TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
            // 建立TLS连接
            SSLContext sslContext = SSLContext.getInstance("TLS");
            // 初始化SSLContext
            sslContext.init(keyManagers, trustManagers, new SecureRandom());
            // INSTANCE 忽略域名检查
            SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
            CloseableHttpClient httpclient = HttpClients
                    .custom()
                    .setSSLSocketFactory(sslConnectionSocketFactory)
                    .setSSLHostnameVerifier(new NoopHostnameVerifier())
                    .build();
            requestFactory.setHttpClient(httpclient);
            requestFactory.setConnectTimeout((int) Duration.ofSeconds(15).toMillis());
            restTemplate = new RestTemplate(requestFactory);
        } catch (KeyManagementException | FileNotFoundException | NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyStoreException | CertificateException | UnrecoverableKeyException | IOException e) {
            e.printStackTrace();
        }
        return restTemplate;
    }
}

Tomcat

  • tomcat/conf/server.xml
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol" maxThreads="150" SSLEnabled="true">
    <SSLHostConfig>
        <Certificate certificateKeystoreFile="conf/localhost-rsa.jks" type="RSA" certificateKeystorePassword="123456" />
    </SSLHostConfig>
</Connector>

或者

<Connector 
     port="443" 
     protocol="org.apache.coyote.http11.Http11NioProtocol" 
     maxThreads="150" 
     SSLEnabled="true" 
     scheme="https" 
     secure="true" 
     clientAuth="false" 
     sslProtocol="TLS" 
     keystoreFile="conf/localhost-rsa.jks" 
     keystorePass="123456" />

Nginx

nginx 配置后 tomcat / jar 不用配置

编辑配置文件 vim /usr/local/nginx/conf/nginx.conf

#user  nobody;
worker_processes  1;

events {
   worker_connections  1024;
}

http {
   include  mime.types;
   default_type  application/octet-stream;
   sendfile  on;
   keepalive_timeout  65;

   # http
   server {
      listen  80;
      server_name  localhost 192.168.1.1;
      return 301 https://$server_name$request_uri;
   }

   # https 单向认证
   server {
      listen       443 ssl;
      server_name  localhost 192.168.1.1;

      ssl_certificate /root/ssl/server.crt;
      ssl_certificate_key /root/ssl/server.key;

      location / {
         # 反向代理
         proxy_pass http://localhost:8080;
      }
   }

   # https 双向认证
   server {
        listen       443 ssl;
        server_name  localhost 192.168.1.1;

        ssl_certificate /root/ssl/server.crt;
        ssl_certificate_key /root/ssl/server.key;
        ssl_client_certificate /root/ssl/root.crt; # 根证书 也可以是单个的客户端证书
        ssl_verify_client on; # 开启双向认证
        
        ssl_session_timeout 10m;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE; 
        ssl_prefer_server_ciphers on;

        location / {
            # 反向代理
            proxy_pass http://localhost:8080;
        }
   }

   server {
        listen       443 ssl;
        server_name  localhost 192.168.1.1;

        ssl_certificate /root/ssl/server.crt;
        ssl_certificate_key /root/ssl/server.key;
        ssl_client_certificate /root/ssl/root.crt; # 根证书 也可以是单个的客户端证书
        ssl_verify_client optional; # 配置校验客户端策略, ssl_client_verify = SUCCESS
        
        ssl_session_timeout 10m;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE; 
        ssl_prefer_server_ciphers off;

        location / { # 需要双向验证https的接口
            if ($ssl_client_verify != SUCCESS) {
                 return 401;
            }
            proxy_pass http://localhost:8080;
            proxy_connect_timeout 600;
            proxy_read_timeout 600;
        }

        location /other/downloadUpdateFile { # 获取证书版本和下载证书接口,不需要验证Https
            proxy_pass http://localhost:8080;
            proxy_connect_timeout 600;
            proxy_read_timeout 600;
        }
   }
}

相关文章

网友评论

      本文标题:[Java] SSL 证书使用

      本文链接:https://www.haomeiwen.com/subject/uhcxfdtx.html