Spring Security + Angular 2 + SockJS

时间:2016-11-02 19:43:37

标签: spring angular spring-security sockjs

抱歉我的语言很糟糕。我是德国学生和编程新人。

我已经使用Spring Boot实现了一个带有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','传递',功能(框架){...}

感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

我还没与SockJS合作过。但我已经为纯WebSocket实现了一些小机制。也许它会有所帮助

首先,OAUTH配置:

<div>
<ul class="uib-datepicker-popup dropdown-menu" dropdown-nested ng-if="isOpen" style="display: block" ng-style="{top: position.top+'px', left: position.left+'px'}" ng-keydown="keydown($event)" ng-click="$event.stopPropagation()">
  <!-- regular price button -->
  <button type="button" class="btn btn-sm btn-warning" ng-click="$parent.$parent.regularPrice()">Regular Price</button>
  <!-- /regular price button-->

  <li ng-transclude></li>
  <li ng-if="showButtonBar" style="padding:10px 9px 2px" class="uib-button-bar">
    <span class="btn-group pull-left">
        <button type="button" class="btn btn-sm btn-info uib-datepicker-current" ng-click="select('today')" ng-disabled="isDisabled('today')">{{ getText('current') }}</button>
        <button type="button" class="btn btn-sm btn-danger uib-clear" ng-click="select(null)">{{ getText('clear') }}</button>
    </span>
    <button type="button" class="btn btn-sm btn-success pull-right uib-close" ng-click="close($event)">{{ getText('close') }}</button>
  </li>
</ul>
</div>

第二,angular2授权:

@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")
            );
        };
    }
}

第三个套接字配置:

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
        }
    );

最后,通过angular2建立连接:

@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
        }
    }
}

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