当前位置:网站首页>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,>
边栏推荐
- Network connection (II) three handshakes, four waves, socket essence, packaging of network packets, TCP header, IP header, ACK confirmation, sliding window, results of network packets, working mode of
- Online troubleshooting
- 【FAQ】华为帐号服务报错 907135701的常见原因总结和解决方法
- Reprint: summation formula of proportional series and its derivation process
- Network connection (III) functions and similarities and differences of hubs, switches and routers, routing tables and tables in switches, why do you need address translation and packet filtering?
- Seven examples to understand the storage rules of shaped data on each bit
- Virtual machine configuration network
- Button wizard business running learning - commodity quantity, price reminder, judgment Backpack
- What is an excellent architect in my heart?
- [Galaxy Kirin V10] [server] NUMA Technology
猜你喜欢

六月份阶段性大总结之Doris/Clickhouse/Hudi一网打尽

【FAQ】华为帐号服务报错 907135701的常见原因总结和解决方法
![[Galaxy Kirin V10] [server] NUMA Technology](/img/9b/65466c6fc6336e27e842f50c26b9c3.jpg)
[Galaxy Kirin V10] [server] NUMA Technology

Delayed message center design

Reasons and solutions for the 8-hour difference in mongodb data date display

Development guidance document of CMDB

Rhcsa day 10 operation

Architecture introduction

The time difference between the past time and the present time of uniapp processing, such as just, a few minutes ago, a few hours ago, a few months ago

Vs201 solution to failure to open source file HPP (or link library file)
随机推荐
Static comprehensive experiment ---hcip1
Press the button wizard to learn how to fight monsters - identify the map, run the map, enter the gang and identify NPC
[Galaxy Kirin V10] [desktop] cannot add printer
Realsense of d435i, d435, d415, t265_ Matching and installation of viewer environment
BGP advanced experiment
Batch distribution of SSH keys and batch execution of ansible
Linked list operation can never change without its roots
[Galaxy Kirin V10] [server] NUMA Technology
[FAQ] summary of common causes and solutions of Huawei account service error 907135701
[Galaxy Kirin V10] [server] system partition expansion
按键精灵跑商学习-商品数量、价格提醒、判断背包
uniapp 小于1000 按原数字显示 超过1000 数字换算成10w+ 1.3k+ 显示
Rhcsa learning practice
[Galaxy Kirin V10] [server] NFS setup
The bamboo shadow sweeps the steps, the dust does not move, and the moon passes through the marsh without trace -- in-depth understanding of the pointer
原生div具有编辑能力
六月份阶段性大总结之Doris/Clickhouse/Hudi一网打尽
Talk about scalability
Leetcode48. Rotate image
Two way process republication + routing policy