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