springboot整合springsecurity+websocket+thymeleaf

时间:2025-02-19 12:45:24

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

<!--启动    -->
<dependency>
    <groupId></groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--测试-->
<dependency>
    <groupId></groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
<!--springboot-webscoket整合-->
<dependency>
    <groupId></groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<!--保证样式版本唯一-->
<dependency>
    <groupId></groupId>
    <artifactId>webjars-locator-core</artifactId>
    <version>0.35</version>
</dependency>
<!--引入wsockjs-->
<dependency>
    <groupId></groupId>
    <artifactId>sockjs-client</artifactId>
    <version>1.1.2</version>
</dependency>
<!--引入websocket-->
<dependency>
    <groupId></groupId>
    <artifactId>stomp-websocket</artifactId>
    <version>2.3.3-1</version>
</dependency>
<!--引入jquery-->
<dependency>
    <groupId></groupId>
    <artifactId>jquery</artifactId>
    <version>3.3.1-1</version>
</dependency>
<!--thymeleaf-->
<dependency>
    <groupId></groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!--springsecurity-->
<dependency>
    <groupId></groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

2.配置thymeleaf

在添加

=classpath:/templates/
=.html
-type=text/html
=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) {
        ("/topic");
        ("/app");
    }
    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {

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

1>.自定义WebSocketConfig继承自WebSocketMessageBrokerConfigurer进行WebSocket配置,然后通过@EnableWebSocketMessageBroker注解开启了WebSocket消息代理
2>.("/topic")表示设置消息代理的前缀,即如果消息的前缀是”/topic”,就会将消息转发给代理(broker),再由消息代理将消息广播给当前连接的客户端(通俗的讲就后台向前台发送消息的地址要加上/topic前缀
)
3>.("/app")表示配置一个或多个前缀,通过这些前缀过滤出需要被注解方法处理的消息(通俗的讲就前台向后台发送消息的地址要加上/app前缀)
4>.("/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{
        ("/topic/greetings","您好");
    }
}

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

3.前端代码

<script>
    var stompClient = null;//SockJS服务器和用户连接对象
    function connect() { 
        var socket = new SockJS('/chat');// 连接服务器
        stompClient = (socket);// 初始化
        ({}, function(frame) {
            ('/topic/greetings', function(greeting) {// 获取服务器端发送过来的消息
                alert(());
            });
        });
    }
    function disconnect() {// 关闭连接
        if (stompClient !== null) {
            ();
        }
    }
   // 前端向后端发送信息
        ("/app/hello", {}, ({
            'name' : $("#name").val(),
            'content' : $("#content").val()
        }));
</script>

主要用到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 {
        ()
                .withUser("齐**")
                .password("$2a$10$")
                .roles("admin")
                .and()
                .withUser("辛**")
                .password("$2a$10$")
                .roles("user")
                .and()
                .withUser("李**")
                .password("$2a$10$")
                .roles("user")
                .and()
                .withUser("岳**")
                .password("$2a$10$")
                .roles("user")
                .and()
                .withUser("尚**")
                .password("$2a$10$")
                .roles("user");
    }
// 任何请求毒药进行授权认证才能访问
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        ()
                .anyRequest()
                .authenticated()
                .and()
                .formLogin()
                .permitAll();
    }
}

@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=();
        (from);
        ((), "/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./13501268/2403079?source=dra