一、创建应用
在钉钉管理后台-应用开发-企业内部开发-创建应用(我们这边创建的是H5微应用)
创建好了之后,会拿到应用凭证:AgentId,AppKey,AppSecret
这三个值在开发中会用到
二、授权免登流程
1、前端–获取微应用免登授权码
具体参考API:获取授权码API
2、后端–授权免登
(1)获取access_token
用AppKey和AppSecret换取access_token
public static String getAccessToken(String appKey, String appSecret) {
DefaultDingTalkClient client = new
DefaultDingTalkClient("https://oapi.dingtalk.com/gettoken");
OapiGettokenRequest request = new OapiGettokenRequest();
request.setAppkey(appKey);
request.setAppsecret(appSecret);
request.setHttpMethod("GET");
OapiGettokenResponse response = null;
try {
response = client.execute(request);
} catch (ApiException e) {
log.error("dingUtil getAppToken error", e);
throw new BizException("获取token失败");
}
if (!response.isSuccess()) {
log.error("dingUtil getAccessTokenAfresh failed, errorCode={}, errorMsg={}", response.getErrcode(), response.getErrmsg());
return null;
}
return response.getAccessToken();
}
说明:正常情况下access_token有效期为7200秒,有效期内重复获取返回相同结果,并自动续期。所以不需要每次有用户授权登录,都要去获取一次。
@Component
public class AccessTokenCache {
private static Logger logger = LoggerFactory.getLogger(AccessTokenCache.class);
private static AccessTokenCache cache = new AccessTokenCache();
private String appToken = null;
private AccessTokenCache() {
}
public static AccessTokenCache getInstance() {
return cache;
}
public void init() {
while (true) {
try {
appToken = DingDingUtil.getAccessToken("appKey", "appSecret");
if (null != appToken) {
logger.info("获取token成功, appToken:{}", appToken);
// 休眠 1 小时
Thread.sleep(3600 * 1000);
} else {
// 如果access_token为null,60秒后再获取
Thread.sleep(60 * 1000);
}
} catch (InterruptedException e) {
try {
Thread.sleep(60 * 1000);
} catch (InterruptedException e1) {
logger.error("{}", e1);
}
logger.error("{}", e);
}
}
}
public String getAppToken() {
return appToken;
}
}
在启动类加上:
AccessTokenCache accessTokenCache = new AccessTokenCache();
AccessTokenCache.getInstance().init();
每个小时获取一次access_token 需要的时候通过这个方法来获取就好了,
在授权,鉴权,消息通知等流程中都是要用到的。
参考API:获取access_tokenAPI
(2)获取用户userid
通过免登授权码和access_token获取用户的userid。
DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/user/getuserinfo");
OapiUserGetuserinfoRequest request = new OapiUserGetuserinfoRequest();
request.setCode(code);
request.setHttpMethod("GET");
OapiUserGetuserinfoResponse response = client.execute(request, accessToken);
if (!response.isSuccess()) {
log.error("dingUtil getUserInfo failed, errorCode={}, errorMsg={}", response.getErrcode(), response.getErrmsg());
return null;
}
return response;
返回值:
{
"userid": "****",// 员工在当前企业内的唯一标识,也称staffId
"is_sys": true,//是否是管理员,true:是,false:不是
"sys_level": 1,//级别。1是主管理员,2是子管理员,100是老板,0是其他(如普通员工)
"errcode": 0//错误码
"errmsg": "ok",//错误描述
}
获取用户信息参考API:获取用户信息
(3)获取用户详情
如果要获取当前用户更多的详情,可以使用这个api去获取更多用户信息
用上一步获得的userid和access_token获取用户详情信息
DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/user/get");
OapiUserGetRequest request = new OapiUserGetRequest();
request.setUserid(userId);
request.setHttpMethod("GET");
OapiUserGetResponse response = client.execute(request, accessToken);
if (!response.isSuccess()) {
log.error("dingUtil getUser failed, errorCode={}, errorMsg={}", response.getErrcode(), response.getErrmsg());
return null;
}
获取用户详情参考API:获取用户详情述
(4)将当前用户信息写进缓存,并生成token给前端以便验证登录用户,这样就拿到了当前用户信息完成了授权免登。
三、鉴权流程
在开发过程,前端调用某些api是需要鉴权才可以调用的。所以要走鉴权流程把需要鉴权的api走鉴权流程。
1、后端–获取签名
(1)获取access_token(同上)
(2)获取jsapi_ticket
用access_token换取ticket
注意:
a、当jsapi_ticket未过期时,再次调用get_jsapi_ticket会获取到一个全新的jsapi_ticket(和旧的jsapi_ticket值不同),这个全新的jsapi_ticket的过期时间是2小时。
b、jsapi_ticket是一个appKey对应一个,所以在使用的时候需要将jsapi_ticket以appKey为维度进行缓存下来(设置缓存过期时间2小时),并不需要每次都通过接口拉取。
DefaultDingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/get_jsapi_ticket");
OapiGetJsapiTicketRequest req = new OapiGetJsapiTicketRequest();
req.setTopHttpMethod("GET");
OapiGetJsapiTicketResponse response = client.execute(req, accessToken);
if (!response.isSuccess()) {
log.error("dingUtil getTicket failed, errorCode={}, errorMsg={}", response.getErrcode(), response.getErrmsg());
return null;
}
return response.getTicket();
(3)生成签名,并将签名参数返回给前端
生成签名的参数:
String ticket 上一步获取的票据
String nonceStr 随机字符串
long timeStamp 当前时间戳
String url 当前网页的URL,不包含#及其后面部分
String plain = "jsapi_ticket=" + ticket + "&noncestr=" + nonceStr + "×tamp=" + String.valueOf(timeStamp)
+ "&url=" + url;
try {
MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
sha1.reset();
sha1.update(plain.getBytes("UTF-8"));
return byteToHex(sha1.digest());
} catch (NoSuchAlgorithmException e) {
log.error("dingUtil sign error", e);
throw new BizException("签名错误");
} catch (UnsupportedEncodingException e) {
log.error("dingUtil sign error", e);
throw new BizException("签名错误");
}
/**
* 字节数组转化成十六进制字符串
*
* @param hash
* @return
*/
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;
}
返回前端的参数:nonceStr,timeStamp,signature(签名结果),corpId(企业ID),agentId(创建应用时获得的)
2、前端–JSAPI鉴权
拿着后端返回的签名参数进行dd.config鉴权
注意:这里鉴权,钉钉那边是做了灰度的,如果出现偶发错误情况,那一定是代码有问题。
参考博文:钉钉鉴权报错
至此,完成鉴权。整个鉴权流程API:鉴权流程API
本文详细介绍了在钉钉中创建企业内部应用的步骤,包括获取应用凭证、授权免登流程(前端获取授权码、后端换取access_token、获取用户信息及详情)以及鉴权流程(获取签名并进行JSAPI鉴权)。通过这些步骤,可以实现用户免登授权和鉴权调用受保护的API。
1745

被折叠的 条评论
为什么被折叠?



