gpt4 book ai didi

java - WebSocket 服务器在打开时获取客户端证书

转载 作者:太空宇宙 更新时间:2023-11-03 13:22:29 24 4
gpt4 key购买 nike

我有一个在 WildFly 10 上运行的简单 ServerEndpoint,它配置为具有双向 TLS 的 wss,因此需要客户端证书。我在连接到端点时没有问题,因此相互身份验证已正确完成,但我无法在 onOpen 方法中访问客户端证书。我正在尝试使用 getUserPrincipal() 来做到这一点,但我总是得到 null

我需要获取客户端证书以进行授权。

import java.io.IOException;
import java.security.Principal;

import javax.servlet.http.HttpSession;
import javax.websocket.EndpointConfig;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint(value = "/test", configurator = GetHttpSessionConfigurator.class)
public class TestWebSocketEndPoint {

private Session wsSession;
private HttpSession httpSession;

@OnOpen
public void onOpen(Session session, EndpointConfig config){
this.wsSession = session;
this.httpSession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName());
Principal userPrincipal = session.getUserPrincipal();
System.out.println(session.getId() + " has opened a connection");
try {
session.getBasicRemote().sendText("Connection Established");
} catch (IOException ex) {
ex.printStackTrace();
}
}

/**
* When a user sends a message to the server, this method will intercept the message
* and allow us to react to it. For now the message is read as a String.
*/
@OnMessage
public void onMessage(String message, Session session){
System.out.println("Message from " + session.getId() + ": " + message);
try {
session.getBasicRemote().sendText(message);
} catch (IOException ex) {
ex.printStackTrace();
}
}

/**
* The user closes the connection.
*
* Note: you can't send messages to the client from this method
*/
@OnClose
public void onClose(Session session){
System.out.println("Session " +session.getId()+" has ended");
}
}

GetHttpSessionConfigurator:

import java.security.Principal;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpSession;
import javax.websocket.HandshakeResponse;
import javax.websocket.server.HandshakeRequest;
import javax.websocket.server.ServerEndpointConfig;

public class GetHttpSessionConfigurator extends ServerEndpointConfig.Configurator {
@Override
public void modifyHandshake(ServerEndpointConfig config,
HandshakeRequest request,
HandshakeResponse response)
{
HttpSession httpSession = (HttpSession)request.getHttpSession();
Map<String, List<String>> map = request.getParameterMap();
Principal principal = request.getUserPrincipal();
config.getUserProperties().put(HttpSession.class.getName(),httpSession);
}
}

请求监听器:

import java.security.Principal;
import java.security.cert.X509Certificate;

import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpServletRequest;

@WebListener
public class RequestListener implements ServletRequestListener {

public void requestDestroyed(ServletRequestEvent sre) {
// TODO Auto-generated method stub

}

public void requestInitialized(ServletRequestEvent sre) {
((HttpServletRequest) sre.getServletRequest()).getSession();
Principal p = ((HttpServletRequest) sre.getServletRequest()).getUserPrincipal();

boolean secure = ((HttpServletRequest) sre.getServletRequest()).isSecure();
String authType = ((HttpServletRequest) sre.getServletRequest()).getAuthType();

X509Certificate[] certs = (X509Certificate[]) ((HttpServletRequest) sre.getServletRequest()).getAttribute("javax.servlet.request.X509Certificate");
}

}

websocket 客户端是一个使用 TooTallNate/java-websocket 并安全连接的独立应用程序:

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.util.Enumeration;

import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.java_websocket.WebSocketImpl;

public class TestClient {

private static final Log log = LogFactory.getLog(TestClient.class);

public static void main(String[] args) throws URISyntaxException {
WebSocketImpl.DEBUG = true;

WSRAClient wsRaClient = new WSRAClient(new URI("wss://localhost:8443/TestWebSocket-0.0.1-SNAPSHOT/test"));

String keystoreFile = "keystore.p12";
String keystorePassword = "keystore";

String truststoreFile = "truststore.jks";
String truststorePassword = "truststore";


try {
SSLContext ssl = SSLContext.getInstance("TLSv1.2");

log.info("Configuring SSL keystore");
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
KeyStore store = KeyStore.getInstance(KeyStore.getDefaultType());
log.debug("Loading keystore");
store.load(new FileInputStream(keystoreFile), keystorePassword.toCharArray());
log.debug("Number of keystore certificates: " + store.size());
Enumeration<String> enumeration = store.aliases();
while(enumeration.hasMoreElements()) {
String alias = enumeration.nextElement();
log.debug("alias name: " + alias);
Certificate certificate = store.getCertificate(alias);
log.debug(certificate.toString());
}
kmf.init(store, keystorePassword.toCharArray());
KeyManager[] keyManagers = new KeyManager[1];
keyManagers = kmf.getKeyManagers();

log.info("Configuring SSL truststore");
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
KeyStore truststore = KeyStore.getInstance(KeyStore.getDefaultType());
log.debug("Loading truststore");
truststore.load(new FileInputStream(truststoreFile), truststorePassword.toCharArray());
log.debug("Number of truststore certificates: " + truststore.size());
enumeration = truststore.aliases();
while(enumeration.hasMoreElements()) {
String alias = (String)enumeration.nextElement();
log.debug("alias name: " + alias);
Certificate certificate = truststore.getCertificate(alias);
log.debug(certificate.toString());
}
tmf.init(truststore);
TrustManager[] trustManagers = tmf.getTrustManagers();

ssl.init(keyManagers, trustManagers, new SecureRandom());

SSLSocketFactory factory = ssl.getSocketFactory();// (SSLSocketFactory) SSLSocketFactory.getDefault();

wsRaClient.setSocket(factory.createSocket());

wsRaClient.connectBlocking();

BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
while ( true ) {
String line = reader.readLine();
if(line.equals("close")) {
wsRaClient.close();
} else {
wsRaClient.send(line);
}
}

} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
log.error(e);
System.exit(0);
} catch (KeyStoreException e) {
e.printStackTrace();
log.error(e);
System.exit(0);
} catch (CertificateException e) {
e.printStackTrace();
log.error(e);
System.exit(0);
} catch (FileNotFoundException e) {
e.printStackTrace();
log.error(e);
System.exit(0);
} catch (IOException e) {
e.printStackTrace();
log.error(e);
System.exit(0);
} catch (UnrecoverableKeyException e) {
e.printStackTrace();
log.error(e);
System.exit(0);
} catch (KeyManagementException e) {
e.printStackTrace();
log.error(e);
System.exit(0);
} catch (InterruptedException e) {
e.printStackTrace();
log.error(e);
System.exit(0);
}

}

}

最佳答案

参见:Accessing HttpServletRequest properties within a WebSocket @ServerEndpoint

  1. Create servlet filter on URL pattern matching websocket handshake request.
  2. In filter, get request attribute of interest and put it in session before continuing chain.
  3. Finally get it from the session which is in turn just available via handshake request

关于java - WebSocket 服务器在打开时获取客户端证书,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45780224/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com