钉钉开发入门,微应用识别用户身份,获取用户免登受权码code,获取用户userid,获取用户详细信息

这是几年前写的了,如今钉钉的认证流程有些改变,corpSecret 这个东西官方都不建议使用了。html

 

新的第三方企业开发微应用的免登流程 教程 请移步:http://www.javashuo.com/article/p-vskfeyvn-e.html前端


 

最近有个需求,在钉钉内,点击微应用,获取用户身份,根据获取到的用户身份去企业内部的用户中心作校验,校验经过,相关子系统直接登录;java

就是在获取这个用户身份的时候,网上的资料七零八落的,找的人烦躁的很,因此本身记录一下;git

实现这个要求,有好几种方式,使用ISV方式相对来讲比较简单一点,获取的到的信息虽然没有其余方式那么全,可是也包含了百分之七八十的信息,少了角色信息之类的;web

 

效果:(demo的GIT地址在文末)api

 

说说步骤:服务器

1.去OA 控制台建立一个微应用: https://oa.dingtalk.comapp

  

 

  这个首页跳转地址,信任了之后,就能够直接使用js-sdk来获取用户code等相关信息,最方便的一种.ide

  若是是别的页面,使用js-sdk 须要进行dd.config的初始化,这个初始化里面,包含了相关的权限校验.工具

2.应用建立完了之后,会生成一个agentID,

  若是仅仅只是为了获取当前点击用户的信息,而且获取的位置是在这个首页地址的js里面,则大能够不用管这个信息,可是,若是须要更加复杂的操做,就须要获取这个ID,获取方法在建立完了之后,右上角的小三角下拉,有个设置,点进去就能看到

  另外,关于js-sdk的须要鉴权的api信息查询地址:jsapi列表(是否须要dd.config校验)

  列表里面不须要的接口调用,都不须要进行dd.config()

3.获取钉钉开发的corpID和corpSecert

  进入钉钉开发者平台获取:http://open-dev.dingtalk.com

  

  通常获取上面的足够.web sso免登可能须要下面的SSOSecert;

  

4.准备工做作完

  如今咱们有如下信息:

  corpID:

  corpSecert:

  agentID:

  url:这个url就是你须要获取用户code的那个页面url

  固然若是只是简单的获取用户信息,不须要进行dd.config的话,能够不用管agrntID和url

 

5.进入开发(这里只是作获取当前用户信息的示例)

  (1).前端页面引入 dingtalk.js 

  (2).在页面添加 获取code 的 js 代码,

  (3).将获取的 code 发送到后台处理

  (4).后台先根据corpID,corpSecert获取一个accessToken(这个token是获取其余信息的一个关键key)。 文档 

   后台根据 code accessToken 获取 userinfo , 这个获取到的是一个简单的用户信息,包括userid,时候管理员等。 文档 

   后台根据上一步返回的简单的,包含userid的信息,拿到userid

   后台根据userid accessToken 获取用户的详细信息  。文档

  (5).返回给前台显示,或者进行后续开发

 

贴一贴这个流程中关键一点的代码:

前端页面在引入js 后,或有一个dd的全局变量,这个就是js-sdk,若是须要权限校验的,就要放在最前边

关于免登受权码 code 的获取 

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 地址)

import java.io.IOException; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Formatter; import cn.jlhd.util.HttpHelper; import cn.jlhd.util.JsonUtil; import cn.jlhd.util.ReturnUtil; /** * * 1.获取accessToken * 2.获取jsapi中的ticket * 3.生成jsapiz中的鉴权sign * 4.根据传入的临时code获取用户的基本信息,入userinfo * 5.根据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 corpId * @param corpSecert * @return 与钉钉服务器请求生成的accessToken */
    public static String getAccessToken(String corpId, String corpSecert) { long curTime = System.currentTimeMillis(); long differ = curTime - LAST_TIME; if (ACCESS_TOKEN != null && differ < cacheTime) return ACCESS_TOKEN; ACCESS_TOKEN = requestAccessToken(corpId, corpSecert); LAST_TIME = curTime; return ACCESS_TOKEN; } /** * * @param accessToken * * @see getAccess_Token(String corpId, String corpSecert) 生成的access_token * @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("&timestamp=").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 corpId, String corpSecert) { StringBuffer url = new StringBuffer(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 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); }
        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; } }

 

 

作了一个简单demo获取用户信息:

关于钉钉的接口封装GIT 地址: https://gitee.com/lne/DTalkApi

关于获取信息的简单demo地址:https://gitee.com/lne/dtalk_login_simple_demo

相关文章
相关标签/搜索