Spring 安全 + Angular 2 + SockJS

Spring Security + Angular 2 + SockJS

对不起,一开始我的语言不好。我是一名来自德国的学生,刚开始编程。

我已经使用 Spring Boot 实现了一个小型 websocket 服务器,并使用 Basic Auth 通过 Spring Security 对其进行了保护。 Angular 2 用于前端。我已经实现了以下解决方案来连接到 websocket。

 * Connects to a websocket server.
 * @param  {string} url     The url of the WS Server
 * @param  {string} channel The channel to subscribe
 * @return {boolean} connection status
 */
public connect(url: string, channel: string): boolean {
    console.group('WebSocketService: Welcome to the connect function.');
    console.log('Connects to', url);
    console.log('Channel is', channel);
    let _self = this;
    let socket = new SockJS(url);
    _self.wsClient = Stomp.over(socket);

    _self.wsClient.connect({}, function(frame) {
        _self.setConnected(true);
        console.log('Connected: ', frame);
        _self.wsClient.subscribe(channel, function(greeting) {
            console.log(greeting);
            _self.subjects[channel].next(greeting);
        });
    });
    console.groupEnd();
    return true;
}

调用此函数让浏览器打开用户名和密码输入。 现在我可以连接和断开与服务器的连接,无需再次输入用户名/密码。

如何使用代码中的登录信息替换此浏览器输入 window?

我试图通过一个 Post 请求来做到这一点,例如:

private test2(){
  let username : string = 'admin';
  let password : string = 'pass';
  let headers = new Headers();
  headers.append("Authorization", "Basic " + btoa(username + ":" + password));
  headers.append("Content-Type", "application/x-www-form-urlencoded");
  console.log('Test beginnt');
  return this._http.get('http://localhost:8080/gs-guide-websocket', {headers: headers}).map(res=> console.log(res))
}

Blockquote

但这只给我一个 http 200 响应,并没有打开会话或其他东西。

我也试过将登录信息放在原始请求中。

_self.wsClient.connect('admin','pass', function(frame) { ...}

感谢您的帮助。

我没有使用过 SockJS。但是我已经为纯 WebSocket 实现了一些小机制。也许会有帮助

首先,OAUTH配置:

@Configuration
@EnableAuthorizationServer
@EnableResourceServer
public class OAuth2Configuration extends AuthorizationServerConfigurerAdapter {

    private static Logger logger = LoggerFactory.getLogger(OAuth2Configuration.class);
    private UsersService service = new UsersService();

    @Autowired
    AuthenticationManagerBuilder authenticationManager;

    @Autowired
    UserDetailsService userDetailsService;


    @Override
    public void configure( AuthorizationServerEndpointsConfigurer endpoints) throws Exception {

        authenticationManager.userDetailsService(this.userDetailsService);
        endpoints.authenticationManager((Authentication authentication) ->  authenticationManager.getOrBuild().authenticate(authentication));
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory().withClient("application_name")
                .authorizedGrantTypes("password", "authorization_code", "refresh_token")
                .scopes("write", "read", "trust")
                .secret("secret").accessTokenValiditySeconds(24 * 60 * 60);
    }

    @Bean
    public UserDetailsService userDetailsService() {
        return (username) -> {
            return service.getByName(username).map(account -> new User(account.getName(), account.getPassword(), account.getAuthorities())).orElseThrow(
                    () -> new RuntimeException("User not found")
            );
        };
    }
}

第二,angular2授权:

let headers = new Headers();
headers.append("Authorization", "Basic appname:secret");
this.http.post("localhost:8080/oauth_endpoint?grant_type=password&scope=trust&username=" + login + "&password=" + password , "", { headers: headers })
      .map((response: Response) => response.json())
      .subscribe(response => {
          this.accessToken = response.access_token; //will be used for socket
        }
    );

第三套接字配置:

@Configuration
@EnableWebSocket
public class SocketConfig implements WebSocketConfigurer {

    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(socketHandler(), "/websocket").setAllowedOrigins("*");
    }

    @Bean
    public SocketHandler socketHandler() {
        return new SocketHandler();
    }
}

public class SocketHandler extends TextWebSocketHandler {

    @Autowired
    private CheckTokenEndpoint checkTokenEndpoint;

    private static Logger logger = LoggerFactory.getLogger(SocketHandler.class);


    public void afterConnectionEstablished(WebSocketSession session) {
        logger.info("New peer connected: " + session.getId());
    }

    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
        logger.debug("Peer is trying to authenticate");
        String token = message.getPayload().toString();
        try {
            checkTokenEndpoint.checkToken(token);
            logger.info("New peer authenticated. ");
        } catch (Exception e) {
            logger.warn("Peer unauthenticated!");
            session.close(); //closing connection when provided token doesn't match
        }
    }
}

最后,通过angular2建立连接:

let ws = new WebSocket("localhost:8080/websocket", []);
ws.onopen = (event: Event) => {
      this.send(
          ws.send()

      });

如果您只是 copy/paste,此代码可能无法正常工作。我还有其他几个案例要处理(即我的 websocket 正在重新建立连接)。因为它们不在问题范围内,所以我在此处放置代码时手动删除了它们。