webSocket實現掃碼登錄


基於WebSocket實現簡單的掃碼登錄

      WebSocket是一種在單個TCP連接上進行全雙工通信的協議。
      WebSocket通信協議於2011年被IETF定為標准RFC 6455,並由RFC7936補充規范。WebSocket API也被W3C定為標准。
      WebSocket使得客戶端和服務器之間的數據交換變得更加簡單,允許服務端主動向客戶端推送數據。在WebSocket API中,瀏覽器和服務器只需要完成一次握手,兩者之間就直接可以創建持久性的連接,並進行雙向數據傳輸。


因為是第一次接觸,所以畫了一個簡單的流程圖

上代碼

  1. 導包
       <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 CopyOnWriteArraySet
 
 
 
         
          
  
  
   webSocketSet = 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;
     }


第一次在博客園寫隨寫,如有問題還望指正


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM