如何编写用于连接OAuth 2.0安全Spring WebSocket API的JavaScript客户端?
我需要使用spring创建一个Websocket服务器,这可以通过使用下面的代码轻松完成如何编写用于连接OAuth 2.0安全Spring WebSocket API的JavaScript客户端?,javascript,spring-boot,websocket,oauth-2.0,spring-websocket,Javascript,Spring Boot,Websocket,Oauth 2.0,Spring Websocket,我需要使用spring创建一个Websocket服务器,这可以通过使用下面的代码轻松完成 @Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(new SocketHandler(), "/poll");
registry.addHandler(new SocketPushHandler(), "/push");
}
}
其中,SocketHandler和SocketPushHandler是websocket端点的处理程序类
在这一切正常之前,我们能够运行服务器并使用普通的socket=newwebsocket(websocketUrl)
javascript代码连接到端点
现在我们需要在API端点上实现OAuth 2.0安全性,这可以通过导入一些Spring安全依赖项轻松实现\
现在,最困难的部分是编写客户端来连接安全端点,方法是将OauthAuthorization beaer
作为头的一部分传递。
从文档中我们知道,我们不能向Web套接字端点发送头
因此,根据此链接中的信息,我创建了一个API网关/open ws Request type GET
,客户端将连接到该网关并向其发送授权头,服务器端内部的该端点将打开一个WebSocket客户端连接,将头传递为javax.WebSocket.WebSocketContainer
支持带有自定义标题的websocket客户端
现在,我的javascript首先对网关端点进行GET ajax调用,并在成功时发出新的websocket请求
下面是模拟网关的SpringAPI
@RequestMapping(value = "/open-ws", method = RequestMethod.GET)
public void getOperatorTokenDefinition(@RequestHeader(value = HttpHeaders.AUTHORIZATION) String bearerToken,
@RequestHeader(value = "websocketURL") String websocketURL,
HttpServletRequest acquireTokenServletRequest, HttpServletResponse response) {
webSocketClient.connecttoserver(websocketURL, acquireTokenServletRequest.getRemoteHost(), bearerToken, response);
// ResponseEntity<String> responseEntity = new ResponseEntity<>("connected", HttpStatus.OK);
}
因此,问题是这是连接Oauth 2.0 Websocket的正确方法,如果是,如何处理上述错误,如果否,如何将头发送到授权端点。
注意:不使用Stomp,因为我们还没有确认实际的客户端(即UI)是否允许/拥有Stomp JS
@Component
public class WebSocketClient {
private Session client;
public void connecttoserver(String websocketURL,String host,String bearerAccessToken, HttpServletResponse response) {
final AtomicReference<String> message = new AtomicReference<>();
Endpoint endpoint = new Endpoint() {
@Override
public void onOpen(Session session, EndpointConfig config) {
System.out.println("WSS OPEN!!!!!");
try (OutputStream output = response.getOutputStream()) {
output.write(session.getId());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
ClientEndpointConfig.Configurator configurator = new ClientEndpointConfig.Configurator() {
@Override
public void beforeRequest(Map<String, List<String>> headers) {
List<String> connection = new ArrayList<>(1);
connection.add("Upgrade");
List<String> origin = new ArrayList<>(1);
origin.add(originURL);
List<String> upgradeWebsocket = new ArrayList<>(1);
upgradeWebsocket.add("WebSocket");
List<String> host = new ArrayList<>(1);
host.add(websocketURL);
List<String> contenttype = new ArrayList<>(1);
contenttype.add("application/json");
List<String> authorization = new ArrayList<>(1);
authorization.add("Bearer " + bearerAccessToken);
List<String> tenantId = new ArrayList<>(1);
tenantId.add(tenantID);
List<String> key = new ArrayList<>(1);
key.add("HcFOxrSD89ya65X2qMF9lQ==");
List<String> version = new ArrayList<>(1);
version.add("13");
headers.put("Connection", connection);
headers.put("Upgrade", upgradeWebsocket);
headers.put("Host", host);
headers.put("Origin", origin);
// headers.put("Content-Type", contenttype);
headers.put("Authorization", authorization);
headers.put("Sec-WebSocket-Key", key);
headers.put("Sec-WebSocket-Version", version);
}
};
ClientEndpointConfig clientConfig = ClientEndpointConfig.Builder.create().configurator(configurator).build();
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
try {
// if (!this.client.isOpen())
this.client = container.connectToServer(endpoint, clientConfig, URI.create(websocketURL));
client.addMessageHandler(new MessageHandler.Whole<String>() {
@Override
public void onMessage(String response) {
// TODO Auto-generated method stub
message.set(response);
// System.out.println("response>>>>>>>>>>>>>>>>>>> "+response.toString());// this dosent work
}
});
System.out.println("Response--------------------------------->" + message.get());
// client.close();
} catch (DeploymentException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
$(document).ready(function(){
$("#Websocketconnect").click(function(){
$.ajax({
type: 'GET',
url: hostUrl.value,
headers: {
"Authorization":websocketToken.value,
"websocketURL":websocketUrl.value,
"Content-type":"text/plain"
},
success: function(result){
$("#readystatus").value = result;
webSocketCycleEvent(websocketUrl.value);
}});
});
});
function webSocketCycleEvent(websocketUrl){
socket = new WebSocket(websocketUrl);
socket.onerror = function(error) {
console.log('WebSocket Error: ' + error);
};
// Show a connected message when the WebSocket is opened.
socket.onopen = function(event) {
socketStatus.innerHTML = 'Connected to: ' + websocketUrl;
socketStatus.className = 'open';
};
socket.onmessage = function(event) {
var message = event.data;
messagesList.innerHTML += '<li class="received"><span>Received:</span>' +
message + '</li>';
};
socket.onclose = function(event) {
socketStatus.innerHTML = 'Disconnected from WebSocket.';
socketStatus.className = 'closed';
};
}
form.onsubmit = function(e) {
e.preventDefault();
// Retrieve the message from the textarea.
var message = messageField.value;
socket.send(message);
messagesList.innerHTML += '<li class="sent"><span>Sent:</span>' + message +
'</li>';
// Clear out the message field.
messageField.value = '';
return false;
};
javax.websocket.DeploymentException: The HTTP response from the server [400] did not permit the HTTP upgrade to WebSocket
at org.apache.tomcat.websocket.WsWebSocketContainer.connectToServer(WsWebSocketContainer.java:343)
at com.example.simplewebsocketserver.WebSocketClient.connecttoserver(WebSocketClient.java:101)
at com.example.simplewebsocketserver.WebSocketController.getOperatorTokenDefinition(WebSocketController.java:31)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)