失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > java实现简单扫码登录功能(模仿微信网页版扫码)

java实现简单扫码登录功能(模仿微信网页版扫码)

时间:2020-01-04 06:59:57

相关推荐

java实现简单扫码登录功能(模仿微信网页版扫码)

java实现简单扫码登录功能

模仿微信pc网页版扫码登录使用js代码生成qrcode二维码减轻服务器压力js循环请求服务端,判断是否qrcode被扫二维码超时失效功能二维码被扫成功登录,服务端产生sessionId,传到页面使用js保存cookie多线程

生成qrcode相关js jquery.qrcode.js

-

代码

页面div

<div class="pc_qr_code"><input type="hidden" id="uuid" value="${uuid }"/></div><div id="result">请使用手机扫码</div>1234567

主要js

//生成二维码!function(){var uuid = $("#uuid").val();var content;content = "..........do?uuid="+uuid;//console.dir(content);$('.pc_qr_code').qrcode({render:"canvas",width:200,height:200,correctLevel:0,text:content,background:"#ffffff",foreground:"black",src:"/logo.png"}); setCookie("sid", 123, -1*60*60*1000);keepPool();//自动循环调用}();function keepPool(){var uuid = $("#uuid").val();$.get(ctx+"/web/login/pool.do",{uuid:uuid,},function(msg){//如果放入一个不存在的网址怎么办?//console.log(msg);if(msg.successFlag == '1'){$("#result").html("扫码成功");setCookie(ame, msg.data.cvalue, 3*60*60*1000);//alert("将跳转...");window.location.href = ctx +"/webstage/login/success.do";}else if(msg.successFlag == '0'){$("#result").html("该二维码已经失效,请重新获取");}else{keepPool();}}); }//设置cookiefunction setCookie(cname, cvalue, expireTime) {var d = new Date();d.setTime(d.getTime() + expireTime);//设置过期时间var expires = "expires="+d.toUTCString();var path = "path=/"document.cookie = cname + "=" + cvalue + "; " + expires + "; " + path;}1234567891011121314151617181922232425262728293031323334353637383940414243444546

java代码

//二维码首页public String index() {try {uuid = UUID.randomUUID().toString();super.getRequest().setAttribute("uuid", uuid);ScanPool pool = new ScanPool();pool.setCreateTime(System.currentTimeMillis());Map<String, ScanPool> map = new HashMap<String, ScanPool>(1);map.put(uuid, pool);PoolCache.cacheMap.put(uuid, pool);pool = null;} catch (Exception e) {monLog.error("pc生成二维码登录", e);}return "index";}//判断二维码是否被扫描public void pool() {DataResultInfo result = null;System.out.println("检测[ " + uuid + " ]是否登录");ScanPool pool = null; if(MapUtils.isNotEmpty(PoolCache.cacheMap)) pool = PoolCache.cacheMap.get(uuid);try {if (pool == null) {// 扫码超时,进线程休眠result = DataResultInfo.getInstance().failure();result.setSuccessFlag(CommonConstant.Zero);result.setExtension(CommonConstant.Zero, "该二维码已经失效,请重新获取");Thread.sleep(10 * 1000L);} else {// 使用计时器,固定时间后不再等待扫描结果--防止页面访问超时new Thread(new ScanCounter(uuid, pool)).start();boolean scanFlag = pool.getScanStatus(); //这里得到的ScanPool(时间靠前)和用户使用手机扫码后得到的不是一个,用户扫码后又重新更新了ScanPool对象,并重新放入了redis中,,所以这里要等待上面的计时器走完,才能获得最新的ScanPoolif (scanFlag) {result = DataResultInfo.getSuccess();// 根据uuid从redis中获取pool对象,得到对应的sessionId,返给页面,通过js存cookie中JSONObject jsonObj = new JSONObject();jsonObj.put("cname", CookieConstant.SESSION_KEY);jsonObj.put("cvalue", pool.getSession());result.setData(jsonObj);} else {result = DataResultInfo.getInstance().failure();result.setMessage("等待扫描");}}} catch (Exception e) {e.printStackTrace();}sendJsonMessage(result);}//手机扫码接口(以id和token作为用户身份登录)public String phoneScanLogin() {DataResultInfo result = null;ScanPool pool = null; if(MapUtils.isNotEmpty(PoolCache.cacheMap)) pool = PoolCache.cacheMap.get(uuid);try {if (pool == null) {result = DataResultInfo.getInstance().failure();result.setMessage("该二维码已经失效,请重新获取");} else {if (StringUtils.isNotEmpty(id) && StringUtils.isNotEmpty(token)) {//根据id和token查询后台,获取用户信息userBeanString redisToken = redisUtil.getRedis(RedisKeyConstant.APP_TOKEN+userId);if(redisToken != null && redisToken.equals(token)){UserBean userBean = userService.findByUserId(Long.valueOf(userId));if (userBean != null) {String sessionId = SessionConstant.SESSION_ID_PRE+ FormatUtils.password(userBean.getId().toString());Map<String, String> cookieSession = new HashMap<String, String>();cookieSession.put(CookieConstant.SESSION_KEY, sessionId);// WrCookie.writeCookie(getResponse(),cookieSession);// 添加用户信息到redisboolean re = redisUtil.addUserInfo( RedisKeyConstant.SESSION + sessionId, BeanUtils.toBean(userBean, UserInfo.class));getSession().setAttribute( SessionConstant.USER_INFO_WEB, BeanUtils.toBean(userBean, UserInfo.class));getSession().setAttribute( DomainConstant.USER_CENTER_KEY, DomainConstant.USER_CENTER);pool.setSession(sessionId);pool.scanSuccess();}else{result = DataResultInfo.getInstance().failure();result.setMessage("用户信息获取异常!请稍后再试");}} else {result = DataResultInfo.getInstance().failure();result.setExtension("11", "用户身份信息失效,请重新登录!");}} else {result = DataResultInfo.getInstance().failure();result.setMessage("请求参数有误!");return "error";}// 不能清除,否则conn方法得不到pool对象,不会进入线程休眠// System.out.println("清除扫描过的uuid");//PoolCache.cacheMap.remove(uuid);}} catch (Exception e) {monLog.error("手机扫码 后访问 异常", e);}sendJsonMessage(result);return null;}//扫码成功跳转页public String success() {String sessionId = WrCookie.getCookie(super.getRequest(), CookieConstant.SESSION_KEY);UserInfo userInfo = redisUtil.getUserInfo(RedisKeyConstant.SESSION + sessionId);super.getRequest().setAttribute(SessionConstant.USER_INFO_WEB, userInfo);return SUCCESS;}//线程判断二维码是否超时class ScanCounter implements Runnable {public Long timeout = 30 * 1000L; //超时时长// 传入的对象private String uuid;private ScanPool scanPool;public ScanCounter(String p, ScanPool scanPool) {uuid = p;this.scanPool = scanPool;}@Overridepublic void run() {try {Thread.sleep(timeout);} catch (InterruptedException e) {e.printStackTrace();}notifyPool(uuid, scanPool);}public synchronized void notifyPool(String uuid, ScanPool scanPool) {if (scanPool != null) scanPool.notifyPool();}public String getUuid() {return uuid;}public void setUuid(String uuid) {this.uuid = uuid;}public ScanPool getScanPool() {return scanPool;}public void setScanPool(ScanPool scanPool) {this.scanPool = scanPool;}}1234567891011121314151617181922232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811911122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166

ScanPool.java(存放uuid的bean)

public class ScanPool implements Serializable{/*** @Fields serialVersionUID : TODO(用一句话描述这个变量表示什么) */private static final long serialVersionUID = -9117921544228636689L;private Object session ;//创建时间 private Long createTime = System.currentTimeMillis(); //登录状态 private boolean scanFlag = false; public boolean isScan(){ return scanFlag; } public void setScan(boolean scanFlag){ this.scanFlag = scanFlag; } /** * 获取扫描状态,如果还没有扫描,则等待固定秒数 * @param wiatSecond 需要等待的秒数 * @return */ public synchronized boolean getScanStatus(){ try { if(!isScan()){ //如果还未扫描,则等待 this.wait(); } if (isScan()) { System.err.println("手机扫描完成设置getScanStatus..true...........");return true; } } catch (InterruptedException e) { e.printStackTrace(); } return false; } /** * 扫码之后设置扫码状态 * @param token * @param id */ public synchronized void scanSuccess(){ try { System.err.println("手机扫描完成setScan(true)....同时释放notifyAll(手机扫码时,根据uuid获得的scanpool对象)");setScan(true); this.notifyAll(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } public synchronized void notifyPool(){ try { this.notifyAll(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } /***********************************************/public Long getCreateTime() { return createTime; } public void setCreateTime(Long createTime) { this.createTime = createTime; }public Object getSession() {return session;}public void setSession(Object session) {this.session = session;}}123456789101112131415161718192223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495

PoolCache.java(定时清理二维码uuid的类)

public class PoolCache {// 缓存超时时间 10分钟private static Long timeOutSecond = 10 * 60 * 1000L;// 每半小时清理一次缓存private static Long cleanIntervalSecond = 30 * 60 * 1000L;//此map在多线程中会出现 ConcurrentModificationException//public static Map<String, ScanPool> cacheMap = new HashMap<String, ScanPool>();//List//public static CopyOnWriteArrayList<Map<String, ScanPool>> copyOnWriteArrayList = new CopyOnWriteArrayList<Map<String,ScanPool>>();//专用于高并发的map类-----Map的并发处理(ConcurrentHashMap)public static ConcurrentHashMap<String, ScanPool> cacheMap = new ConcurrentHashMap<String, ScanPool>();static {new Thread(new Runnable() {@Overridepublic void run() {while (true) {try {Thread.sleep(cleanIntervalSecond);} catch (InterruptedException e) {e.printStackTrace();}clean();}}public void clean() {try {/*if (copyOnWriteArrayList.size() > 0) {Iterator<Map<String, ScanPool>> iterator = copyOnWriteArrayList.iterator();while (iterator.hasNext()) {Map<String, ScanPool> map = iterator.next();Iterator<String> it2 = map.keySet().iterator();while (it2.hasNext()){String uuid = it2.next();ScanPool pool = map.get(uuid);if (System.currentTimeMillis() - pool.getCreateTime() > timeOutSecond ) {copyOnWriteArrayList.remove(map);System.err.println("失效了: .. "+ uuid);System.err.println("失效了: .. "+ map);break;}}}}*/if (cacheMap.keySet().size() > 0) {Iterator<String> iterator = cacheMap.keySet().iterator();while (iterator.hasNext()) {String key = iterator.next();ScanPool pool = cacheMap.get(key);if (System.currentTimeMillis() - pool.getCreateTime() > timeOutSecond ) {cacheMap.remove(key);}}}} catch (Exception e) {monLog.error("定时清理uuid异常", e);}}}).start();}}12345678910111213141516171819222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172

扫码流程 图:

流程图:

使用线程实时监听扫码状态;

用户扫描二维码相当于使用 用户名密码 在网页端登录,需要存浏览器cookie

,而用户通过使用手机扫码,直接请求服务器,登陆成功,js中得到用户数据及cookie,把cookie返给页面,再通过js存入cookie中,

本文借鉴与此大神的代码,稍作了修改,参考 扫二维码自动跳转(java),

++++++++demo源码地址:

**应大佬们的要求

附上github源码地址供大家参考*:/luuuuuuuuu/qrscan

如果觉得《java实现简单扫码登录功能(模仿微信网页版扫码)》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。