繁体   English   中英

Spring MVC + Stomp + WebSocket + https 不能作为 http 工作

[英]Spring MVC + Stomp + WebSocket + https not working as http

我有一个功能可以在我的应用程序中显示即时通知,就像有人发送消息一样,我会向其他用户发送通知,就像您收到新消息一样。 为此,我使用 Spring MVC + Stomp + WebSocket。

在我的本地/测试环境中,Web 套接字帧通过 http 接收和正常工作。 Prod 环境在 https 上,帧没有像 http 那样接收。 因此,通知不会更新。

我在 websocket 响应中观察到一件事:在本地服务器上显示电子邮件时的用户名。 在 Prod 服务器中显示一些随机长值。

春季版本:4.3.5.RELEASE
春季安全:4.2.1.RELEASE

网络套接字配置:

import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/topic");
        config.setApplicationDestinationPrefixes("/app");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/stomp/notify").withSockJS();
    }
}

网络安全配置:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.encoding.ShaPasswordEncoder;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.session.HttpSessionEventPublisher;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;


@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    AuthenticationService authenticationService;

    @Value("${ssl.enabled:false}")
    private boolean sslEnabled;

    @Autowired
    public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception {
        ShaPasswordEncoder encoder = new ShaPasswordEncoder();
        auth.userDetailsService(authenticationService).passwordEncoder(encoder);
    }

    @Bean
    public HttpSessionEventPublisher httpSessionEventPublisher() {
        return new HttpSessionEventPublisher();
    }

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

        if (sslEnabled) {
            http.requiresChannel().antMatchers("/").requiresSecure();
        }

        /* authorize requests */
        http.authorizeRequests()
                .antMatchers("/").permitAll()
                .antMatchers("/university-signup").permitAll()
                .antMatchers("/fb1clicksignup").permitAll()
                .antMatchers("/about").permitAll()
                .antMatchers("/media").permitAll()
                .antMatchers("/invite").permitAll()
                .antMatchers("/public").permitAll()
                .antMatchers("/reset-password").permitAll()
                .antMatchers("/email-unsubscribe").permitAll()
                .antMatchers("/email-subscribe").permitAll()
                .antMatchers("/member")
                .access("hasAnyAuthority('USER')")
                .antMatchers("/member/*")
                .access("hasAnyAuthority('USER')")
                .and().exceptionHandling().accessDeniedPage("/");   

        /* login form */
        http.formLogin().loginPage("/")
                .loginProcessingUrl("/login")
                .successHandler(customSuccessHandler())
                .usernameParameter("email").passwordParameter("password")
                .and().csrf();

        /* logout */
        http.logout().deleteCookies("remember_me_chk")
                .invalidateHttpSession(true)
                .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
                .logoutSuccessUrl("/");

        /* remember me*/
        http.rememberMe().
                key("ec2Mm2458nestOU812lingpiaza2910").
                rememberMeParameter("remember-me-param").
                rememberMeCookieName("remember_me_chk").
                tokenValiditySeconds(31536000);


        http.sessionManagement().maximumSessions(2); //a user can only have 2 active sessions
        http.sessionManagement().sessionAuthenticationErrorUrl("/"); //kick the user to the homepage if session is not valid
        http.sessionManagement().sessionFixation().migrateSession();
        http.sessionManagement().invalidSessionUrl("/");

    }

    @Bean
    public CustomSuccessHandler customSuccessHandler() {
        return new CustomSuccessHandler();
    }
}

消息发送逻辑:

@Autowired
private SimpMessagingTemplate messageSender;

public void sendNotification() {
     messageSender.convertAndSend("/topic/messages", "Got New Message!");
}

本地/测试服务器请求 url:

ws://mydomain.com/stomp/notify/879/z5qcek18/websocket

本地/测试服务器响应帧:

a["CONNECTED\nversion:1.1\nheart-beat:0,0\nuser-name:usertest@mydomain.com\n\n\u0000"]

Prod 服务器请求 url:

wss://mydomain.com/stomp/notify/879/z5qcek18/websocket

产品服务器响应帧:

a["CONNECTED\nversion:1.1\nheart-beat:0,0\nuser-name:110721669125112652938\n\n\u0000"]

我的应用程序中有社交网络登录是我的错。 如果我做直接登录电子邮件可用。 如果我做社交网络登录电子邮件对我不可用。 所以我将 spring 安全主体用户名设置为 oauth 令牌。 这就是它将响应帧显示为不同的原因。 现在我将 emailId 设置为 spring 安全主体用户名,它按预期工作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM