Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Java Новый топик    Ответить
 Spring Boot 2 + Spring Security + JWT + WebSocket + SockJS + STOMP Проблема Авторизации  [new]
Tsyklop
Member

Откуда: Украина
Сообщений: 1069
Юзал этот гайд.

Но вот столкнулся с тем что мне нужно получить юзера в контроллере. А получить его я могу из JWT токена. Если с REST приложением и JWT все понятно и сделано, то в сокетах я не понимаю как мне авторизовывать пользователя?

Код:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    private final TokenUtils tokenUtils;

    private static final String ENDPOINT = "/websocket";

    private static final String TOPIC_CHAT = "/secured/client";
    private static final String TOPIC_QUEUE = "/secured/queue";
    private static final String TOPIC_OPERATOR = "/secured/operator";

    public WebSocketConfig(TokenUtils tokenUtils) {
        this.tokenUtils = tokenUtils;
    }

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker(TOPIC_CHAT, TOPIC_QUEUE, TOPIC_OPERATOR);
        config.setApplicationDestinationPrefixes("/ws");
        config.setUserDestinationPrefix("/secured/user");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint(ENDPOINT)
                .setAllowedOrigins("*")
                .addInterceptors(new WebSocketHandshakeInterceptor()).withSockJS();
    }

    @Override
    public void configureClientInboundChannel(ChannelRegistration registration) {
        registration.interceptors(new ChannelInterceptor() {

            @Override
            public Message<?> preSend(Message<?> message,  MessageChannel channel) {

                StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);

                List<String> tokenList = accessor.getNativeHeader("Authorization");
                String token = null;

                if(tokenList == null || tokenList.size() < 1) {
                    return message;
                } else {
                    token = tokenList.get(0);
                    if(token == null) {
                        return message;
                    }
                }

                accessor.setUser(null);

                // not documented anywhere but necessary otherwise NPE in StompSubProtocolHandler!
                accessor.setLeaveMutable(true);
                return MessageBuilder.createMessage(message.getPayload(), accessor.getMessageHeaders());
            }

        });
    }

}


Конфиг секюрити для сокетов:

@Configuration
public class WebSocketSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {

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

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


SecurityConfig

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UnauthorizedEntryPoint unauthorizedEntryPoint;

    @Autowired
    private TokenAuthenticationProvider tokenAuthenticationProvider;

    private static final RequestMatcher PUBLIC_URLS = new OrRequestMatcher(
            new AntPathRequestMatcher("/"),
            new AntPathRequestMatcher("/index"),
            new AntPathRequestMatcher("/index.html"),
            new AntPathRequestMatcher("/resource/**"),
            new AntPathRequestMatcher("/favicon.ico"),
            new AntPathRequestMatcher("/actuator/**"),
            new AntPathRequestMatcher("/h2-console/**"),
            new AntPathRequestMatcher("/**/favicon.ico"),
            new AntPathRequestMatcher("/webjars/**"),
            new AntPathRequestMatcher("/websocket/**"),
            new AntPathRequestMatcher("/api/v1/download/**"),
            new AntPathRequestMatcher("/api/v1/owner/auth/**"),
            new AntPathRequestMatcher("/api/v1/operator/auth/**")
    );

    private static final RequestMatcher PROTECTED_URLS = new NegatedRequestMatcher(PUBLIC_URLS);

    @Override
    protected void configure(AuthenticationManagerBuilder auth) {
        auth.authenticationProvider(this.tokenAuthenticationProvider);
    }

    @Override
    public void configure(WebSecurity web) {
        web.ignoring().requestMatchers(PUBLIC_URLS);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.cors().and()
                .csrf().disable()
                .formLogin().disable()
                .httpBasic().disable()
                .logout().disable();

        http.headers().frameOptions().disable();

        http.authorizeRequests()
                .requestMatchers(PUBLIC_URLS)
                .permitAll();

        http.authorizeRequests()
                .antMatchers("/secured/**").authenticated();

        http
                .sessionManagement()
                .sessionCreationPolicy(STATELESS)
                .and()
                .exceptionHandling()
                .defaultAuthenticationEntryPointFor(unauthorizedEntryPoint, PROTECTED_URLS)
                .and()
                .authenticationProvider(tokenAuthenticationProvider)
                .addFilterBefore(tokenAuthenticationFilter(), AnonymousAuthenticationFilter.class)
                .authorizeRequests()
                .requestMatchers(PROTECTED_URLS)
                .authenticated();

    }

