1. WebSocket 基础概念
什么是 WebSocket?
WebSocket 是一种网络通信协议,可通过单个TCP 连接提供全双工通信。 “全双工”是指客户端和服务器可以同时发送和接收信息,而不像传统的HTTP 请求是半双工的(即一次只能执行一个请求或响应)。
WebSocket 与 HTTP 的区别
连接持久性:HTTP 协议基于请求/响应模型,连接通常在服务器响应请求后关闭。 WebSocket 在握手后建立持久连接,直到客户端或服务器决定终止连接。实时:WebSockets支持实时数据传输。这对于需要快速响应的应用(在线游戏、实时聊天等)来说非常重要。标头大小:WebSocket 标头信息比HTTP 小,因此WebSocket 发送数据时需要的开销较小。
建立连接的过程
客户端请求:WebSocket 连接由“升级”HTTP 请求初始化。客户端发送一个特殊的HTTP 请求,其中包含Upgrade: Websocket 和Connection: Upgrade 标头。服务器响应:如果服务器支持WebSockets,则返回状态码101 Switching Protocol,表示服务器已同意协议更改。数据传输:握手完成后,可以通过此连接双向传输数据。
使用场景
实时聊天应用程序在线游戏实时数据更新(例如股票价格) 协作应用程序(例如实时文档编辑)
WebSocket URL
WebSocket URL 以ws://(未加密)或wss://(加密)开头,HTTP 以http://开头,HTTPS 以https://开头。
2. 在 Spring Boot 中使用 WebSocket
步骤 1: 添加依赖项
首先,将Spring Boot 对WebSockets 的支持添加到您的pom.xml 文件中。这通常意味着添加spring-boot-starter-websocket 依赖项。
复制xml 代码中的依赖项
依赖
groupIdorg.springframework.boot/groupId
artifactIdspring-boot-starter-websocket/artifactId
/依赖
!– 其他依赖项–
/依赖项
步骤 2: 配置 WebSocket
在Spring Boot 应用程序中创建一个配置类来启用和配置WebSocket。
@作品
@EnableWebSocketMessageBroker //启用WebSocket消息代理
公共类WebSocketConfig 实现WebSocketMessageBrokerConfigurer {
@覆盖
公共无效registerStompEndpoints(StompEndpointRegistry注册表){
//注册客户端将用于连接到WebSocket 服务器的WebSocket 端点。
registry.addEndpoint(\’/ws\’).withSockJS();
//SockJS用于兼容不支持WebSockets的浏览器
}
@覆盖
公共无效configureMessageBroker(MessageBrokerRegistry注册表){
//定义一个消息代理将消息从一个客户端路由到另一个客户端
registry.setApplicationDestinationPrefixes(\’/app\’);
//客户端将使用此前缀发送消息
registry.enableSimpleBroker(\’/topic\’);
//简单的消息代理,定义客户端可以订阅的前缀
}
}
这里,STOMP(简单文本导向消息协议)用作WebSocket的子协议。 STOMP 提供可互操作的有线格式,允许STOMP 客户端与启用STOMP 的消息代理进行交互。
步骤 3: 创建 WebSocket 控制器
接下来,创建一个控制器来处理发送到WebSocket 的消息。
@控制器
公共类WebSocketController {
@MessageMapping(\’/hello\’) //定义消息的地址
@SendTo(\’/topic/greetings\’) //定义客户端订阅的地址
公共Stringgreeting(字符串消息)抛出异常{
//当服务器收到来自“/app/hello”的消息时调用此方法
返回\’你好,\’+消息+\’!\’;
}
}
该控制器接收发送到/app/hello 的消息并将响应发送到/topic/greetings。
步骤 4: 客户端连接
在客户端,您需要使用适当的库来建立WebSocket 连接。如果您的客户端是网页,则可以使用SockJS 和STOMP 客户端库。
!DOCTYPE html
html
头
titleWebSocket 测试/标题
脚本src=\’https://cdn.jsdelivr.net/npm/sockjs-client/dist/sockjs.min.js\’/script
脚本src=\’https://cdn.jsdelivr.net/npm/stomp-websocket/lib/stomp.min.js\’/script
/头
身体
脚本类型=\’文本/javascript\’
var socket=new SockJS(\’/ws\’); //连接到服务器上的WebSocket 端点。
var stompClient=Stomp.over(socket) //使用STOMP 子协议。
stompClient.connect({}, 函数(框架) {
//连接成功后的回调函数
console.log(\’Connected:\’ + 框架);
stompClient.subscribe(\’/topic/greetings\’, 函数(问候语) {
//在“/topic/greetings”中注册以接收消息
警报(JSON.parse(greeting.body).content);
});
});
函数发送消息() {
stompClient.send(\’/app/hello\’, {}, JSON.stringify({\’name\’: \’yourName\’}));
//发送消息到“/app/hello”
}
/剧本
Button onclick=\’sendMessage()\’发送消息/按钮
/身体
/html
2.Spring Security安全框架
Spring Security是专门针对Java应用程序的安全框架。为基于Spring的应用程序提供全面的安全解决方案。
安全性提供了一个默认的登录页面,并在未登录的情况下拦截对此页面的所有请求。默认的登录名和密码可以在yml配置文件中更改。
弹簧:
安全:
用户:
name: 老板
密码: 123
使用顺序
创建数据库并使用Mybatis管理的dao层创建密码解析器——PasswordEncoder。
公共类MyPasswordEncode 实现PasswordEncoder {
/*
*密码加密方式
* */
@覆盖
公共字符串编码(CharSequence rawPassword){
System.out.println(\’自定义密码解析器,encode方法执行\’);
返回rawPassword.toString()。
}
/**
*如何验证密码的明文和密文是否相同
* @param rawPassword 客户端传递的纯文本密码。
* @param encodedPassword 服务器上存储的密文密码。
* @返回
*/
@覆盖
公共布尔匹配(CharSequence rawPassword,字符串编码密码){
//首先使用编码方式使用相同的加密策略对明文进行加密,然后比较密文。
返回编码(rawPassword).equals(encodedPassword);
}
/*
* 是否需要升级你的密码破解策略,强化你的密码破解策略
* */
@覆盖
公共布尔upgradeEncoding(字符串编码密码){
返回PasswordEncoder.super.upgradeEncoding(encodedPassword)。
}
}
创建一个配置类只管理这个解析器——解析器
定义登录服务类型——的方法的实现是根据用户名查询用户对象和用户权限列表。 (我的用户详细信息服务Impl)
/**
*登录服务实现类型
*/
@成分
公共类MyUserDetailsServiceImpl 实现UserDetailsService {;
@Autowired
userMapper 用户映射器;
/**
*该方法的实现根据用户名查询用户对象和用户权限列表。
* @param 用户名
* @返回
* @抛出用户名未找到异常
*/
@覆盖
公共UserDetails loadUserByUsername(字符串用户名)抛出UsernameNotFoundException {
//根据用户名查询用户
用户user=userMapper.SelectByUserName(用户名);
//判断用户是否存在
如果(用户==空)
{
throw new UsernameNotFoundException(\’用户名或密码不正确\’);
}
//返回UserDetails 接口类型的对象
org.springframework.security.core.userdetails.user 结果=
新的org.springframework.security.core.userdetails.User(
username,//登录用户的用户名
user.getPassword(),//登录用户的密码是服务器存储的密文
AuthorityUtils.NO_AUTHORITIES//工具没有提供任何权限的空集合,
);
返回结果。
}
}
安全性** 登录自动自定义验证的默认设置** 执行顺序
当登录默认页面时,sercurity会自动调用实现PosswordEndcoder接口的类的encode方法来解析密码,然后sercurity调用实现UserDetailsService接口的实现类的loadUserByUsername方法来检索用户。查询然后安全将继续。调用实现PosswordEndcoder接口的类的encode方法,确保库密码和表单密码匹配。
MySecurityConfiguration配置类的编写
@作品
@EnableWebSecurity
公共类MySecurityConfiguration {
/**
* 创建安全过滤器链对象
* @返回
*/
@豆子
public SecurityFilterChain securityFilterChain(HttpSecurity security) 抛出异常{
//登录设置类
定制器FormLoginConfigurerHttpSecurity 定制器=新定制器FormLoginConfigurerHttpSecurity(){
@覆盖
公共无效定制(FormLoginConfigurerHttpSecurity配置器){
//具体认证设置
作曲家
.loginPage(\’/登录\’)
//.defaultSuccessUrl(\’/test\’)//默认跳转地址
//.successForwardUrl(\’/test\’) //认证成功后跳转到地址
.successHandler(new MyAuthenticationsuccessHandler(\’/test\’,true))//设置认证成功后的处理代码逻辑。
.failureUrl(\’/loginfail\’)//登录失败跳转地址
;//设置登录页面访问地址。默认为/登录。必须是检索请求。定制后提供控制器+视图
}
};
//设置认证配置
安全
.formLogin(定制器);
//完成登录设置
定制器LogoutConfigurerHttpSecurity logoutCustomizer=新定制器LogoutConfigurerHttpSecurity() {
@覆盖
公共无效自定义(LogoutConfigurerHttpSecurity configLoginout){
配置退出登录
.logoutUrl(\’/logout\’)//注销请求地址
.logoutSuccessUrl(\’/login\’)//注销成功后的跳转地址是否为默认登录页面地址?
.logoutSuccessHandler(new MyLogOutsuccessHandler()) //设置注销登录成功后的处理代码
.addLogoutHandler(new MyLogOutHandler())
;
}
};
//设置注销设置
security.logout(logoutCustomizer);
安全
.authorizeRequests()
.antMatchers(\’/login\’,\’/css/**\’,\’/image/**\’,\’/loginfail\’).permitAll() //允许所有用户访问/login 路径
.anyRequest().authenticated(); //所有其他请求都需要身份验证
//关闭CSRF功能
security.csrf().disable();
返回security.build()。
}
/**
* 创建密码编码器类型的bean对象
*/
@豆子
公共密码编码器密码编码器(){
//strong哈希密码解析器。该构造方法可以传递一个范围为4到31的整数参数。数字越高,实力越高,但性能越低。
返回一个新的BCryptPasswordEncoder()。
}
}
MyAuthenticationsuccessHandler类用于处理认证成功的处理逻辑
//认证成功后的处理逻辑
公共类MyAuthenticationssuccessHandler 实现AuthenticationSuccessHandler {
//登录成功后访问的地址
私有字符串URL;
//是重定向吗?
私有布尔值是一个重定向。
公共MyAuthenticationssuccessHandler(字符串url,布尔isRedirect){
这个.url=url;
this.isRedirect=isRedirect;
}
/**
* 认证成功后具体执行代码
* @参数请求
* @参数响应
* @paramauthentication 认证成功后的用户主体对象(包含个人的登录信息和权限列表)
* @抛出IOException
* @抛出ServletException
*/
@覆盖
public void onAuthenticationSuccess(HttpServletRequest请求,HttpServletResponse响应,身份验证authentication)抛出IOException,ServletException {
if(是重定向){
//重定向
响应.sendRedirect(url);
}除此之外
//转移要求
request.getRequestDispatcher(url).forward(请求,响应);
}
}
MyLogOutHandler(登出的一般做额外处理,比如保存会话中某些attribute到数据库)
公共类MyLogOutHandler 实现LogoutHandler {
/**
* 处理逻辑
* @参数请求
* @参数响应
* @参数验证
*/
@覆盖
公共无效注销(HttpServletRequest请求,HttpServletResponse响应,身份验证){
//通常会执行额外的处理,例如将会话中的某些属性保存到数据库中。
//日志记录等
}
}
MyLogOutsuccessHandler(登出成功的处理逻辑)
公共类MyLogOutsuccessHandler 实现LogoutSuccessHandler {
/**
*注销成功后的操作
*/
@Override
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
System.out.println(\”退出登录成功后的处理\”);
//销毁会话,清空缓存
request.getSession().invalidate();//销毁会话
authentication.setAuthenticated(false);//设置未登录状态
response.sendRedirect(\”/login\”);//进行重定向
}
}
#以上关于Websocket And Security的相关内容来源网络仅供参考,相关信息请以官方公告为准!
原创文章,作者:CSDN,如若转载,请注明出处:https://www.sudun.com/ask/93809.html