当前位置:网站首页>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,>
边栏推荐
- 基于线性函数近似的安全强化学习 Safe RL with Linear Function Approximation 翻译 2
- On binary tree (C language)
- Two way process republication + routing policy
- Basic principle of servlet and application of common API methods
- Use the data to tell you where is the most difficult province for the college entrance examination!
- Software sharing: the best PDF document conversion tool and PDF Suite Enterprise version sharing | with sharing
- How do microservices aggregate API documents? This wave of show~
- Reprint: summation formula of proportional series and its derivation process
- How to quickly parse XML documents through C (in fact, other languages also have corresponding interfaces or libraries to call)
- [machine] [server] Taishan 200
猜你喜欢
OSPF comprehensive experiment
RHCE - day one
Reprint: summation formula of proportional series and its derivation process
[Galaxy Kirin V10] [desktop and server] FRP intranet penetration
Recursion and divide and conquer strategy
Rhcsa learning practice
What is an excellent architect in my heart?
BGP advanced experiment
[Galaxy Kirin V10] [desktop] printer
【Day1】 deep-learning-basics
随机推荐
Introduction to extensible system architecture
On binary tree (C language)
For programmers, if it hurts the most...
/*Write a loop to output the elements of the list container in reverse order*/
Rhcsa learning practice
Quick sort (C language)
Write a program to define an array with 10 int elements, and take its position in the array as the initial value of each element.
[Galaxy Kirin V10] [server] FTP introduction and common scenario construction
Two way process republication + routing policy
Whether a person is reliable or not, closed loop is very important
Rhcsa - day 13
Recursive method to achieve full permutation (C language)
Development guidance document of CMDB
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
Si vous ne connaissez pas ces quatre modes de mise en cache, vous osez dire que vous connaissez la mise en cache?
Differences among opencv versions
VLAN part of switching technology
Network disk installation
/*The rewriter outputs the contents of the IA array. It is required that the type defined by typedef cannot be used in the outer loop*/
Button wizard business running learning - commodity quantity, price reminder, judgment Backpack