    @Bean
    TokenAuthenticationFilter tokenAuthenticationFilter() throws Exception {
        final TokenAuthenticationFilter filter = new TokenAuthenticationFilter(PROTECTED_URLS);
        filter.setAuthenticationManager(authenticationManager());
        filter.setAuthenticationSuccessHandler(new AuthenticationSuccessHandler());
        filter.setAuthenticationFailureHandler(new AuthenticationFailureHandler());
        return filter;
    }

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration configuration = new CorsConfiguration().applyPermitDefaultValues();
        configuration.addAllowedMethod(HttpMethod.PUT);
        configuration.addAllowedMethod(HttpMethod.DELETE);
        configuration.addAllowedMethod(HttpMethod.OPTIONS);
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

}
12 фев 19, 18:23    [21807733]     Ответить | Цитировать Сообщить модератору
 Re: Spring Boot 2 + Spring Security + JWT + WebSocket + SockJS + STOMP Проблема Авторизации  [new]
вадя
Member

Откуда: Екатеринбург
Сообщений: 16674
Tsyklop,

а что ты от использования этого хочешь добиться?
12 фев 19, 18:28    [21807740]     Ответить | Цитировать Сообщить модератору
 Re: Spring Boot 2 + Spring Security + JWT + WebSocket + SockJS + STOMP Проблема Авторизации  [new]
Озверин
Member

Откуда: Ростов-на-Дону
Сообщений: 5183
Так вроде тут и можно(из твоего кода). Единственное, что это надо делать только
if (StompCommand.CONNECT.equals(accessor.getCommand())) {} 
, если верить документации: https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#websocket-stomp-authentication

После чего, парсить юзака, записать его в текущую сессию, после чего оно там магически и автоматически ассоциирует сессию с пользователем....магия!


@Override
    public void configureClientInboundChannel(ChannelRegistration registration) {
        registration.interceptors(new ChannelInterceptor() {

            @Override
            public Message<?> preSend(Message<?> message,  MessageChannel channel) {

                StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);

                List<String> tokenList = accessor.getNativeHeader("Authorization");
                String token = null;

                if(tokenList == null || tokenList.size() < 1) {
                    return message;
                } else {
                    token = tokenList.get(0);
                    if(token == null) {
                        return message;
                    }
                }

                accessor.setUser(null);

                // not documented anywhere but necessary otherwise NPE in StompSubProtocolHandler!
                accessor.setLeaveMutable(true);
                return MessageBuilder.createMessage(message.getPayload(), accessor.getMessageHeaders());
            }

        });
    }
12 фев 19, 18:45    [21807750]     Ответить | Цитировать Сообщить модератору
 Re: Spring Boot 2 + Spring Security + JWT + WebSocket + SockJS + STOMP Проблема Авторизации  [new]
Tsyklop
Member

Откуда: Украина
Сообщений: 1069
вадя
Tsyklop, а что ты от использования этого хочешь добиться?

как ни странно получить авторизованного юзера
12 фев 19, 19:37    [21807795]     Ответить | Цитировать Сообщить модератору
 Re: Spring Boot 2 + Spring Security + JWT + WebSocket + SockJS + STOMP Проблема Авторизации  [new]
вадя
Member

