# 实现PC登录页扫描登录功能如何实现

# 参照版本

V8.2SP1

# 需求

项目上需要复用PC登录页的“微信/M3扫码登录”功能,期望把二维码放在客户第三方系统页面展示,供大家扫描登录OA。需要知道这个二维码生成接口及实现。

1702544932371.png

# 标准实现分析

要进行定制开发,必须了解免登录的实现原理:

# 生成二维码

前端开发,通过F12查找二维码元素,看到这是一个canvas,基于html5渲染。这里看应该是前端js进行的渲染,可以找特征值id="qrcode1",一般都是通过dom操作渲染。

1702545111152.png

全局搜索qrcode1关键字,可以找到渲染二维码的代码位置:

1702545393516.png

总结:渲染二维码逻辑为前端显示:

// 一、引入JQuery组件及jquery.qrcode.js(使用别的QR渲染组件也可以)
// 二、实现如下前端代码,随后Jquery("#qrcode1 .qrcode")这个Dom下就有二维码了
var date = new Date();
var dateNumber = date.getTime();

// 记住这个random,这是关键变量
var random="seeyon-" + Math.uuid() + "-" + dateNumber;
var qrcodeRandom = "https://weixin.seeyon.com/mobilehelp.jsp?random=" + random;
$("#random").val(random);

//canvas方式进行图片渲染
$("#qrcode1 .qrcode").empty();
$("#qrcode1 .qrcode").qrcode({
	render: isIE8?"table":"canvas", //canvas方式
	width: adjustWidth, //宽度
	height: adjustHeight, //高度
	text: utf16to8(qrcodeRandom) //任意内容
});

// 记住这行代码:每隔1秒向服务器确认是否免登录
setInterval("intervalLogin()", 1000);

# 扫码记录免登

M3或企业微信扫描二维码,能读取到二维码中的random信息,这个random是当前用户很重要的记录信息。

随后M3或企业微信调用OA的免登录接口,记录当前用户进行了免登录:

  • LoginResource#loginForWechat(random) 企业微信免登
  • LoginResource#loginForM3(random) M3免登

# PC自动登录

上一步是M3通知OA服务器:用户进行了免登,OA服务器记录了免登状态。但此时PC二维码界面是不知道用户免登的,需要有一个动作确认是否有免登状态,如果确认OK,则自动登录,这块实现逻辑就在前端的intervalLogin()方法里:

// 前面二维码渲染处进行了每隔1秒轮询判定是否免登的实现
setInterval("intervalLogin()", 1000);

//轮询请求,防止后台阻塞
function intervalLogin(){
	if(sendFlag){
		sendFlag = false;
		loginForWechat();
	}
}

// 真正的轮询方法
function loginForWechat(){
	// 从页面获取random信息
	var random = $("#random").val();
    $.ajax({
        async : true,
        type: "GET",
        url: _ctxPath+"/main.do?method=login4QrCode&random=" + random,  //这个请求的意思是判断当前是否进行了免登录操作,如果没有则返回loginError字符串,如果有则返免登录的人员loginName登录名
        dataType : 'text',
        success : function(data) {
            if(data != "loginError" || data == null){
				// 如果确认进行了免登录,则模拟登录按钮直接登录
                $("#login_username").val(data);
				// 这个执行的button上面的点击事件,实际触发的是onclick方法,具体可自行查看前端代码
                $("#login_button").click();
            } else {
                sendFlag = true;
            }
        },
        error : function(XMLHttpRequest, textStatus, errorThrown) {
            alert($.i18n('login.tip.failure'));
        }
    });
}

依据源码分析,在判定免登录成功后会执行$("#login_button").click();方法,根据方法溯源,可以看到调用链:

$("#login_button").click();
↓
loginButtonOnClickHandler();
↓
doLoginSubmit()
↓
$("#submit_button").click();
↓
<form method="post" action="${path}/main.do?method=login" id="login_form" name="loginform">
	<input id="submit_button" type="submit" style="display: none" value="" />
</form>
↓
MainController#login();
↓
QrCodeLoginAuthentication#authenticate(); //免登录认证器

# 实现原理小结

基于以上分析,扫描的完整逻辑为:

1、在PC登录页渲染显示出免登录二维码

2、M3、企业微信APP扫描二维码后,在APP端远程调用OA服务器通知该用户进行了免登录

3、在PC登录页每隔1秒询问OA:用户是否进行了免登录。如果OA服务器返回免登录动作,则PC执行form提交操作登录。

# 第三方页面定制开发解决方案

1、复制一份seeyon\main\login\default\login.jsp登录页的实现源码,把所有能看到的元素全部隐藏起来,只渲染一个二维码,让人感觉这个页面就一个二维码:

  • 将背景色、背景图全部干掉
  • 将input、button等能看到的Dom元素全部隐藏起来,不要删除
  • 将form标签增加target=_blank属性,表示打开新窗口
  • 实现免登录二维码渲染操作,保障能看到二维码
-- 增加target="_blank"属性
<form method="post" action="${path}/main.do?method=login" id="login_form" name="loginform" target="_blank">
	<input id="submit_button" type="submit" style="display: none" value="" />
</form>

2、第三方页面Iframe的形式访问复制的那份JSP页面,此时第三方页面就只能看到二维码了

3、随后用M3或企业微信扫描二维码,按照原来的业务逻辑会执行submit提交操作,登录打开OA页面

注1:为什么要拷贝一份login.jsp而不是新建一个空白html页面,只引入二维码?

答:因为自动跳转使用了login.jsp里面的很多业务逻辑,包括dom的操作,当然如果你技术能力强,也可以自己实现免登录

编撰人:het