当前位置:网站首页>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=123456
As 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-eeae5ba57015
As 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=123456
As 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-cda7e36bf2f7
As 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,>
边栏推荐
- Doris / Clickhouse / Hudi, a phased summary in June
- Latex error: missing delimiter (. Inserted) {\xi \left( {p,{p_q}} \right)} \right|}}
- MPLS: multi protocol label switching
- Work order management system OTRs
- Virtual machine configuration network
- [Galaxy Kirin V10] [server] soft RAID configuration
- Sword finger offer 05 (implemented in C language)
- Development guidance document of CMDB
- Dos:disk operating system, including core startup program and command program
- Quick sort (C language)
猜你喜欢
leetcode1-3
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
Rhcsa day 9
The future education examination system cannot answer questions, and there is no response after clicking on the options, and the answers will not be recorded
Rhcsa12
Safety reinforcement learning based on linear function approximation safe RL with linear function approximation translation 1
What is an excellent architect in my heart?
Development guidance document of CMDB
[Galaxy Kirin V10] [server] NFS setup
BGP advanced experiment
随机推荐
system design
Number of relationship models
六月份阶段性大总结之Doris/Clickhouse/Hudi一网打尽
[Galaxy Kirin V10] [server] set time synchronization of intranet server
[Galaxy Kirin V10] [server] FTP introduction and common scenario construction
Jianzhi offer 04 (implemented in C language)
Communication layer of csframework
Introduction to extensible system architecture
If you don't know these four caching modes, dare you say you understand caching?
How to quickly parse XML documents through C (in fact, other languages also have corresponding interfaces or libraries to call)
Write a program that uses pointers to set all elements of an int array to 4.18: 0.
VLAN part of switching technology
MFC document view framework (relationship between classes)
Legion is a network penetration tool
Rhsca day 11 operation
Rhcsa day 9
有老师知道 继承RichSourceFunction自定义读mysql怎么做增量吗?
Recursive method to achieve full permutation (C language)
Rhcsa operation
183 sets of free resume templates to help everyone find a good job