Spring安全性/Spring会话/Web套接字 [英] Spring security/Spring session/Web sockets

查看:299
本文介绍了Spring安全性/Spring会话/Web套接字的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正尝试结合使用Spring Session,Spring Security和Websockets,以在不使用Cookie的情况下为Websocket API实现安全性.

We are attempting to use a combination of spring session, spring security and websockets to implement security for a websocket API without using cookies.

理想情况下,我们将使用授权标头或通过websocket/stomp消息进行身份验证,但是在当前的spring websocket支持下,这似乎是不可能的.

Ideally we would be using a authorization header or authentication using the websocket/stomp messages but this does not seem to be possible with the current spring websocket support.

我们正在使用预身份验证提供程序来验证查询参数令牌并登录用户.我可以看到,正确的用户在预身份验证中被拔出了握手,但SecurityContext不可用于有线拦截器进入网络套接字.

We are using a pre-auth provider to validate a query parameter token and log the user in. I can see that the proper user is pulled out in the pre-auth for the handshake but the SecurityContext is not available to interceptors wired into the websocket.

我们的春季安全配置是

Our spring security configuration is

<!-- API security -->
<security:http use-expressions="false" realm="api" authentication-manager-ref="apiAuthenticationManager" entry-point-ref="accessDeniedAuthEntryPoint" pattern="/api/**" create-session="never">
    <security:custom-filter position="FIRST" ref="sessionRepositoryFilter" />
    <security:custom-filter position="PRE_AUTH_FILTER" ref="headerTokenAuthFilter" />
    <security:intercept-url pattern="/api/**" access="ROLE_USER" />


    <security:access-denied-handler  ref="accessDeniedHandler"  />

</security:http>

<security:authentication-manager id="apiAuthenticationManager">
    <security:authentication-provider ref="preauthAuthProvider" />
</security:authentication-manager>

<bean id="headerTokenAuthFilter" class="com.example.server.security.HeaderTokenAuthFilter" >
    <property name="authenticationManager" ref="apiAuthenticationManager"/>
    <property name="continueFilterChainOnUnsuccessfulAuthentication" value="false"/>
    <property name="checkForPrincipalChanges" value="true"/>
    <property name="sessionRepository" ref="sessionRepository" />
</bean>

<bean id="accessDeniedHandler" class="org.springframework.security.web.access.AccessDeniedHandlerImpl" />
<bean id="accessDeniedAuthEntryPoint" class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint" />

<bean id="sessionRepository" class="org.springframework.session.data.redis.RedisOperationsSessionRepository">
    <constructor-arg ref="jedisConnectionFactory"/>
</bean>
<bean id="sessionRepositoryFilter" class="org.springframework.session.web.http.SessionRepositoryFilter">
    <constructor-arg ref="sessionRepository"/>
</bean>

我们的websocket配置为

Our websocket configuration is

@Configuration
@EnableScheduling
@EnableWebSocketMessageBroker
public class WebsocketConfiguration extends AbstractSessionWebSocketMessageBrokerConfigurer<ExpiringSession> {

@Inject
private AuthenticationValidationInterceptor authenticationValidationInterceptor;
@Inject
private SelectorQuotingInterceptor selectorQuotingInterceptor;
@Inject
private SelectorValidationInterceptor selectorValidationInterceptor;

@Override
protected void configureStompEndpoints(StompEndpointRegistry registry) {
    registry.addEndpoint("/stomp")
            .withSockJS().setSessionCookieNeeded(false);
}

@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
    registry.enableStompBrokerRelay("/topic")
            .setRelayHost("localhost")
            .setRelayPort(7672);
    registry.setApplicationDestinationPrefixes("/api/data/streaming");
}

@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
    registration.setInterceptors(
            authenticationValidationInterceptor,
            selectorValidationInterceptor,
            selectorQuotingInterceptor);
}

@Override
public void configureClientOutboundChannel(ChannelRegistration registration) {

}

}

推荐答案

此处是被告的同事.我们的配置在很大程度上是正确的,但是我们的问题源于对安全上下文及其从Websocket方面的可用性的误解.

Coworker of the accursed here. Our configuration is largely correct but our issue stemmed from a bit of a misunderstanding around the security context and its availability from the websocket side of things.

评论来自 https://jira.spring.io/browse/SEC-2179 使我们从拦截器中的消息中获取了登录的用户主体

Comments gathered from various sub-issues of https://jira.spring.io/browse/SEC-2179 led us to grabbing the logged in user principal from the message in the interceptor

StompHeaderAccessor headerAccessor = StompHeaderAccessor.wrap(message);
Principal userPrincipal = headerAccessor.getUser();

而不是

SecurityContextHolder.getContext().getAuthentication().getName();

这篇关于Spring安全性/Spring会话/Web套接字的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