springboot整合springsecurity+websocket+thymeleaf

1.创建一个普通的springboot-web项目,导入相关的依赖。



    org.springframework.boot
    spring-boot-starter-web



    org.springframework.boot
    spring-boot-starter-test
    test



    org.springframework.boot
    spring-boot-starter-websocket



    org.webjars
    webjars-locator-core
    0.35



    org.webjars
    sockjs-client
    1.1.2



    org.webjars
    stomp-websocket
    2.3.3-1



    org.webjars
    jquery
    3.3.1-1



    org.springframework.boot
    spring-boot-starter-thymeleaf



    org.springframework.boot
    spring-boot-starter-security

2.配置thymeleaf

在application.properties添加

spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
spring.thymeleaf.servlet.content-type=text/html
spring.thymeleaf.encoding=UTF-8

3.配置websocket

<1>.WebSocket简介
WebSocket是一种在单个TCP连接上进行双全工通信的协议,已被W3C定为标准,使用WebSocket可以使得客户端和服务器之间的数据交换变得更加简单,他允许服务端主动向客户端推送数据,在WebSocket协议中,浏览器和服务端只需要完成一次握手,两者之间就可以建立持久性的连接,并进行双向数据传输
WebSocket使用了HTTP/1.1的协议升级特性,一个WebSocket请求首先使用非正常的HTTP请求以特定的模式访问一个URL,这个URL有两种模式,分别是ws和wss,对应HTTP协议中的HTTP以及HTTPS,在请求头有一个Connection:Upgrade字段,表示客户端想要对协议进行升级,另外还有一个Upgrade:websocket字段,表示客户端想要将请求协议升级为WebSocket协议,这两个字段共同告诉服务器要将连接升级为WebSocket这样一个双全工协议,如果服务端同意协议升级,那么在握手完成之后,文本消息或者其他二进制的消息就可以同时在两个方向上进行发送,而不需要关闭和重新连接,此时的客户端可服务端的关系是对等的,他们可以互相向对方主动发送消息,和传统的解决方案相比,WebSocket具有如下特点:
(1)WebSocket使用时需要先创建连接,这使得WebSocket成为一种有状态的协议,在之后的通行过程中可以省略部分状态信息(例如身份认证等)
(2)WebSocket连接在端口80(ws)或者443(wss)上连接,与HTTP使用的端口相同,这样基本所有的防火墙都不会阻止WebSocket的连接
(3)WebSocket使用HTTP协议进行握手,因此可以直接集成到网络浏览器和HTTP服务器中,不需要额外的成本
(4)心跳消息(ping和pong)将被反复推送,保持WebSocket一致处于活跃状态
(5)使用该协议,当消息启动或者到达时,服务端和客户端都可以知道
(6)Websocket连接关闭时将发送一个特殊的关闭消息
(7)WebSocket支持跨域,可以避免Ajax的限制
(8)HTTP规范要求浏览器将并发连接限制为每个主机名两个连接,但是当我们使用WebSocket的时候,当握手完成后,该限制就不存在了,因为此时的连接已经不再是HTTP连接了
(9)WebSocket协议支持扩展,用户可以扩展协议,实现部分自定义的子协议
(10)更好的二进制支持以及更好的压缩效果

<2>.配置

1.添加主配置类

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        registry.enableSimpleBroker("/topic");
        registry.setApplicationDestinationPrefixes("/app");
    }
    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {

        registry.addEndpoint("/chat").withSockJS();
    }
}

