1

スプリング セッション、スプリング セキュリティ、および Websockets の組み合わせを使用して、Cookie を使用せずに Websocket API のセキュリティを実装しようとしています。

理想的には、websocket/stomp メッセージを使用して認証ヘッダーまたは認証を使用することになりますが、これは現在の Spring Websocket サポートでは不可能のようです。

事前認証プロバイダーを使用して、クエリ パラメーター トークンを検証し、ユーザーをログインさせています。ハンドシェイクの事前認証で適切なユーザーが引き出されていることがわかりますが、Websocket に配線されたインターセプターは SecurityContext を使用できません。 .

私たちの春のセキュリティ構成は

<!-- 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>

私たちのウェブソケットの設定は

@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) {

}

}
4

1 に答える 1

2

ここの呪われし者の同僚。私たちの設定はおおむね正しいですが、問題はセキュリティ コンテキストと Websocket 側からのその可用性に関する少しの誤解から生じました。

https://jira.spring.io/browse/SEC-2179のさまざまなサブイシューから収集されたコメントにより、インターセプターのメッセージからログインしているユーザー プリンシパルを取得することができました。

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

それよりも

SecurityContextHolder.getContext().getAuthentication().getName();
于 2015-01-20T09:59:39.057 に答える