Spring + Oauth2 + JWT+ Websocket

Posted

技术标签:

【中文标题】Spring + Oauth2 + JWT+ Websocket【英文标题】: 【发布时间】:2018-01-15 04:17:39 【问题描述】:

我正在做一个关于 spring boot + oauth2 + websocket 的例子。我在 8098 端口上运行的资源服务器上有 spring websocket 配置和其他代码。我试图从在 8080 端口上运行的客户端应用程序连接它。但是当我运行我的应用程序时,我在浏览器控制台上收到错误 401(未经授权)。我正在分享我的一些代码:

1) 客户端应用程序(在 8080 端口上运行)获取 websocket 连接的 javascript 代码

'use strict';

// pull in the SockJS JavaScript library for talking over WebSockets.
var SockJS = require('sockjs-client');
// pull in the stomp-websocket JavaScript library to use the STOMP sub-protocol.
require('stompjs');

function register(registrations) 
    const access_token = localStorage.getItem("ACCESS_TOKEN");
    console.log("Access Token " + access_token);
    const csrf_token = localStorage.getItem("XSRF");
    // Here is where the WebSocket is pointed at the server application’s /messages endpoint
    // websocket use this URL to open TCP connection
    var socket = SockJS('http://localhost:8098/notifications');
    var stompClient = Stomp.over(socket);

    var headers = 
        'X-Csrf-Token': csrf_token,
        Authorization: 'Bearer ' + access_token
    

    // connect to server using stompClient
    stompClient.connect(headers, function(frame) 
        // Iterate over the array of registrations supplied so each can subscribe for callback as messages arrive.
        stompClient.send("/app/notifications", );
        registrations.forEach(function (registration) 
            stompClient.subscribe(registration.route, registration.callback);
        );
    );



module.exports = 
    register: register
;

2) 资源服务器(在 8098 端口上运行)代码,我有服务器端 websocket 配置

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfiguration extends AbstractSecurityWebSocketMessageBrokerConfigurer 

    // This prefix we will append to every message's route.
    static final String MESSAGE_PREFIX = "/topic"
    static final String END_POINT = "/notifications"
    static final String APPLICATION_DESTINATION_PREFIX = "/app"

    @Override
    protected boolean sameOriginDisabled() 
        return true;
    

    /**
     * This method configure the end-point on the backend for clients and server to link ('/notifications').
     */
    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) 

         // This code register the '/notifications' end-point. The SockJS client will attempt to connect to '/notifications' end-point
        if(registry != null) 
            registry.addEndpoint(END_POINT).setAllowedOrigins("*").withSockJS()
        

    

    /**
     * This method configure the message broker used to relay messages between server and client.
     */
    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) 

        if(registry != null) 
            // Enable a broker to send messages to the client on destinations prefixed with '/topic'
            registry.enableSimpleBroker(MESSAGE_PREFIX);
            // prefix for messages that are bound for @MessageMapping annotated methods. This prefix will be used to define all message mappings
            registry.setApplicationDestinationPrefixes(APPLICATION_DESTINATION_PREFIX)
        
    

请提出一些解决方案。

【问题讨论】:

你有这个例子的链接吗? 【参考方案1】:

最后我解决了这个问题。问题是以前我使用 jwt_token 和前缀“bearer”以解码形式发送访问令牌。

所以我做了一些调试,我知道令牌应该以其实际形式发送而不是解码。

    之前我在客户端从这样的响应中提取访问令牌:

let decoded = jwt_decode(response.entity.details.tokenValue); localStorage.setItem("ACCESS_TOKEN", decoded.jti);

这是不正确的。所以我用下面的代码改变了它:

localStorage.setItem("ACCESS_TOKEN", response.entity.details.tokenValue);

    在 websocket-listener js 文件中我做了以下更改
const access_token = localStorage.getItem("ACCESS_TOKEN");

var socket = SockJS('http://localhost:8098/notifications/?access_token='+access_token);

看到我在不带前缀'bearer'的url查询参数中发送访问令牌。

它奏效了。

【讨论】:

以上是关于Spring + Oauth2 + JWT+ Websocket的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Spring OAuth2 JWT 令牌?

创建隐式JWT时的Spring Boot OAuth2?

Oauth2 + jwt 和 spring boot

Spring Security OAuth2 Jwt 访问被拒绝

Spring Boot Security OAuth2 实现支持JWT令牌的授权服务器

Spring + Oauth2 + JWT+ Websocket