1. 程式人生 > 其它 >webSocket實現掃碼登入

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;
     }


第一次在部落格園寫隨寫,如有問題還望指正