1>.自定义WebSocketConfig继承自WebSocketMessageBrokerConfigurer进行WebSocket配置,然后通过@EnableWebSocketMessageBroker注解开启了WebSocket消息代理
2>.registry.enableSimpleBroker("/topic")表示设置消息代理的前缀,即如果消息的前缀是”/topic”,就会将消息转发给代理(broker),再由消息代理将消息广播给当前连接的客户端(通俗的讲就后台向前台发送消息的地址要加上/topic前缀
)
3>.registry.setApplicationDestinationPrefixes("/app")表示配置一个或多个前缀,通过这些前缀过滤出需要被注解方法处理的消息(通俗的讲就前台向后台发送消息的地址要加上/app前缀)
4>.registry.addEndpoint("/chat").withSockJS()表示定义一个前缀为”/chat”的edPoint,并开启sockjs支持,sockjs可以解决浏览器对WebSocket的兼容性问题,客户端将通过这里配置的URL来建立WebSocket连接(确切的说就是通过/chat进行连接后台)

2.添加controller

@RestController
public class GreetingController {
    @Autowired
    SimpMessagingTemplate simpMessagingTemplate;
    @MessageMapping("/hello")
    public void greeting(Message message)throws Exception{
        simpMessagingTemplate.convertAndSend("/topic/greetings","您好");
    }
}

SimpMessagingTemplate 代理对象,服务器向前端用户发送消息。

3.前端代码

主要用到SockJS对象,有初始化建立连接,发送,接收消息,还有断开连接等方法。

4.配置springsecurity

1.主配置类

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{

    @Bean// 密码加密
    PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    /**
     * 密码加密过:123
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("齐**")
                .password("$2a$10$RMuFXGQ5AtH4wOvkUqyvuecpqUSeoxZYqilXzbz50dceRsga.WYiq")
                .roles("admin")
                .and()
                .withUser("辛**")
                .password("$2a$10$RMuFXGQ5AtH4wOvkUqyvuecpqUSeoxZYqilXzbz50dceRsga.WYiq")
                .roles("user")
                .and()
                .withUser("李**")
                .password("$2a$10$RMuFXGQ5AtH4wOvkUqyvuecpqUSeoxZYqilXzbz50dceRsga.WYiq")
                .roles("user")
                .and()
                .withUser("岳**")
                .password("$2a$10$RMuFXGQ5AtH4wOvkUqyvuecpqUSeoxZYqilXzbz50dceRsga.WYiq")
                .roles("user")
                .and()
                .withUser("尚**")
                .password("$2a$10$RMuFXGQ5AtH4wOvkUqyvuecpqUSeoxZYqilXzbz50dceRsga.WYiq")
                .roles("user");
    }
// 任何请求毒药进行授权认证才能访问
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest()
                .authenticated()
                .and()
                .formLogin()
                .permitAll();
    }
}

2.controller类

@RestController
public class GreetingController {

    @Autowired
    SimpMessagingTemplate simpMessagingTemplate;

    /**
     * 消息群发
     * @param message
     * @return
     * @throws Exception
     */
    @MessageMapping("/hello")
    @SendTo("/topic/greetings")
    public Message greeting(Message message) throws Exception {
        return message;

    }

    /**
     * 点对点发送
     * @param principal
     * @param chat
     * @throws Exception
     */
    @MessageMapping("/chat")
    public void chat(Principal principal, Chat chat) throws Exception {
        String from=principal.getName();
        chat.setFrom(from);
        simpMessagingTemplate.convertAndSendToUser(chat.getTo(), "/queue/chat", chat);;
    }
}

1)群发消息依然使用@SendTo来实现,点对点则用SimpMessagingTemplate(单发消息)来实现

2)@MessageMapping("/chat")表示来自”/app/chat”路径的消息将被chat方法处理,chat方法的第一个参数Principal可以用来获取当前登录用户的信息,第二个参数则是客户端发送来的消息

3)在chat方法中,首先获取当前登录用户的用户名,设置给chat对象的from属性,再将消息发送出去,发送的目标就是chat的to属性

4)消息发送使用的方法是convertAndSendToUser,该方法内部调用了convertAndSend方法,并对消息路径做了处理(单发消息),chat可以换成任意的object对象,用于存储消息。

参考文章:https://blog.51cto.com/13501268/2403079?source=dra

 

 

你可能感兴趣的:(springboot)