webSocket實現掃碼登入
阿新 • • 發佈:2021-06-29
基於WebSocket實現簡單的掃碼登入
WebSocket是一種在單個TCP連線上進行全雙工通訊的協議。 WebSocket通訊協議於2011年被IETF定為標準RFC 6455,並由RFC7936補充規範。WebSocket API也被W3C定為標準。 WebSocket使得客戶端和伺服器之間的資料交換變得更加簡單,允許服務端主動向客戶端推送資料。在WebSocket API中,瀏覽器和伺服器只需要完成一次握手,兩者之間就直接可以建立永續性的連線,並進行雙向資料傳輸。
因為是第一次接觸,所以畫了一個簡單的流程圖
上程式碼
- 導包
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-websocket</artifactId> </dependency>
2.開啟spring支援
@Configuration public class WebSocketConfig { @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } }
@Component @ServerEndpoint(value = "/websocket") public class WebSocketWxLogin { //用來存放每個連線對應的WebSocketWxLogin物件,適用於同時與多個客戶端通訊 public static CopyOnWriteArraySetwebSocketSet = new CopyOnWriteArraySet (); //其中Key為連線唯一標識 public static ConcurrentHashMap webSocketMap = new ConcurrentHashMap (); private Session session; /** * 建立連線成功呼叫的方法 */ @OnOpen public void onOpen(Session session)throws IOException { this.session = session; //我這裡使用時間戳作為唯一id long l = System.currentTimeMillis(); String str = l+""; String sessionId = TripleDES.encode(str); webSocketSet.add(this); webSocketMap.put(sessionId,this); Map map = new HashMap(); map.put("code",400); map.put("msg","獲取成功!"); map.put("sessionId",sessionId); String s = JSONObject.toJSONString(map); session.getBasicRemote().sendText(s); } /** * 關閉連線呼叫的方法 */ @OnClose public void onClose(Session closeSession){ System.out.println(session); webSocketMap.remove(session); webSocketSet.remove(this); } /** * 向用戶推送訊息 */ public void sendMessage(String message) throws IOException { this.session.getBasicRemote().sendText(message); } }
3.登入介面
@PostMapping("login") @ApiOperation(value = "掃碼登入", notes = "掃碼登入") private Object login(String sessionId) { Assert.notNull(sessionId,"缺少引數"); WebSocketWxLogin o1 = WebSocketWxLogin.webSocketMap.get(sessionId); Assert.notNull(o1,"二維碼已過期"); Assert.notNull(getUser(),"未登入!"); String token = getRequest().getSession().getId(); redisUtil.set(String.format(RedisParam.KEY_MOBILE_USER_LOGIN, token), getUser(), RedisParam.LOGIN_EXPIRE_TIME); Map map = new HashMap(); map.put("code",401); map.put("msg","登入成功!"); map.put("token",token); String s = JSONObject.toJSONString(map); try { o1.sendLogin(s); }catch (Exception e){ return RespEntity.errorResp("登入失敗!"); } return RespEntity.successResp("登入成功!",token); }
4.JS程式碼
<script type="text/javascript"> var websocket = new WebSocket("ws:127.0.0.1:8009/websocket"); //ws:伺服器+埠/後端的端點 //接收到訊息的回撥方法 websocket.onmessage = function (event) { console.log(event.data); } //連線關閉的回撥方法 websocket.onclose = function () { console.log("WebSocket連線關閉"); } //監聽視窗關閉事件,當視窗關閉時,主動去關閉websocket連線,確保斷開時關閉連線 window.onbeforeunload = function () { closeSocket(); } //關閉WebSocket連線 function closeSocket() { websocket.close(); } </script>
如果線上使用了nginx,則需要在nginx配置檔案裡新增
map $http_upgrade $connection_upgrade { default upgrade; '' close; }
這個寫在server裡
location /ws/ { proxy_pass http://127.0.0.1:8008/; proxy_read_timeout 600; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "Upgrade"; proxy_set_header X-real-ip $remote_addr; proxy_set_header X-Forwarded-For $remote_addr; }
第一次在部落格園寫隨寫,如有問題還望指正