钉钉微应用的免登录(前后端)
最近做了个钉钉企业内部微应用的项目。记录下自己的心得。
首先根据官方文档明白免登流程
但是,最近更新的开发者平台,已经不在提供corpSecret了,所以获取获取access_token就要获取获取appKey和appSecret,官方文档写的很清楚,获取access_token如下图所示:
封装一个AuthHelper 如下:
/**
1.获取accessToken
2.获取jsapi中的ticket
3.生成jsapiz中的鉴权sign
4.根据传入的临时code获取用户的基本信息,入userinfo
5.(ISV版本)根据userid获取详细用户信息
@author lnexin
*/
public class AuthHelper {// 钉钉api相关
static String TOKEN_URL = “https://oapi.dingtalk.com/gettoken”;
static String TICKET_URL = “https://oapi.dingtalk.com/get_jsapi_ticket”;
static String USER_INFO_URL = “https://oapi.dingtalk.com/user/getuserinfo”;
static String USER_ALL_URL = “https://oapi.dingtalk.com/user/get”;// 调整到1小时50分钟
public static final long cacheTime = 1000 * 60 * 55 * 2;private static String ACCESS_TOKEN = null;
private static String JSAPI_TICKET = null;
private static long LAST_TIME = 0;/**
@param appKey
@param appSecret
@return 与钉钉服务器请求生成的accessToken
*/
public static String getAccessToken(String appKey, String appSecret) {
long curTime = System.currentTimeMillis();
long differ = curTime - LAST_TIME;if (ACCESS_TOKEN != null && differ < cacheTime)
return ACCESS_TOKEN;ACCESS_TOKEN = requestAccessToken(appKey, appSecret);
LAST_TIME = curTime;return ACCESS_TOKEN;
}
/**
@param accessToken
@return 一个用于js鉴权的ticket
*/
public static String getJsapiTicket(String accessToken) {
long curTime = System.currentTimeMillis();
long differ = curTime - LAST_TIME;if (JSAPI_TICKET != null && differ < cacheTime) {
return JSAPI_TICKET;
}
JSAPI_TICKET = requestJsapiTicket(accessToken);
return JSAPI_TICKET;
}
/**
- 根据传入的相关参数生成sign
- @param ticket
- @param nonceStr
- @param timeStamp
- @param url
- @return
*/
public static String sign(String ticket, String nonceStr, long timeStamp, String url) {
StringBuffer plain = new StringBuffer();
plain.append(“jsapi_ticket=”).append(ticket);
plain.append("&noncestr=").append(nonceStr);
plain.append("×tamp=").append(String.valueOf(timeStamp));
plain.append("&url=").append(url);
MessageDigest sha;
try {
sha = MessageDigest.getInstance(“SHA-1”);
sha.reset();
sha.update(plain.toString().getBytes(“UTF-8”));
return bytesToHex(sha.digest());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
private static String requestAccessToken(String appKey, String appSecret) {
StringBuffer url = new StringBuffer(TOKEN_URL);
url.append("?appkey=").append(appKey);
url.append("&appsecret=").append(appSecret);
String result = null;
try {
result = HttpHelper.sendGet(url.toString());
} catch (IOException e) {
result = ReturnUtil.result("-1",
“请求accessTokenc出错!appKey:” + appKey + “,appSecret:” + appSecret + “异常信息:” + e);
}
System.out.println(“appKey:” + appKey + “,appSecret:” + appSecret + “,result:” + result);
return JsonUtil.getJsonNode(result).get(“access_token”).asText();
}private static String requestJsapiTicket(String accessToken) {
StringBuffer url = new StringBuffer(TICKET_URL);
url.append("?access_token=").append(accessToken);
String result = null;
try {
result = HttpHelper.sendGet(url.toString());
} catch (IOException e) {
result = ReturnUtil.result("-1", “请求JsapiTicket出错!accessToken:” + accessToken + “异常信息:” + e);
}
System.out.println(“accessToken:” + accessToken + “,result:” + result);
return JsonUtil.getJsonNode(result).get(“ticket”).asText();
}private static String bytesToHex(byte[] hash) {
Formatter formatter = new Formatter();
for (byte b : hash) {
formatter.format("%02x", b);
}
String result = formatter.toString();
formatter.close();
return result;
}/**
- 获取用户信息
- @param code
用户相应的临时code
- @param token
根据相应corpid和corpsecret生成的access_token
- @return 用户ID等相关信息
/
public static String getUserInfo(String code, String accessToken) {
StringBuffer url = new StringBuffer(USER_INFO_URL);
url.append("?access_token=").append(accessToken);
url.append("&code=").append(code);
String result = null;
try {
result = HttpHelper.sendGet(url.toString());
} catch (IOException e) {
result = ReturnUtil.result("-1", “请求User信息出错!code:” + code + “异常信息:” + e);
}
return result;
}
/* - 获取用户详细信息
- @param userid 在某个corpid下的唯一用户userid
- @param accessToken 据相应corpid和corpsecret生成的access_token
- @return
*/
public static String getUser(String userid, String accessToken) {
StringBuffer url = new StringBuffer(USER_ALL_URL);
url.append("?access_token=").append(accessToken);
url.append("&userid=").append(userid);
String result = null;
try {
result = HttpHelper.sendGet(url.toString());
} catch (IOException e) {
result = ReturnUtil.result("-1", “请求User信息出错!userid:” + userid + “异常信息:” + e);
}
return result;
}
}
前端代码如下:
钉钉微应用免登陆
<script type="text/javascript">//可以不要:01==>>startvar _config = null;$.ajax({type : "POST",url : "/config",dataType : "json",contentType : "application/json;charset=utf-8",async : false,data : "iNoI123s22",success : function(data) {// alert(data+"1、data")_config = data;// alert(_config+"2、_config")}});dd.config({agentId : _config.agentId, // 必填,微应用IDcorpId : _config.corpId,//必填,企业IDtimeStamp : _config.timestamp, // 必填,生成签名的时间戳nonceStr : _config.nonceStr, // 必填,生成签名的随机串signature : _config.sign, // 必填,签名type:0, //选填。0表示微应用的jsapi,1表示服务窗的jsapi;不填默认为0jsApiList : ['runtime.info','device.notification.prompt','biz.chat.pickConversation','device.notification.confirm','device.notification.alert','device.notification.prompt','biz.chat.open','biz.util.open','biz.user.get','biz.contact.choose','biz.telephone.call','biz.util.uploadImage','biz.ding.post']});//可以不要:01==>>end// alert("111112222");dd.error(function(r){alert("error:"+JSON.stringify(r));})dd.ready(function() {//可以不要:02==>>startdd.device.notification.showPreloader({text : "正在获取当前用户信息 ...",showIcon : true,onSuccess : function(result) {},onFail : function(err) {}});//可以不要:02==>>end//获取code//必须dd.runtime.permission.requestAuthCode({corpId : _config.corpId,onSuccess : function(result) {var code = result.code;// alert("code:"+code);$("#code").text("钉钉传向后台CODE:" + code);getUserInfo(code);},onFail : function(err) {alert('出错了, ' + err);}});});//拿到code以后剩下的都可以不要:03==>>startfunction getUserInfo(code) {$.ajax({type : "GET",url : "/userinfo?code=" + code,async : false,dataType : 'json',contentType : "application/json;charset=utf-8",success : (function(response) {$("#userid").text("获取的用户信息:" + JSON.stringify(response));dd.device.notification.hidePreloader({ //隐藏加载中onSuccess : function(result) {},onFail : function(err) {}});dd.device.notification.vibrate({//手机震动duration : 1000,onSuccess : function(result) {},onFail : function(err) {}});// 显示用户简略信息displayInfo(response);}),});}function displayInfo(response) {dd.device.notification.actionSheet({//actionSheet弹窗title : "当前用户信息",cancelButton : '关闭',//取消按钮文本otherButtons : [ 'userid: ' + response.userid, 'deviceId: ' + response.deviceId, 'is_sys: ' + response.is_sys, 'sys_level: ' + response.sys_level ],//其他按钮列表onSuccess : function(result) {$.ajax({type : "GET",url : "/user?userid=" + response.userid,async : false,dataType : 'json',contentType : "application/json;charset=utf-8",success : (function(data) {// $("#userall").text("用户信息详细:" + JSON.stringify(data));//显示用户详细信息displayall(data);alert(data.mobile);})});},onFail : function(err) {}});}function displayall(data) {var all = [];all.push("userID:" + data.userid);// all.push("openID:" + data.openid);all.push("unionid:" + data.unionid);// all.push("dingId:" + data.dingId);all.push("name:" + data.name);all.push("mobile:" + data.mobile);all.push("isBoss:" + data.isBoss);all.push("active:" + data.active);all.push("isAdmin:" + data.isAdmin);all.push("isSenior:" + data.isSenior);all.push("department:" + data.department);all.push("isLeaderInDepts:" + data.isLeaderInDepts);dd.device.notification.actionSheet({title : "详细信息", //标题cancelButton : '关闭', //取消按钮文本otherButtons : all,onSuccess : function(result) {},onFail : function(err) {}})}//拿到code以后剩下的都可以不要:03==>>start
</script>
到这里基本OK了,这两个为主要代码,还有其他的封装页面比较简单,就不贴出来了
钉钉微应用的免登录(前后端)相关推荐
- 企业内部钉钉H5微应用(免登录)Spring Boot项目实战
文章目录 前言 一.准备工作 1.开发前准备: 2.钉钉微应用的免登流程: 二.开放过程 1.新建企业号 2.创建H5微应用 3.项目编码 三.微应用配置 四.启动项目后即可访问,应用截图 总结 前言 ...
- [整站源码]thinkphp美肤微形美容仪器网站模板+前后端源码
模板介绍: 本模板自带eyoucms内核,无需再下载eyou系统,原创设计.手工书写DIV+CSS,完美兼容IE7+.Firefox.Chrome.360浏览器等:主流浏览器:结构容易优化:多终端均可 ...
- 微服务背景下的前后端分离
Web前后端分离 前后端开发模式已经成为一种"政治正确"了.当然,这种模式的确是分工明确.开发高效的.同时,与前后端分离开发模式相对应的,实际是FULL STACK--全栈开发模式 ...
- 微信第三方登录前后端分离实现思路
微信第三方登录前后端分离实现思路 前端实现 这里说一下前后端的思路,页面加载时声明一个变量state='时间戳+6位随机数', 前端路径生成二维码, 其中有个state参数需要我们传递,这个参数你传什 ...
- (详解)钉钉接口,PC端微应用,免登录及获取当前用户信息
1.用了两天的时间,一直在研究微应用的,免登录及获取用户信息这一块. 但是钉钉官网写的太繁杂了,看了一天,硬是没看明白,最后,硬着头皮,一点点查资料,借鉴别人的代码,终于 研究 出来了,为了防止 年轻 ...
- 钉钉H5微应用开发免登以及接口调试
钉钉H5微应用开发以及接口调试 企业内部应用免登 https://open.dingtalk.com/document/orgapp-server/enterprise-internal-applic ...
- 干货 | 万字长文全面解析GraphQL,携程微服务背景下的前后端数据交互方案
作者简介 古映杰,携程研发高级经理,负责前端框架和基础设施的设计.研发与维护.开源项目react-lite和react-imvc作者. 前言 随着多终端.多平台.多业务形态.多技术选型等各方面的发展, ...
- php前后端分离登录,前后端分离下如何登录
1 Web登录涉及到知识点 1.1 HTTP无状态性HTTP是无状态的,一次请求结束,连接断开,下次服务器再收到请求,它就不知道这个请求是哪个用户发过来的.当然它知道是哪个客户端地址发过来的,但是对于 ...
- 首个直播商城,拼团商城,小程序商城的微服务分布式框架,前后端分离
简介: sdb mall 项目说明 sdb是一个轻量级的在renren-fast基础上利用jfinal架构二次开发的一个极速二次开发直播,拼团商城框架,前后端分离的Java快速开发平台,C端采用微信小 ...
最新文章
- 【技术交流】让我们来谈一谈多线程和并发任务
- spingmvc-参数传递
- html表单提交前验证,jquery表单提交前实现同步验证(附代码)
- 关于Vue中计算属性computed和methods属性的区别,你了解多少呢
- java mysql nclob_java语言操作Oracle数据库中的CLOB数据类型 (转)
- 热门开源多媒体库 PJSIP 被爆5个内存损坏漏洞
- 【BZOJ4205】卡牌配对
- Google亲儿子 Nexus/Pixel 手机刷机Root之旅
- javascript将页面设为首页代码大全
- vue、四级联动(省市区街道)
- 修改网络设备在路由器中显示名称
- 计算机网络初探(ip协议)
- html5 保存 搜索历史,前端实现搜索记录功能也就是天猫app历史记录存储方便浏览 - 今天的代码你撸了嘛...
- 文件服务器属于固定资产吗,服务器内存属于固定资产吗
- linux deploy连接ssh失败,ubuntu – Jenkins发布ssh成功连接服务器但是put文件失败
- 商标权的取得方式有哪些
- 【计算机网络】虚拟IP原理
- taro 小程序编译在标签上px转rpx的api
- 为什么使用计算机辅助翻译工具中文译文,TCloud计算机辅助翻译工具
- java 视频转码 视频压缩
热门文章
- 古董电脑清灰+双系统安装 part1
- JAVA多线程+事务进行批量新增
- 俄罗斯欲推国产应用取代 Google Play
- html桌面图标样式,Win7桌面图标样式怎么修改和还原|Win7修改和还原桌面图标样式的方法...
- Some objects were not cleaned up when closing the scene.
- 路由器交换机基本配置命令
- 推荐系统的评测指标新颖性和惊喜度的区别
- PT网站显示阻断页面,无法登录进去怎么办?
- iPhone上的CPU架构,核数以及运行内存
- 我与python约个会:12程序编程基础6:选择和循环