Netty的wss支援

棲息之鷹發表於2020-04-06

1. 載入ssl證書的工具類

public class SslUtil {

    private static volatile SSLContext sslContext = null;

// type是PKCS12、path是pfx檔案路徑、password是pfx對應的密碼
public static SSLContext createSSLContext(String type ,String path ,String password) throws Exception { if(null == sslContext){ synchronized (SslUtil.class) { if(null == sslContext){ // 支援JKS、PKCS12(我們專案中用的是阿里雲免費申請的證書,下載tomcat解壓後的pfx檔案,對應PKCS12 KeyStore ks = KeyStore.getInstance(type); // 證書存放地址 InputStream ksInputStream = new FileInputStream(path); ks.load(ksInputStream, password.toCharArray()); KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); kmf.init(ks, password.toCharArray()); sslContext = SSLContext.getInstance("TLS"); sslContext.init(kmf.getKeyManagers(), null, null); } } } return sslContext; } }

2. 將SslHandler放在第一個

            bootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, 128)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        public void initChannel(SocketChannel ch) throws Exception {
                            ChannelPipeline pipeline = ch.pipeline();

                            // SSL處理器
                            SSLContext sslContext = SslUtil.createSSLContext(BaseGlobal.getCertType(),
                                    BaseGlobal.getCertPath(), BaseGlobal.getCertPassword());
                            SSLEngine sslEngine = sslContext.createSSLEngine();
                            sslEngine.setNeedClientAuth(false);
                            sslEngine.setUseClientMode(false);
                            pipeline.addLast("sslHandler", new SslHandler(sslEngine));

                            pipeline.addLast("idleStateHandler", new IdleStateHandler(readerIdleTimeSeconds,
                                    writerIdleTimeSeconds, allIdleTimeSeconds));
                            ...
                        }
                    });

 

3. 因為我們專案的特殊性,還需要同時支援TCP、WS協議,所以使用多執行緒載入兩個NettyServer

@EnableCaching
@EnableAutoConfiguration
@SpringBootApplication(scanBasePackages = "xxx")
@MapperScan(basePackages = "xxx")
@EnableAsync
public class V3xboxApplication {
    public static void main(String[] args) {
        SpringApplication.run(V3xboxApplication.class, args);

        // 啟動服務端(客戶端TCP連線)
        // 使用執行緒啟動,是因為Netty的sync方法會阻塞執行緒
        // 此處不使用執行緒池的原因是這裡只需要一個執行緒,不存線上程的頻繁銷燬建立
        NettyServerThread nettyServerThread = new NettyServerThread();
        Thread thread1 = new Thread(nettyServerThread);
        thread1.start();

        // 如果設定wss埠的話,則啟動wss處理伺服器
        if(StringUtil.isNotEmpty(BaseGlobal.getWssPort())) {
            NettyWssServerThread sslServerThread = new NettyWssServerThread();
            Thread thread2 = new Thread(sslServerThread);
            thread2.start();
        }
    }
}

 

4. 因為我們需要在程式動態判斷WS還是WSS,所以在nginx的proxy配置了,這樣後臺就可以識別客戶端是https還是http

proxy_set_header scheme  $scheme;

 

參考:https://www.cnblogs.com/qingyibusi/p/8572783.html

相關文章