多平台统一管理软件接口,如何实现多平台统一管理软件接口
891
2023-01-07
详解java实现简单扫码登录功能(模仿微信网页版扫码)
java实现简单扫码登录功能
模仿微信pc网页版扫码登录
使用js代码生成qrcode二维码减轻服务器压力
js循环请求服务端,判断是否qrcode被扫
二维码超时失效功能
二维码被扫成功登录,服务端产生sessionId,传到页面使用js保存cookie
多线程
生成qrcode相关js jquery.qrcode.js
代码
页面div
主要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:"/UwuIjSGAfElogo.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(msg.data.cname, 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();
}
});
}
//设置cookie
function 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;
}
java代码
//二维码首页
public String index() {
try {
uuid = UUID.randomUUID().toString();
super.getRequest().setAttribute("uuid", uuid);
ScanPool pool = new ScanPool();
pool.setCreateTime(System.currentTimeMillis());
Map
map.put(uuid, pool);
PoolCache.cacheMap.put(uuid, pool);
pool = null;
} catch (Exception e) {
Log4jUtil.CommonLog.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中,,所以这里要等待上面的计时器走完,才能获得最新的ScanPool
if (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查询后台,获取用户信息userBean
String 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
cookieSession
.put(CookieConstant.SESSION_KEY, sessionId);
// WrCookie.writeCookie(getResponse(),cookieSession);
// 添加用户信息到redis
boolean re = redisUtil.addUserInfo( RedisKeyConstant.SESSION + sessihttp://onId, 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) {
Log4jUtil.CommonLog.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;
}
@Override
public 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;
}
}
ScanPool.java(存放uuid的bean)
http://
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;
}
}
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
//List
//public static CopyOnWriteArrayList
//专用于高并发的map类-----Map的并发处理(ConcurrentHashMap)
public static ConcurrentHashMap
static {
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
Thread.sleep(cleanIntervalSecond);
} catch (InterruptedException e) {
e.printStackTrace();
}
clean();
}
}
public void clean() {
try {
/*if (copyOnWriteArrayList.size() > 0) {
Iterator
while (iterator.hasNext()) {
Map
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
while (iterator.hasNext()) {
String key = iterator.next();
ScanPool pool = cacheMap.get(key);
if (System.currentTimeMillis() - pool.getCreateTime() > timeOutSecond ) {
cacheMap.remove(key);
}
}
}
} catch (Exception e) {
Log4jUtil.CommonLog.error("定时清理uuid异常", e);
}
}
}).start();
}
}
扫码流程图:
流程图:
使用线程实时监听扫码状态;
用户扫描二维码相当于使用 用户名密码 在网页端登录,需要存浏览器cookie
,而用户通过使用手机扫码,直接请求服务器,登陆成功,js中得到用户数据及cookie,把cookie返给页面,再通过js存入cookie中
参考https://jb51.net/article/160745.htm
**应大佬们的要求
附上github源码地址供大家参考*: https://github.com/luuuuuuuuu/qrscan
以上所述是给大家介绍的java实现简单扫码登录功能(模仿微信网页版扫码)详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,会及时回复大家的。在此也非常感谢大家对我们网站的支持!
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~