一、本节要点
1.免登授权的流程
(1)签名校验
(2)获取code,并传到后台
(3)根据code获取userid
(4)根据userid获取用户信息,(此处可进行相应业务处理)
(5)将用户信息传到前端,前端拿到用户信息,并做相应处理
2.计算签名信息(signature)
2.1 待签名参数
ticket
jsapi_ticket
nonceStr
随机字符串,随机生成
timeStamp
时间戳
url
当前网页的URL,不包含#及其后面部分
2.2签名流程
(1)字典序
将所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式 (即 key1=value1&key2=value2…)拼接成字符串string1
如:String string1= "jsapi_ticket=" + jsTicket + "&noncestr=" + nonceStr + "×tamp=" + timeStamp + "&url=" + url;
(2)SHA-1签名,得到 signature
/*** @desc : 3.生成签名的函数
*
*@paramticket jsticket
*@paramnonceStr 随机串,自己定义
*@paramtimeStamp 生成签名用的时间戳
*@paramurl 需要进行免登鉴权的页面地址,也就是执行dd.config的页面地址
*@return*@throwsException String*/
public static String getSign(String jsTicket, String nonceStr, Long timeStamp, String url) throwsException {
String plainTex= "jsapi_ticket=" + jsTicket + "&noncestr=" + nonceStr + "×tamp=" + timeStamp + "&url=" +url;
System.out.println(plainTex);try{
MessageDigest crypt= MessageDigest.getInstance("SHA-1");
crypt.reset();
crypt.update(plainTex.getBytes("UTF-8"));returnbyteToHex(crypt.digest());
}catch(NoSuchAlgorithmException e) {throw newException(e.getMessage());
}catch(UnsupportedEncodingException e) {throw newException(e.getMessage());
}
}//将bytes类型的数据转化为16进制类型
private static String byteToHex(byte[] hash) {
Formatter formatter= newFormatter();for (byteb : hash) {
formatter.format("%02x", newObject[] { Byte.valueOf(b) });
}
String result=formatter.toString();
formatter.close();returnresult;
}
View Code
3.签名校验的流程
3.1 后端准备好前端校验参数
后台方法:getConfig(HttpServletRequest)
public staticString getConfig(HttpServletRequest request){//1.准备好参与签名的字段
/**以http://localhost/test.do?a=b&c=d为例
*request.getRequestURL的结果是http://localhost/test.do
*request.getQueryString的返回值是a=b&c=d*/String urlString=request.getRequestURL().toString();
String queryString=request.getQueryString();
String queryStringEncode= null;
String url;if (queryString != null) {
queryStringEncode=URLDecoder.decode(queryString);
url= urlString + "?" +queryStringEncode;
}else{
url=urlString;
}
String nonceStr=UUID.randomUUID().toString(); //随机数
long timeStamp = System.currentTimeMillis() / 1000; //时间戳参数
String signedUrl=url;
String accessToken= null;
String ticket= null;
String signature= null; //签名//2.进行签名,获取signature
try{
accessToken=AuthHelper.getAccessToken(Env.CORP_ID, Env.CORP_SECRET);
ticket=AuthHelper.getJsapiTicket(accessToken);
signature=getSign(ticket,nonceStr,timeStamp,signedUrl);
}catch(Exception e) {//TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("accessToken:"+accessToken);
System.out.println("ticket:"+ticket);
System.out.println("nonceStr:"+nonceStr);
System.out.println("timeStamp:"+timeStamp);
System.out.println("signedUrl:"+signedUrl);
System.out.println("signature:"+signature);
System.out.println("agentId:"+Env.AGENTID);
System.out.println("corpId:"+Env.CORP_ID);
String configValue= "{jsticket:'" + ticket + "',signature:'" + signature + "',nonceStr:'" + nonceStr + "',timeStamp:'"
+ timeStamp + "',corpId:'" + Env.CORP_ID + "',agentId:'" + Env.AGENTID + "'}";
System.out.println(configValue);returnconfigValue;
}
View Code
3.2 前端接收后台参数
在前端调用后端方法,获取dd.config所需的校验参数:‘url’,‘nonceStr’,‘agentId’,‘timeStamp’,‘corpId’,‘signature’。
var _config =;
View Code
3.3 执行前端 dd.config ,进行签名校验
dd.config 用接收到的 nonceStr、agentId、timeStamp、corpId这四个参数去钉钉官方后端计算出一个签名(signature ), 并将这个签名与我们后端所计算的signature来进行比对,若一致,则校验通过。若不一致,则是我们后端计算签名的时候出错了。此时可根据错误消息提示去进行调试。
dd.config({
agentId : _config.agentId,
corpId : _config.corpId,
timeStamp : _config.timeStamp,
nonceStr : _config.nonceStr,
signature : _config.signature,
jsApiList : [//需要调用的借口列表
'runtime.info','biz.contact.choose', //选择用户接口
'device.notification.confirm','device.notification.alert', //confirm,alert,prompt都是弹出小窗口的接口
'device.notification.prompt','biz.ding.post','biz.util.openLink']
});
View Code
3.4 异常:js加载顺序有误所引起的 前端什么信息都不提示
出现这个原因,可能是自己js出错了。我的原因是js加载顺序有误。
请注意这几个js的加载顺序: _config,jquery-3.2.1.min.js 必须在auth.js之前加载
var _config =;
View Code
4. 将code送往后端:ajax
签名校验成功之后,即dd.config校验成功之后,会执行dd.ready函数,这时我们就可以使用钉钉的jsapi了。
签名校验成功后,我们就可以调用获取免登授权码(CODE)的jsapi,来获取code,然后通过ajax方式将这个code传到后台userInfoServlet
/**获取免登授权码 CODE
**/dd.runtime.permission.requestAuthCode({
corpId : _config.corpId,
onSuccess :function(info) { //成功获得code值,code值在info中
alert('authcode: ' +info.code);/**$.ajax的是用来使得当前js页面和后台服务器交互的方法
*参数url:是需要交互的后台服务器处理代码,userInfoServlet
*