最近有個需求,在釘釘內,點擊微應用,獲取用戶身份,根據獲取到的用戶身份去企業內部的用戶中心做校驗,校驗通過,相關子系統直接登陸;
就是在獲取這個用戶身份的時候,網上的資料七零八落的,找的人煩躁的很,所以自己記錄一下;
實現這個要求,有好幾種方式,使用ISV方式相對來說比較簡單一點,獲取的到的信息雖然沒有其他方式那么全,但是也包含了百分之七八十的信息,少了角色信息之類的;
效果:(demo的GIT地址在文末)
說說步驟:
這個首頁跳轉地址,信任了以后,就可以直接使用js-sdk來獲取用戶code等相關信息,最方便的一種.
如果是別的頁面,使用js-sdk 需要進行dd.config的初始化,這個初始化里面,包含了相關的權限校驗.
2.應用創建完了以后,會生成一個agentID,
如果僅僅只是為了獲取當前點擊用戶的信息,并且獲取的位置是在這個首頁地址的js里面,則大可以不用管這個信息,但是,如果需要更加復雜的操作,就需要獲取這個ID,獲取方法在創建完了以后,右上角的小三角下拉,有個設置,點進去就能看到
另外,關于js-sdk的需要鑒權的api信息查詢地址:jsapi列表(是否需要dd.config校驗)
列表里面不需要的接口調用,都不需要進行dd.config()
3.獲取釘釘開發的corpID和corpSecert
一般獲取上面的足夠.web sso免登可能需要下面的SSOSecert;
4.準備工作做完
現在我們有以下信息:
corpID:
corpSecert:
agentID:
url:這個url就是你需要獲取用戶code的那個頁面url
當然如果只是簡單的獲取用戶信息,不需要進行dd.config的話,可以不用管agrntID和url
5.進入開發(這里只是做獲取當前用戶信息的示例)
(1).前端頁面引入dingtalk.js
(2).在頁面添加 獲取code 的 js 代碼,
(3).將獲取的 code發送到后臺處理
后臺根據上一步返回的簡單的,包含userid的信息,拿到userid
(5).返回給前臺顯示,或者進行后續開發
貼一貼這個流程中關鍵一點的代碼:
前端頁面在引入js 后,或有一個dd的全局變量,這個就是js-sdk,如果需要權限校驗的,就要放在最前邊
dd.ready(function() {
dd.runtime.permission.requestAuthCode({
corpId :"這里是你的corpID",
onSuccess :function(result) {var code =result.code;
alert(code);
//將code 發往后臺處理
},
onFail :function(err) {
alert(‘出錯了, ‘ +err);
}
});
});
后臺處理部分:
AuthHelper.java 文末提供
在接收到授權碼以后:
String accessToken =AuthHelper.getAccessToken(CORP_ID, CORP_SECRET);
String user= AuthHelper.getUserInfo(code, accessToken);
當返回正確的時候,這個user 里面結果大致是這樣的:
{"errcode": 0,"errmsg": "ok","userid": "USERID","deviceId":"DEVICEID","is_sys": true,"sys_level": 0|1|2}
然后根據里面的userid,獲取詳細的用戶信息:
String userall = AuthHelper.getUser(userid, accessToken);
返貨正確的話,這個userall里面的結果大致是:(具體查看釘釘開發文檔)
{"errcode": 0,"unionid": "PiiiPyQqBNBii0HnCJ3zljcuAiEiE","openId": "PiiiPyQqBNBii0HnCJ3zljcuAiEiE","roles": [{"id": 23003585,"name": "財務","groupName": "職務"}],"remark": "備注","userid": "04232334556237185","isLeaderInDepts": "{1:false}","isBoss": false,"hiredDate": 1520265600000,"isSenior": false,"tel": "010-88996533","department": [1,2],"workPlace": "北京市朝陽區","email": "ceshi@aliyun.com","orderInDepts": "{1:71738366882504}","dingId": "$:LWCP_v1:$aTPvVHhhsCMtDZRQ1xbYGg==","mobile": "15901516821","errmsg": "ok","active": false,"avatar": "dingtalk.com/abc.jpg","isAdmin": false,"isHide": false,"jobnumber": "001","name": "測試名字","extattr": {},"stateCode": "86","position": "總監"}
然后簡單的獲取信息到此結束;
注意的是:
如果需要更多的操作,就需要在前端頁面進行dd.config的初始化,這個里面的所需要的sign,可以在后臺根據相關信息生成,是必不可少的,生成規則見AuthHelper.java(其他工具類見文末的 git 地址)
importjava.io.IOException;importjava.io.UnsupportedEncodingException;importjava.security.MessageDigest;importjava.security.NoSuchAlgorithmException;importjava.util.Formatter;importcn.jlhd.util.HttpHelper;importcn.jlhd.util.JsonUtil;importcn.jlhd.util.ReturnUtil;/***
* 1.獲取accessToken
* 2.獲取jsapi中的ticket
* 3.生成jsapiz中的鑒權sign
* 4.根據傳入的臨時code獲取用戶的基本信息,入userinfo
* 5.根據userid獲取詳細用戶信息
*
*@authorlnexin
**/
public classAuthHelper {//釘釘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;/***
*@paramcorpId
*@paramcorpSecert
*@return與釘釘服務器請求生成的accessToken*/
public staticString getAccessToken(String corpId, String corpSecert) {long curTime =System.currentTimeMillis();long differ = curTime -LAST_TIME;if (ACCESS_TOKEN != null && differ
ACCESS_TOKEN=requestAccessToken(corpId, corpSecert);
LAST_TIME=curTime;returnACCESS_TOKEN;
}/***
*@paramaccessToken
*
*@seegetAccess_Token(String corpId, String corpSecert) 生成的access_token
*@return一個用于js鑒權的ticket*/
public staticString getJsapiTicket(String accessToken) {long curTime =System.currentTimeMillis();long differ = curTime -LAST_TIME;if (JSAPI_TICKET != null && differ
}
JSAPI_TICKET=requestJsapiTicket(accessToken);returnJSAPI_TICKET;
}/*** 根據傳入的相關參數生成sign
*
*@paramticket
*@paramnonceStr
*@paramtimeStamp
*@paramurl
*@return
*/
public static String sign(String ticket, String nonceStr, longtimeStamp, String url) {
StringBuffer plain= newStringBuffer();
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"));returnbytesToHex(sha.digest());
}catch(NoSuchAlgorithmException e) {
e.printStackTrace();
}catch(UnsupportedEncodingException e) {
e.printStackTrace();
}return null;
}private staticString requestAccessToken(String corpId, String corpSecert) {
StringBuffer url= newStringBuffer(TOKEN_URL);
url.append("?corpid=").append(corpId);
url.append("&corpsecret=").append(corpSecert);
String result= null;try{
result=HttpHelper.sendGet(url.toString());
}catch(IOException e) {
result= ReturnUtil.result("-1","請求accessTokenc出錯!corpid:" + corpId + ",corpsecert:" + corpSecert + "異常信息:" +e);
}
return JsonUtil.getJsonNode(result).get("access_token").asText();
}private staticString requestJsapiTicket(String accessToken) {
StringBuffer url= newStringBuffer(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);
}
return JsonUtil.getJsonNode(result).get("ticket").asText();
}private static String bytesToHex(byte[] hash) {
Formatter formatter= newFormatter();for (byteb : hash) {
formatter.format("%02x", b);
}
String result=formatter.toString();
formatter.close();returnresult;
}/*** 獲取用戶信息
*
*@paramcode
* 用戶相應的臨時code
*@paramtoken
* 根據相應corpid和corpsecret生成的access_token
*@return用戶ID等相關信息*/
public staticString getUserInfo(String code, String accessToken) {
StringBuffer url= newStringBuffer(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);
}returnresult;
}/*** 獲取用戶詳細信息
*@paramuserid 在某個corpid下的唯一用戶userid
*@paramaccessToken 據相應corpid和corpsecret生成的access_token
*@return
*/
public staticString getUser(String userid, String accessToken) {
StringBuffer url= newStringBuffer(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);
}returnresult;
}
}
做了一個簡單demo獲取用戶信息: