QtJava笔记-Qt与Java进行SSL双向认证(Qt服务端,Java客户端)
生活随笔
收集整理的這篇文章主要介紹了
QtJava笔记-Qt与Java进行SSL双向认证(Qt服务端,Java客户端)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
程序運(yùn)行截圖如下:
Qt作為服務(wù)端,Java作為客戶端。
這里的服務(wù)端是用的p12證書,客戶端使用的是jks。
具體的生成方式看以前的博文。
QSSLServer.h
#ifndef QSSLSERVER_H #define QSSLSERVER_H#include <QObject> #include <QList> #include <QTcpServer> #include <QSslError>QT_BEGIN_NAMESPACE class QSslCertificate; class QSslKey; class QSslSocket; QT_END_NAMESPACEclass QSSLServer : public QTcpServer {Q_OBJECT public:QSSLServer(QObject *parent = nullptr);~QSSLServer();protected:void loadCertificate();void incomingConnection(qintptr socketDescriptor) Q_DECL_OVERRIDE;private slots:void sslErrors(const QList<QSslError> &errors);void link();void rx();void disconnected();private:QList<QSslCertificate> m_publicCertificateList;QSslCertificate *m_privateCertificate;QSslKey *m_key;QSslSocket *m_client; };#endif // QSSLSERVER_HQSSLServer.cpp
#include "QSSLServer.h" #include <QSslSocket> #include <QJsonDocument> #include <QSslCertificate> #include <QMap> #include <QFile> #include <QSslKey> #include <QDebug>QSSLServer::QSSLServer(QObject *parent) : QTcpServer(parent) {m_key = new QSslKey;m_privateCertificate = new QSslCertificate;loadCertificate();if(!this->listen(QHostAddress::Any, 19999)){qCritical() << "Unable to start the TCP server";exit(0);}connect(this, &QSSLServer::newConnection, this, &QSSLServer::link);qDebug() << "The SSLServer started succeefully";qDebug() << "port: 19999"; }QSSLServer::~QSSLServer() {delete m_privateCertificate;delete m_key; }void QSSLServer::loadCertificate() {QFile p12File(":/res/p_server.p12");if(!p12File.open(QIODevice::ReadOnly)){qDebug() << "The certificate file open failed!";exit(0);}bool ok = QSslCertificate::importPkcs12(&p12File, m_key, m_privateCertificate, &m_publicCertificateList, "cccccc");if(!ok){qDebug() << "The certificate import error!";exit(0);}p12File.close(); }void QSSLServer::incomingConnection(qintptr socketDescriptor) {QSslSocket *sslSocket = new QSslSocket(this);connect(sslSocket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(sslErrors(QList<QSslError>)));sslSocket->setSocketDescriptor(socketDescriptor);sslSocket->setPrivateKey(*m_key);sslSocket->setLocalCertificate(*m_privateCertificate);sslSocket->addCaCertificates(m_publicCertificateList);sslSocket->setPeerVerifyMode(QSslSocket::VerifyPeer);sslSocket->startServerEncryption();addPendingConnection(sslSocket); }void QSSLServer::sslErrors(const QList<QSslError> &errors) {foreach(const QSslError &error, errors)qDebug() << error.errorString(); }void QSSLServer::link() {QTcpSocket *clientSocket;clientSocket = nextPendingConnection();connect(clientSocket, &QTcpSocket::readyRead, this, &QSSLServer::rx);connect(clientSocket, &QTcpSocket::disconnected, this, &QSSLServer::disconnected); }void QSSLServer::rx() {QTcpSocket* clientSocket = qobject_cast<QTcpSocket*>(sender());QString clientString = clientSocket->readAll();qDebug() << "client:" << clientString;//再發(fā)一條數(shù)據(jù)clientSocket->write("Hello Client"); }void QSSLServer::disconnected() {qDebug("Client Disconnected");QTcpSocket* clientSocket = qobject_cast<QTcpSocket*>(sender());clientSocket->deleteLater(); }main.cpp
#include <QCoreApplication> #include "QSSLServer.h"int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);QSSLServer sslServer;return a.exec(); }Java客戶端:
SslClient.java
package cn.it1995;import javax.net.ssl.KeyManager; import javax.net.ssl.SSLSocket; import javax.net.ssl.TrustManager; import java.io.InputStream; import java.io.OutputStream;public class SslClient implements SslContextProvider{public static void main(String[] args) throws Exception {new SslClient().run("127.0.0.1", 19999);}public TrustManager[] getTrustManagers() throws Exception {return SslUtil.createTrustManagers("D:\\IDEAProject\\SSLDemo\\src\\main\\resources\\client.jks", "cccccc");}public KeyManager[] getKeyManagers() throws Exception {return SslUtil.createKeyManagers("D:\\IDEAProject\\SSLDemo\\src\\main\\resources\\client.jks", "cccccc");}public String getProtocol() {return "TLSv1.2";}private SSLSocket createSSLSocket(String host, Integer port) throws Exception{return SslUtil.createSSLSocket(host, port, this);}public void run(String host, Integer port) throws Exception {try(SSLSocket sslSocket = createSSLSocket(host, port); OutputStream os = sslSocket.getOutputStream(); InputStream is = sslSocket.getInputStream()){System.out.println("已成功連接到服務(wù)端.......");os.write("Hello Server".getBytes());os.flush();System.out.println("已發(fā)送 Hello Server 到服務(wù)端");byte[] buf = new byte[1024];is.read(buf);System.out.println("接收到服務(wù)端消息:" + new String(buf));}catch (Exception e){e.printStackTrace();}} }SslContextProvider.java
package cn.it1995;import javax.net.ssl.KeyManager; import javax.net.ssl.TrustManager;public interface SslContextProvider {TrustManager[] getTrustManagers() throws Exception;KeyManager[] getKeyManagers() throws Exception;String getProtocol(); }SslUtil.java
package cn.it1995;import javax.naming.ldap.LdapName; import javax.naming.ldap.Rdn; import javax.net.ssl.*; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.net.Socket; import java.security.*; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException;public class SslUtil {private static final String JKS = "JKS";public static KeyManager[] createKeyManagers(String keyStorePath, String password) throws Exception {return createKeyManagers(keyStorePath, password, password);}public static KeyManager[] createKeyManagers(String keyStorePath, String storePassword, String keyPassword) throws Exception {String defaultAlgorithm = KeyManagerFactory.getDefaultAlgorithm();KeyManagerFactory kmInstance = KeyManagerFactory.getInstance(defaultAlgorithm);KeyStore ksInstance = KeyStore.getInstance(JKS);FileInputStream fileInputStream = new FileInputStream(keyStorePath);try{ksInstance.load(fileInputStream, storePassword.toCharArray());}catch (IOException e){e.printStackTrace();}catch (CertificateException e){e.printStackTrace();}finally {if(fileInputStream != null){fileInputStream.close();}}try{kmInstance.init(ksInstance, keyPassword.toCharArray());}catch (UnrecoverableKeyException e){e.printStackTrace();}return kmInstance.getKeyManagers();}public static SSLContext createSSLContext(SslContextProvider provider) throws Exception{SSLContext context = SSLContext.getInstance(provider.getProtocol());context.init(provider.getKeyManagers(), provider.getTrustManagers(), new SecureRandom());return context;}public static SSLServerSocket createSSLServerSocket(int port, SslContextProvider provider) throws Exception{SSLContext sslContext = createSSLContext(provider);SSLServerSocketFactory sslServerSocketFactory = sslContext.getServerSocketFactory();SSLServerSocket sslServerSocket = (SSLServerSocket)sslServerSocketFactory.createServerSocket(port);sslServerSocket.setEnabledProtocols(new String[]{provider.getProtocol()});sslServerSocket.setNeedClientAuth(true);return sslServerSocket;}public static SSLSocket createSSLSocket(String host, int port, SslContextProvider provider) throws Exception{SSLContext sslContext = createSSLContext(provider);SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();SSLSocket sslSocket = (SSLSocket)sslSocketFactory.createSocket(host, port);sslSocket.setEnabledProtocols(new String[]{provider.getProtocol()});return sslSocket;}public static TrustManager[] createTrustManagers(String keyStorePath, String password) throws Exception{String defaultAlgorithm = TrustManagerFactory.getDefaultAlgorithm();TrustManagerFactory tmInstance = TrustManagerFactory.getInstance(defaultAlgorithm);KeyStore ksInstance = KeyStore.getInstance(JKS);FileInputStream fileInputStream = new FileInputStream(keyStorePath);try{ksInstance.load(fileInputStream, password.toCharArray());}catch (IOException e){e.printStackTrace();}catch (CertificateException e){e.printStackTrace();}finally {if(fileInputStream != null){fileInputStream.close();}}tmInstance.init(ksInstance);return tmInstance.getTrustManagers();}public static String getPeerIdentity(Socket socket){if(!(socket instanceof SSLSocket)){return null;}SSLSession sslSession = ((SSLSocket)socket).getSession();try{Principal peerPrincipal = sslSession.getPeerPrincipal();return getCommonName(peerPrincipal);}catch (SSLPeerUnverifiedException e){e.printStackTrace();}return "unknown client";}private static String getCommonName(Principal subject){try{LdapName ldapName = new LdapName(subject.getName());for(Rdn rdn : ldapName.getRdns()){if("cn".equalsIgnoreCase(rdn.getType())){return (String)rdn.getValue();}}}catch (Exception e){e.printStackTrace();}return null;} }這里的雙向認(rèn)證的關(guān)鍵:
Qt:
Java:
源碼打包下載地址:
https://github.com/fengfanchen/Java/tree/master/Ssl_QtServer_JavaClient
總結(jié)
以上是生活随笔為你收集整理的QtJava笔记-Qt与Java进行SSL双向认证(Qt服务端,Java客户端)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android笔记-使用okhttp3库
- 下一篇: MySQL笔记-Slave_IO_Run