Откуда: Екатеринбург
Сообщений: 16674
Tsyklop
как ни странно получить авторизованного юзера
почему этот гайд? разве нет ничего проще?
и я так понимаю
это
  private static final RequestMatcher PUBLIC_URLS = new OrRequestMatcher(
            new AntPathRequestMatcher("/"),
            new AntPathRequestMatcher("/index"),
            new AntPathRequestMatcher("/index.html"),
            new AntPathRequestMatcher("/resource/**"),
            new AntPathRequestMatcher("/favicon.ico"),
            new AntPathRequestMatcher("/actuator/**"),
            new AntPathRequestMatcher("/h2-console/**"),
            new AntPathRequestMatcher("/**/favicon.ico"),
            new AntPathRequestMatcher("/webjars/**"),
            new AntPathRequestMatcher("/websocket/**"),
            new AntPathRequestMatcher("/api/v1/download/**"),
            new AntPathRequestMatcher("/api/v1/owner/auth/**"),
            new AntPathRequestMatcher("/api/v1/operator/auth/**")

ограничивает доступность?
для всех или можно указать что и для какого юзера?
12 фев 19, 19:43    [21807799]     Ответить | Цитировать Сообщить модератору
 Re: Spring Boot 2 + Spring Security + JWT + WebSocket + SockJS + STOMP Проблема Авторизации  [new]
Tsyklop
Member

Откуда: Украина
Сообщений: 1069
вадя, это для реста. Открытые всем ресурсы.
12 фев 19, 19:46    [21807803]     Ответить | Цитировать Сообщить модератору
 Re: Spring Boot 2 + Spring Security + JWT + WebSocket + SockJS + STOMP Проблема Авторизации  [new]
Tsyklop
Member

Откуда: Украина
Сообщений: 1069
Озверин, Хорошо. Понял. А вот такой момент. Я так понимаю что юзер ложится в сессию. а у этой сессии есть время жизни. Когда сессия заинвалидейтится то юзер тоже пропадет. и соответственно если будет сообщение где требуется юзер, а его не будет то будет ошибка?

Может стоит на каждое сообщение проверять юзверя? да, понимаю что будет зашквар если много запросов. но все же.
12 фев 19, 19:50    [21807808]     Ответить | Цитировать Сообщить модератору
 Re: Spring Boot 2 + Spring Security + JWT + WebSocket + SockJS + STOMP Проблема Авторизации  [new]
Озверин
Member

Откуда: Ростов-на-Дону
Сообщений: 5183
Tsyklop, https://docs.spring.io/spring/docs/4.3.x/spring-framework-reference/html/websocket.html
12 фев 19, 21:38    [21807870]     Ответить | Цитировать Сообщить модератору
 Re: Spring Boot 2 + Spring Security + JWT + WebSocket + SockJS + STOMP Проблема Авторизации  [new]
Tsyklop
Member

Откуда: Украина
Сообщений: 1069
Озверин, это простой сокет. без sockjs. что я должен был там прочитать?
12 фев 19, 21:40    [21807871]     Ответить | Цитировать Сообщить модератору
 Re: Spring Boot 2 + Spring Security + JWT + WebSocket + SockJS + STOMP Проблема Авторизации  [new]
вадя
Member

Откуда: Екатеринбург
Сообщений: 16674
Tsyklop,
сессия wsимеет бесконечный срок. сессия http по умолчанию 30 минут, но http сессию можно продлять
т.е. при каждом обращении от клиента по ws время жизни продляется на некоторое время.
12 фев 19, 21:57    [21807876]     Ответить | Цитировать Сообщить модератору
 Re: Spring Boot 2 + Spring Security + JWT + WebSocket + SockJS + STOMP Проблема Авторизации  [new]
Tsyklop
Member

Откуда: Украина
Сообщений: 1069
вадя
Tsyklop,
сессия wsимеет бесконечный срок. сессия http по умолчанию 30 минут, но http сессию можно продлять
т.е. при каждом обращении от клиента по ws время жизни продляется на некоторое время.

Тут нет того что было в обычном websocket api.
12 фев 19, 22:04    [21807878]     Ответить | Цитировать Сообщить модератору
 Re: Spring Boot 2 + Spring Security + JWT + WebSocket + SockJS + STOMP Проблема Авторизации  [new]
Tsyklop
Member

Откуда: Украина
Сообщений: 1069
вадя, точнее тут идет работа выше того апи.
12 фев 19, 22:05    [21807879]     Ответить | Цитировать Сообщить модератору
 Re: Spring Boot 2 + Spring Security + JWT + WebSocket + SockJS + STOMP Проблема Авторизации  [new]
вадя
Member

Откуда: Екатеринбург
Сообщений: 16674
Tsyklop
вадя, точнее тут идет работа выше того апи.
да, но сам ws от этого не стал другим.
12 фев 19, 22:11    [21807882]     Ответить | Цитировать Сообщить модератору
 Re: Spring Boot 2 + Spring Security + JWT + WebSocket + SockJS + STOMP Проблема Авторизации  [new]
Tsyklop
Member

Откуда: Украина
Сообщений: 1069
Озверин
Tsyklop, https://docs.spring.io/spring/docs/4.3.x/spring-framework-reference/html/websocket.html

Так что там?
13 фев 19, 12:51    [21808326]     Ответить | Цитировать Сообщить модератору
 Re: Spring Boot 2 + Spring Security + JWT + WebSocket + SockJS + STOMP Проблема Авторизации  [new]
Озверин
Member

Откуда: Ростов-на-Дону
Сообщений: 5183
Tsyklop
Озверин
Tsyklop, https://docs.spring.io/spring/docs/4.3.x/spring-framework-reference/html/websocket.html

Так что там?


там вся интересующая вас информация. А на ту, что не хватает - есть ссылка.
13 фев 19, 13:08    [21808359]     Ответить | Цитировать Сообщить модератору
Все форумы / Java Ответить