当前位置:网站首页>Using SA token to solve websocket handshake authentication
Using SA token to solve websocket handshake authentication
2022-07-04 10:36:00 【Kongming Kongming】
Preface
Compared with Http Single communication mode ,WebSocket You can actively push messages from the server to the browser , This feature can help us accomplish things like Order message push 、IM Live chat And other specific businesses .
However WebSocket I am right “ Identity Authentication ” No direct support , The default connection to the client is “ All's fish that comes to his net ”, So authentication and authorization , We have to do it ourselves .
Sa-Token It's a java Authorization framework , It mainly solves login authentication 、 Permission authentication 、 Single sign on 、OAuth2、 Micro service gateway Authentication And so on .
Now let's introduce how to WebSocket In the integration Sa-Token Identity Authentication , Ensure the security of the connection .
Two ways to integrate
We will introduce the two most common integrations in turn WebSocket The way :
- Java Original version :javax.websocket.Session
- Spring Package version :WebSocketSession
I don't say much nonsense , Directly :
Mode one :Java Original version javax.websocket.Session
1、 The first is introduction pom.xml rely on
<!-- SpringBoot rely on --><dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-web</artifactid></dependency><!-- WebScoket rely on --><dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-websocket</artifactid> </dependency><!-- Sa-Token Permission authentication , Online document :http://sa-token.dev33.cn/ --><dependency> <groupid>cn.dev33</groupid> <artifactid>sa-token-spring-boot-starter</artifactid> <version>1.29.0</version></dependency>2、 Login interface , Used to get a session token
/** * Log on to the test */@[email protected]("/acc/")public class LoginController { // Test login ---- http://localhost:8081/acc/doLogin?name=zhang&pwd=123456 @RequestMapping("doLogin") public SaResult doLogin(String name, String pwd) { // Here is only a simulation example , Real projects need to query data from the database for comparison if("zhang".equals(name) && "123456".equals(pwd)) { StpUtil.login(10001); return SaResult.ok(" Login successful ").set("token", StpUtil.getTokenValue()); } return SaResult.error(" Login failed "); } // ... }3、WebSocket Connection processing
@[email protected]("/ws-connect/{satoken}")public class WebSocketConnect { /** * Fixed prefix */ private static final String USER_ID = "user_id_"; /** * Deposit Session aggregate , Easy to push messages (javax.websocket.Session) */ private static ConcurrentHashMap<string, session> sessionMap = new ConcurrentHashMap<>(); // monitor : Successful connection @OnOpen public void onOpen(Session session, @PathParam("satoken") String satoken) throws IOException { // according to token Get the corresponding userId Object loginId = StpUtil.getLoginIdByToken(satoken); if(loginId == null) { session.close(); throw new SaTokenException(" The connection fails , Invalid Token:" + satoken); } // put To the assembly , Convenient follow-up operation long userId = SaFoxUtil.getValueByType(loginId, long.class); sessionMap.put(USER_ID + userId, session); // Give me a hint. String tips = "Web-Socket Successful connection ,sid=" + session.getId() + ",userId=" + userId; System.out.println(tips); sendMessage(session, tips); } // monitor : Connection is closed @OnClose public void onClose(Session session) { System.out.println(" Connection is closed ,sid=" + session.getId()); for (String key : sessionMap.keySet()) { if(sessionMap.get(key).getId().equals(session.getId())) { sessionMap.remove(key); } } } // monitor : Received a message from the client @OnMessage public void onMessage(Session session, String message) { System.out.println("sid by :" + session.getId() + ", From :" + message); } // monitor : Something goes wrong @OnError public void onError(Session session, Throwable error) { System.out.println("sid by :" + session.getId() + ", An error occurred "); error.printStackTrace(); } // --------- // Push a message to the specified client public static void sendMessage(Session session, String message) { try { System.out.println(" towards sid by :" + session.getId() + ", send out :" + message); session.getBasicRemote().sendText(message); } catch (IOException e) { throw new RuntimeException(e); } } // Push a message to a specified user public static void sendMessage(long userId, String message) { Session session = sessionMap.get(USER_ID + userId); if(session != null) { sendMessage(session, message); } } }4、WebSocket To configure
/** * Turn on WebSocket Support */@Configuration public class WebSocketConfig { @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } } 5、 Start class
@SpringBootApplicationpublic class SaTokenWebSocketApplication { public static void main(String[] args) { SpringApplication.run(SaTokenWebSocketApplication.class, args); } }Set up , Start project
6、 test
1、 First, we access the login interface , Get the conversation token
http://localhost:8081/acc/doLogin?name=zhang&pwd=123456As shown in the figure :

2、 Then we'll find one WebSocket Connect to the online test page , for example :https://www.bejson.com/httputil/websocket/
Connection address :
ws://localhost:8081/ws-connect/302ee2f8-60aa-42aa-8ecb-eeae5ba57015As shown in the figure :

3、 If we enter a wrong token, What will happen? ?

You can see , The connection will be immediately disconnected !
Mode two :Spring Package version :WebSocketSession
1、 ditto : The first is introduction pom.xml rely on
<!-- SpringBoot rely on --><dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-web</artifactid></dependency><!-- WebScoket rely on --><dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-websocket</artifactid> </dependency><!-- Sa-Token Permission authentication , Online document :http://sa-token.dev33.cn/ --><dependency> <groupid>cn.dev33</groupid> <artifactid>sa-token-spring-boot-starter</artifactid> <version>1.29.0</version></dependency>2、 Login interface , Used to get a session token
/** * Log on to the test */@[email protected]("/acc/")public class LoginController { // Test login ---- http://localhost:8081/acc/doLogin?name=zhang&pwd=123456 @RequestMapping("doLogin") public SaResult doLogin(String name, String pwd) { // Here is only a simulation example , Real projects need to query data from the database for comparison if("zhang".equals(name) && "123456".equals(pwd)) { StpUtil.login(10001); return SaResult.ok(" Login successful ").set("token", StpUtil.getTokenValue()); } return SaResult.error(" Login failed "); } // ... }3、WebSocket Connection processing
/** * Handle WebSocket Connect */public class MyWebSocketHandler extends TextWebSocketHandler { /** * Fixed prefix */ private static final String USER_ID = "user_id_"; /** * Deposit Session aggregate , Easy to push messages */ private static ConcurrentHashMap<string, websocketsession> webSocketSessionMaps = new ConcurrentHashMap<>(); // monitor : Connection on @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { // put To the assembly , Convenient follow-up operation String userId = session.getAttributes().get("userId").toString(); webSocketSessionMaps.put(USER_ID + userId, session); // Give me a hint. String tips = "Web-Socket Successful connection ,sid=" + session.getId() + ",userId=" + userId; System.out.println(tips); sendMessage(session, tips); } // monitor : Connection is closed @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { // Remove from collection String userId = session.getAttributes().get("userId").toString(); webSocketSessionMaps.remove(USER_ID + userId); // Give me a hint. String tips = "Web-Socket Connection is closed ,sid=" + session.getId() + ",userId=" + userId; System.out.println(tips); } // Received a message @Override public void handleTextMessage(WebSocketSession session, TextMessage message) throws IOException { System.out.println("sid by :" + session.getId() + ", From :" + message); } // ----------- // Push a message to the specified client public static void sendMessage(WebSocketSession session, String message) { try { System.out.println(" towards sid by :" + session.getId() + ", send out :" + message); session.sendMessage(new TextMessage(message)); } catch (IOException e) { throw new RuntimeException(e); } } // Push a message to a specified user public static void sendMessage(long userId, String message) { WebSocketSession session = webSocketSessionMaps.get(USER_ID + userId); if(session != null) { sendMessage(session, message); } } }4、WebSocket Front interceptor
/** * WebSocket The front interceptor of handshake */public class WebSocketInterceptor implements HandshakeInterceptor { // Trigger before handshake (return true Will shake hands successfully ) @Override public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler handler, Map<string, object> attr) { System.out.println("---- Trigger before handshake " + StpUtil.getTokenValue()); // Refuse to shake hands without logging in if(StpUtil.isLogin() == false) { System.out.println("---- Unauthorized client , The connection fails "); return false; } // Mark userId, Shake hands with success attr.put("userId", StpUtil.getLoginIdAsLong()); return true; } // Trigger after handshake @Override public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) { System.out.println("---- Trigger after handshake "); } }5、WebSocket To configure
/** * WebSocket Related configuration */@[email protected] class WebSocketConfig implements WebSocketConfigurer { // register WebSocket processor @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) { webSocketHandlerRegistry // WebSocket Connecting the processor .addHandler(new MyWebSocketHandler(), "/ws-connect") // WebSocket Interceptor .addInterceptors(new WebSocketInterceptor()) // Allow cross-domain .setAllowedOrigins("*"); }}6、 Start class
/** * Sa-Token Integrate WebSocket Authentication example */@SpringBootApplicationpublic class SaTokenWebSocketSpringApplication { public static void main(String[] args) { SpringApplication.run(SaTokenWebSocketSpringApplication.class, args); } }Start project , Start testing
7、 test
1、 First access the login interface , Get the conversation token
http://localhost:8081/acc/doLogin?name=zhang&pwd=123456As shown in the figure :

2、 Then open the WebSocket Connect to the online test page , for example :https://www.bejson.com/httputil/websocket/
Connection address :
ws://localhost:8081/ws-connect?satoken=fe6e7dbd-38b8-4de2-ae05-cda7e36bf2f7As shown in the figure :

notes : Here the url Pass on Token Because it is more convenient on the third-party test page , In real projects, you can learn from Cookie、Header Parameters 、url Parameters Choose one of three ways to pass the session token , Same effect
3、 If you enter an incorrect Token

The connection fails !
The sample address
The above code has been uploaded git, The sample address : Code cloud :sa-token-demo-websocket
Reference material
- Gitee Address :https://gitee.com/dromara/sa-token
- GitHub Address :https://github.com/dromara/sa-token
- Sa-Token Official website :https://sa-token.dev33.cn/
</string,></string,></string,>
边栏推荐
- Static comprehensive experiment ---hcip1
- PHP code audit 3 - system reload vulnerability
- Debug:==42==ERROR: AddressSanitizer: heap-buffer-overflow on address
- Sword finger offer 05 (implemented in C language)
- Today's sleep quality record 78 points
- system design
- Talk about scalability
- Error C4996 ‘WSAAsyncSelect‘: Use WSAEventSelect() instead or define _ WINSOCK_ DEPRECATED_ NO_ WARN
- Latex arranges single column table pictures in double column format articles
- Evolution from monomer architecture to microservice architecture
猜你喜欢

Safety reinforcement learning based on linear function approximation safe RL with linear function approximation translation 2

From programmers to large-scale distributed architects, where are you (I)

Two way process republication + routing policy

Collection of practical string functions

Tables in the thesis of latex learning

Sword finger offer 05 (implemented in C language)

Virtual machine configuration network

Vs201 solution to failure to open source file HPP (or link library file)
![[Galaxy Kirin V10] [server] KVM create Bridge](/img/a4/a35a276d13e194cefc547607c59f00.jpg)
[Galaxy Kirin V10] [server] KVM create Bridge

Introduction to extensible system architecture
随机推荐
Write a program to judge whether the elements contained in a vector < int> container are 9.20: exactly the same as those in a list < int> container.
MongoDB数据日期显示相差8小时 原因和解决方案
IPv6 comprehensive experiment
Error C4996 ‘WSAAsyncSelect‘: Use WSAEventSelect() instead or define _ WINSOCK_ DEPRECATED_ NO_ WARN
Software sharing: the best PDF document conversion tool and PDF Suite Enterprise version sharing | with sharing
Jianzhi offer 04 (implemented in C language)
2020-03-28
Learning XML DOM -- a typical model for parsing XML documents
基于线性函数近似的安全强化学习 Safe RL with Linear Function Approximation 翻译 2
Const's constant member function after the function; Form, characteristics and use of inline function
Vs201 solution to failure to open source file HPP (or link library file)
Dynamic memory management
Evolution from monomer architecture to microservice architecture
Quick sort (C language)
leetcode1-3
[Galaxy Kirin V10] [desktop] build NFS to realize disk sharing
[Galaxy Kirin V10] [desktop] can't be started or the screen is black
Sword finger offer 05 (implemented in C language)
Use the data to tell you where is the most difficult province for the college entrance examination!
[Galaxy Kirin V10] [desktop] login system flash back