一、工具和环境:eclipse+springBoot+Maven+jquery+51手机模拟器
二、阅读官方开发文档并熟记免登流程和步骤
三、按步骤实现:
1、在企业管理后台:https://oa.dingtalk.com/上注册企业完成之后,在企业应用-工作台设置页面里面,可以获取到企业的corpId和CorpSecret。
2、通过调用获取access_token的接口获取企业的access_token。
// accessToken放到文件中缓存2小时
public static final long cacheTime = 1000 * 60 * 60 * 2;
/**
* 2、通过调用获取access_token的接口获取企业的access_token。
* @return
* @throws OApiException
*/
public static String getAccessToken() throws OApiException {
long curTime = System.currentTimeMillis();
JSONObject accessTokenValue = (JSONObject) FileUtils.getValue("accesstoken", Env.CORP_ID); //从accesstoken.properties文件中取accesstoken
String accToken = "";
String jsTicket = "";
JSONObject jsontemp = new JSONObject();
//首次获取accesstoken或者缓存时间超过2小时后重新获取
if (accessTokenValue == null || curTime - accessTokenValue.getLong("begin_time") >= cacheTime) {
try
{
ServiceFactory serviceFactory = ServiceFactory.getInstance();
CorpConnectionService corpConnectionService = serviceFactory.getOpenService(CorpConnectionService.class);
accToken = corpConnectionService.getCorpToken(Env.CORP_ID, Env.CORP_SECRET);
JSONObject jsonAccess = new JSONObject();
jsontemp.clear();
jsontemp.put("access_token", accToken);
jsontemp.put("begin_time", curTime);
jsonAccess.put(Env.CORP_ID, jsontemp);
FileUtils.write2File(jsonAccess, "accesstoken");
if(accToken.length() > 0){
JsapiService jsapiService = serviceFactory.getOpenService(JsapiService.class);
JsapiTicket JsapiTicket = jsapiService.getJsapiTicket(accToken, "jsapi");
jsTicket = JsapiTicket.getTicket();
JSONObject jsonTicket = new JSONObject();
jsontemp.clear();
jsontemp.put("ticket", jsTicket);
jsontemp.put("begin_time", curTime);
jsonTicket.put(Env.CORP_ID, jsontemp);
FileUtils.write2File(jsonTicket, "jsticket");
}
} catch (Exception e) {
e.printStackTrace();
}
} else {
return accessTokenValue.getString("access_token");
}
return accToken;
}
3、通过调用获取jsticket的接口获取企业的jsticket。
/**
* 3、通过调用获取jsticket的接口获取企业的jsticket。
* @param accessToken
* @return
* @throws OApiException
*/
public static String getJsapiTicket(String accessToken) throws OApiException {
JSONObject jsTicketValue = (JSONObject) FileUtils.getValue("jsticket", Env.CORP_ID);
long curTime = System.currentTimeMillis();
String jsTicket = "";
if (jsTicketValue == null || curTime -
jsTicketValue.getLong("begin_time") >= cacheTime) {
ServiceFactory serviceFactory;
try {
serviceFactory = ServiceFactory.getInstance();
JsapiService jsapiService = serviceFactory.getOpenService(JsapiService.class);
JsapiTicket JsapiTicket = jsapiService.getJsapiTicket(accessToken, "jsapi");
jsTicket = JsapiTicket.getTicket();
JSONObject jsonTicket = new JSONObject();
JSONObject jsontemp = new JSONObject();
jsontemp.clear();
jsontemp.put("ticket", jsTicket);
jsontemp.put("begin_time", curTime);
jsonTicket.put(Env.CORP_ID, jsontemp);
FileUtils.write2File(jsonTicket, "jsticket");
} catch (Exception e) {
e.printStackTrace();
}
return jsTicket;
} else {
return jsTicketValue.getString("ticket");
}
}
4、在后端通过sign(ticket, nonceStr, timeStamp, url)计算前端校验需要使用的签名信息。
/**
* 4、在后端通过sign(ticket, nonceStr, timeStamp, url)计算前端校验需要使用的签名信息。
* @param url
* @return
* @throws OApiException
*/
public static Map<String,Object> getConfig(String url) throws OApiException {
String accessToken = getAccessToken();
String JsTicket = getJsapiTicket(accessToken);
String nonceStr = Utils.getRandomStr(16); //随机数生成nonceStr
long timeStamp = System.currentTimeMillis();
try {
String signature = getJsApiSingnature(url, nonceStr, timeStamp, JsTicket);
Map<String, Object> JsApiConfig = new HashMap<String,Object>();
JsApiConfig.put("signature", signature);
JsApiConfig.put("timeStamp", timeStamp);
JsApiConfig.put("corpId", Env.CORP_ID);
JsApiConfig.put("agentId", Env.AGENT_ID);
JsApiConfig.put("nonceStr", nonceStr);
return JsApiConfig;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static String getJsApiSingnature(String url,String nonceStr,long timeStamp,String jsTicket) throws DingTalkEncryptException{
String plainTex = "jsapi_ticket=" + jsTicket + "&noncestr=" + nonceStr + "×tamp=" + String.valueOf(timeStamp) + "&url=" + url;
System.out.println(plainTex);
String signature = "";
try{
MessageDigest crypt = MessageDigest.getInstance("SHA-1");
crypt.reset();
crypt.update(plainTex.getBytes("UTF-8"));
signature = byteToHex(crypt.digest());
return signature;
}catch (Exception e){
throw new DingTalkEncryptException(DingTalkEncryptException.COMPUTE_SIGNATURE_ERROR);
}
}
private static String byteToHex(final byte[] hash) {
Formatter formatter = new Formatter();
for (byte b : hash){
formatter.format("%02x", b);
}
String result = formatter.toString();
formatter.close();
return result;
}
}
5、将:‘url’,‘nonceStr’,‘agentId’,‘timeStamp’,‘corpId’,‘signature’传递到前端页面,在前端页面使用jsapi提供的dd.config(PC客户端使用DingTalkPC.config)接口进行签名校验。
package com.alibaba.dingtalk.openapi.demo.controller;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.alibaba.dingtalk.openapi.demo.OApiException;
import com.alibaba.dingtalk.openapi.demo.auth.AuthHelper;
import com.alibaba.dingtalk.openapi.demo.service.ServiceHelper;
import com.alibaba.fastjson.JSONObject;
@Controller
@RequestMapping("/")
public class MainController {
@Autowired
private ServiceHelper serviceHelper;
@RequestMapping("/demo")
public String index(){
return "index";
}
@CrossOrigin
@RequestMapping("/get_js_config")
@ResponseBody
public Map<String,Object> getJsConfig(@RequestParam(value="url",required = false) String url) throws OApiException{
return AuthHelper.getConfig(url);
}
@CrossOrigin
@RequestMapping("/get-user-info")
@ResponseBody
public JSONObject getUserInfo(String code) throws OApiException{
return JSONObject.parseObject(serviceHelper.getUserInfo(AuthHelper.getAccessToken(),code));
}
@CrossOrigin
@RequestMapping("/api_get")
@ResponseBody
public JSONObject getUserInfoById(String code) throws OApiException{
return JSONObject.parseObject(serviceHelper.getUserInfoById(AuthHelper.getAccessToken(),JSONObject.parseObject(serviceHelper.getUserInfo(AuthHelper.getAccessToken(),code)).getString("userid")));
}
}
6、在页面引入jsapi:https://g.alicdn.com/ilw/ding/0.9.2/scripts/dingtalk.js
7、使用钉钉js-api提供的获取免登授权码接口获取CODE
8、通过CODE换取身份
<html>
演示图:
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />
<title>创联云钉钉二次开发</title>
<script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js" charset="utf-8"></script>
<script src="https://g.alicdn.com/ilw/ding/0.9.2/scripts/dingtalk.js" charset="utf-8"></script>
</head>
<script type="text/javascript">
Window.authcode = "";
$(document).ready(function(){
var url = window.location.href;
var corpId="";
var signature = "";
var nonceStr = "";
var timeStamp = "";
var agentId= "";
$.post(
'get_js_config',
{
"url":url
},
function(result){
corpId= result.corpId;
signature = result.signature;
nonceStr = result.nonceStr;
timeStamp = result.timeStamp;
agentId= result.agentId;
dd.config({
agentId : agentId,
corpId : corpId,
timeStamp : timeStamp,
nonceStr : nonceStr,
signature :signature,
jsApiList : [
'runtime.info',
'biz.contact.choose',
'device.notification.confirm',
'device.notification.alert',
'device.notification.prompt',
'biz.ding.post',
'biz.util.openLink' ]
});
dd.ready(function() {
dd.runtime.info({
onSuccess : function(info) {
console.log('runtime info: ' + JSON.stringify(info));
},
onFail : function(err) {
console.log('fail: ' + JSON.stringify(err));
}
});
dd.runtime.permission.requestAuthCode({
corpId : corpId,
onSuccess : function(info) {
Window.authcode = info.code;
$.get(
'api_get',
{
"code":info.code
},
function(result){
$("#agent").empty();
$("#agent").append(result.name);
}
);
},
onFail : function(err) {
console.log('requestAuthCode: ' + JSON.stringify(err));
}
});
});
dd.error(function(err) {
alert('dd error: ' + JSON.stringify(err));
});
}
)
});
function auth(){
$("#code").empty();
var html = "<span>"+Window.authcode+"</span>";
$("#code").append(html);
}
function getUserInfo(){
var code = Window.authcode;
$.get(
'get-user-info',
{
"code":code
},
function(result){
$("#user").empty();
var html="<ul>";
html+= "<li>"+result.userid+"</li>";
html+= "<li>"+result.is_sys+"</li>";
html+= "<li>"+result.deviceId+"</li>";
html+= "<li>"+result.sys_level+"</li>";
html+= "</ul>";
$("#user").append(html);
}
);
}
</script>
<style type="text/css">
.btn{
height:40pxp;
width:200px;
font-size:24px;
font-family:"Arial black";
}
.content{
font-size:48px;
font-family:"Arial black";
}
.head{
align-content:center;
font-size:18px;
}
</style>
<body>
<div class="head">
免登demo
</div>
<div>
<div style="...">
<!-- <button class="btn" onclick="getAgentInfo()">获取用户信息</button> -->
欢迎登录! <div id ="agent" class="contert"></div>
</div>
<!--
<div>
<button class="btn" onclick="auth()">显示免登授权码</button>
<div id ="code" class="contert"></div>
</div>
<div style="...">
<button class="btn" onclick="getUserInfo()">获取身份信息</button>
<div id ="user" class="contert"></div>
</div>
-->
</div>
</body>
</html>
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。