【问题标题】:Spring Security + Angular 2 + SockJSSpring Security + Angular 2 + SockJS
【发布时间】:2016-11-02 19:43:37
【问题描述】:

一开始我很抱歉我的语言不好。我是一名来自德国的学生,刚接触编程。

我已经使用 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;
}

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

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

我尝试通过一个 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))
}

块引用

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

我也尝试将登录信息放入原始请求中。

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

感谢您的帮助。

【问题讨论】:

    标签: spring angular spring-security sockjs


    【解决方案1】:

    我没有使用 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
            }
        );
    

    第三个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()
    
          });
    

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

    【讨论】:

    • 这基本上是我一直在寻找的。您能否详细说明CheckTokenEndpoint?在 Authorization 头中发送令牌是否足够,并且它会被 Spring Security 自动拾取吗?
    猜你喜欢
    • 2017-09-07
    • 2015-12-05
    • 1970-01-01
    • 2017-02-14
    • 2017-08-23
    • 2016-12-20
    • 2018-03-06
    • 2019-02-18
    • 2017-10-04
    相关资源
    最近更新 更多