Отправить пользовательское сообщение с весны - PullRequest
0 голосов
/ 18 ноября 2018

У меня есть конечная точка (/ create), которая имеет некоторую логику, и обработка занимает 3-4 минуты, поэтому я использовал rabbitmq, и как только конечная точка получает запрос, он принимает тело и отправляет сообщение в rabbitmq, слушателяпрослушивает сообщение и обрабатывает запрос. Теперь я хочу уведомить пользователя о том, что его запрос успешно обработан.

  • Правильно ли выбран веб-сокет для этого требования
  • Есть ли другой способ лучшечто я могу достичь своей цели?

Итак, я продолжил работу с websocket, так как я использую аутентификацию на основе oauth. Я не могу заставить работать web-сокет

Вот мой код, который у меня естьзаписано:

SocketConfig.java

@Configuration
@EnableWebSocketMessageBroker
public class SocketConfig implements WebSocketMessageBrokerConfigurer {

  @Override
  public void configureMessageBroker(MessageBrokerRegistry config) {
    config.enableSimpleBroker("/topic","/secured/queue");
    //config.setApplicationDestinationPrefixes("/app");
    //config.setUserDestinationPrefix("/secured/user");
  }

  @Override
  public void registerStompEndpoints(StompEndpointRegistry registry) {
    registry.addEndpoint("/secured/messagereg").setAllowedOrigins("*").withSockJS();
  }

SocketHandler.java

@Configuration
public class SocketHandler extends AbstractSecurityWebSocketMessageBrokerConfigurer {

  @Override
  protected boolean sameOriginDisabled() {
    return true;
  }

  @Override
  protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
    messages
        .simpDestMatchers("/secured/**", "/secured/**/**").authenticated()
        .anyMessage().authenticated();
  }
}

WebSecurityConfig.java

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Profile("!test")
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

  @Autowired
  private Auth0PropertyConfig config;

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    JwtWebSecurityConfigurer
        .forRS256(config.getAudience(), config.getIssuer())
        .configure(http)
        .cors()
        .and()
        .csrf().disable()
        .authorizeRequests()
        .anyRequest().authenticated()
        .and()
        .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
    ;
  }
}

clientCode

 const socket = new SockJs("/secured/messagereg/?access_token="+token);
    this.setState({ clientRef: Stomp.over(socket) }, () =>
      this.state.clientRef.connect({},
        frame => {
          this.setState({ connection: true });
          this.state.clientRef.subscribe("/user/secured/queue/reply", message => {
            console.log("asd received ----------" + message.body);
            this.setState(prevs => ({
              message: [...prevs.message, message]
            }));
          });
        },
        error => {
          console.log("Stomp protocol error." + error);
        }
      )
    );

Я получаю 401 несанкционированный при подключении к сокету.

1 Ответ

0 голосов
/ 19 ноября 2018

По моему мнению: шаблон push-сообщений (например, с использованием STOMP) подходит для этого сценария, но в конечном итоге это зависит от ваших архитектурных принципов. Вы также можете запросить у сервера результат (используя REST API), который имеет как преимущества (общая архитектура безопасности), так и недостатки (код клиента, трафик и накладные расходы времени реакции).

Ответ:

Чтобы заставить ваш код работать, я думаю, вам нужен еще один метод в вашем SocketConfig.java, который будет подключаться к вашему OAUTH-фильтру (или любому другому методу, который у вас может быть).

Важно - Аутентификация websocket не использует существующий контекст Spring Security . Вот почему вам нужно снова реализовать auth, например, в классе SocketConfig, используя метод WebSocketMessageBrokerConfigurer configureClientInboundChannel.

В следующем примере предполагается, что вы уже получили токен OAUTH ранее, и он используется только для повторной аутентификации соединения через веб-сокет. Установка ссылки на пользователя в StompHeaderAccessor (3-я последняя строка) позволит вашему коду отправить сообщение нужному пользователю.

Также требуется, чтобы в заголовке сообщения был установлен токен OAUTH, в отличие от параметра конечной точки в вашем примере. Я думаю, что это может быть безопаснее для обмена сообщениями через веб-носки, так как само сообщение шифруется на уровне протокола, если вы используете wss .

@Autowired
private YourOauthService auth;

@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
    registration.interceptors(new ChannelInterceptor() {
        @Override
        public Message<?> preSend(Message<?> message, MessageChannel channel) {
            StompHeaderAccessor accessor =
                    MessageHeaderAccessor.getAccessor(message,
                           StompHeaderAccessor.class);
            if (StompCommand.CONNECT.equals(accessor.getCommand())) {
                String token = accessor.removeNativeHeader("Authorization").get(0);
                Authentication user = auth.getAuthentication(token);

                accessor.setUser(user);
            }
            return message;
        }
    });
}

Я нашел еще несколько интересных примеров в https://robertleggett.wordpress.com/2015/05/27/websockets-with-spring-spring-security/

...