基于Guns7开源框架,整合DingTalkSDK扫码登入系统功能实现
一、写在前面:
博主使用Gun7版本开源地址:https://www.stylefeng.top/contents/beetl/
钉钉开放平台:https://open-dev.dingtalk.com/apiExplorer
钉钉平台第三方扫码登陆文档(博主看这个写的):https://open.dingtalk.com/document/orgapp-server/scan-qr-code-to-log-on-to-third-party-websites
二、开发步骤:
登陆页面搭建钉钉二维码容器
1.在原有的 login.html 增加一个from标签,增加一个div标签命名id,并默认样式为display:none
<form class="layui-form" style="display: none" id="dingtalkForm">
<h2 style="margin-left: 15%">钉钉扫码登录</h2>
<div id="login_container"></div>
</form>
构建钉钉登陆二维码
1.在页面中引入ddLogin.js
<script src="https://g.alicdn.com/dingding/dinglogin/0.0.5/ddLogin.js"></script>
2.初始化钉钉扫描的二维码
钉钉内网穿透文件地址:https://github.com/open-dingtalk/pierced
//url:钉钉系统登陆页的访问路径(项目需要部署在服务器上,项目部署在本地需作内网穿透)
var url = encodeURIComponent('http://myproject.vaiwan.com/dingtalk/login');
//下面路径中需要替换你自己的 appid参数
var goto = encodeURIComponent('https://oapi.dingtalk.com/connect/oauth2/sns_authorize?appid=appid&response_type=code&scope=snsapi_login&state=STATE&redirect_uri='+url);
var obj = DDLogin({
id:"login_container",//这里需要你在自己的页面定义一个HTML标签并设置id,例如<div id="login_container"></div>或<span id="login_container"></span>
goto: goto,
style: "border:none;background-color:#FFFFFF;",
width : "312", //二维码的宽高
height: "350"
});
var handleMessage = function (event) {
var origin = event.origin;
if( origin == "https://login.dingtalk.com" ) { //判断是否来自ddLogin扫码事件。
var loginTmpCode = event.data;
//获取到loginTmpCode后就可以在这里构造跳转链接进行跳转了
//appid 替换你自己的appid
//redirect_uri 参数是你部署或者穿透到外网的域名
window.location.href="https://oapi.dingtalk.com/connect/oauth2/sns_authorize?appid=appid&response_type=code&scope=snsapi_login&state=STATE&redirect_uri=http://myproject.vaiwan.com/dingtalk/login&loginTmpCode="+loginTmpCode;
}
};
if (typeof window.addEventListener != 'undefined') {
window.addEventListener('message', handleMessage, false);
} else if (typeof window.attachEvent != 'undefined') {
window.attachEvent('onmessage', handleMessage);
}
3.账户密码登陆与钉钉扫码登陆切换
//这里只需要切换两个div显示隐藏就好了比较原始,也没做动画
//账户密码登录
$('#PcControl').click(function(){
$("#PcControl").hide();
$("#dingtalkForm").hide();
$("#upwForm").show();
$("#codeControl").show();
});
//钉钉扫码登录
$('#codeControl').click(function(){
$("#upwForm").hide();
$("#codeControl").hide();
$("#PcControl").show();
$("#dingtalkForm").show();
});
4.后台编写钉钉控制器
注意:这里需要将访问的路径权限过滤排除掉,不然访问会被拦截
获取到钉钉扫码的code可以直接查出用户名,我这里做了简单的判断,拿上用户名去数据库查询,有便算登陆成功。注意:账号唯一应该使用手机号比较好。
/**
* 页面扫码登录
* @return
* @throws Exception
*/
@GetResource(name = "钉钉登录", path = "/dingtalk/login")
public String login(@RequestParam(value = "code")String code, Model model) throws Exception{
String userName = DingTalkUtil.getUserInfoByQR(code);
QueryWrapper<SysUser> sysUserQueryWrapper = new QueryWrapper<>();
sysUserQueryWrapper.eq("real_name",userName);
SysUser sysUser = sysUserService.getOne(sysUserQueryWrapper);
if(sysUser!=null){
LoginResponse loginResponse = authServiceApi.loginWithUserName(sysUser.getAccount());
addLoginCookie(loginResponse.getToken());
return PREFIX+"/jump.html";
}else{
return PREFIX+"/noacc.html";
}
}
getUserInfoByQR(String code )方法
/**
* 扫码登录
* @param code
* @return
* @throws Exception
* URLConstant.URL_GET_USER_INFO "https://oapi.dingtalk.com/sns/getuserinfo_bycode"
* URLConstant.URL_USER_BYUNIONID "https://oapi.dingtalk.com/topapi/user/getbyunionid"
*/
public static String getUserInfoByQR(String code) throws Exception{
DefaultDingTalkClient client2 = new DefaultDingTalkClient(URLConstant.URL_GET_USER_INFO);
OapiSnsGetuserinfoBycodeRequest reqBycodeRequest = new OapiSnsGetuserinfoBycodeRequest();
// 通过扫描二维码,跳转指定的redirect_uri后,向url中追加的code临时授权码
reqBycodeRequest.setTmpAuthCode(code);
OapiSnsGetuserinfoBycodeResponse bycodeResponse = client2.execute(reqBycodeRequest, Constant.APP_KEY,Constant.APP_SECRET);
// 根据unionid获取userid
String unionid = bycodeResponse.getUserInfo().getUnionid();
DingTalkClient clientDingTalkClient = new DefaultDingTalkClient(URLConstant.URL_USER_BYUNIONID);
OapiUserGetbyunionidRequest reqGetbyunionidRequest = new OapiUserGetbyunionidRequest();
reqGetbyunionidRequest.setUnionid(unionid);
OapiUserGetbyunionidResponse oapiUserGetbyunionidResponse = clientDingTalkClient.execute(reqGetbyunionidRequest,AccessTokenUtil.getToken());
// 根据userId获取用户信息
String userId = oapiUserGetbyunionidResponse.getResult().getUserid();
return getUserName(AccessTokenUtil.getToken(), userId);
}
getUserName(String accessToken, String userId) 方法
response中可以获取用户的基本信息,其中包括姓名&手机号
发布完我调整一下,用手机号作验证。
/**
* 私有方法,根据钉钉用户id 获取用户姓名
* @param accessToken
* @param userId
* @return
* URLConstant.URL_USER_GET "https://oapi.dingtalk.com/user/get"
*/
private static String getUserName(String accessToken, String userId) {
try {
DingTalkClient client = new DefaultDingTalkClient(URLConstant.URL_USER_GET);
OapiUserGetRequest request = new OapiUserGetRequest();
request.setUserid(userId);
request.setHttpMethod("GET");
OapiUserGetResponse response = client.execute(request, accessToken);
return response.getName();
} catch (ApiException e) {
e.printStackTrace();
return null;
}
}
至此功能完成。
小伙伴们一件三连吧!