首先要通过钉钉开放平台创建H5微应用,得到企业id(CorpId),和H5微应用凭证:微应用的ID(AgentId)、微应用的唯一标识key(AppKey)、密钥(AppSecret)。

钉钉开放平台链接
https://open-dev.dingtalk.com

钉钉免登录流程:
1、前端通过CorpId获取免登授权码code;
2、后端通过AppKey和AppSecret获取access_token;
3、使用免登授权码code和access_token去获取用户userid;
4、通过access_token和userid去获取用户详情userinfo;
5、拿userinfo信息去和登录用户去比较,如果一致,则免登录成功。

注意事项
因为是企业内部应用免登录,所以不需要鉴权。免登授权码code每次请求返回的数据都不一样,请求一次的时效是5分钟,access_token有效期7200秒,自动续期。

前端代码

<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><script src="/webjars/jquery/jquery.min.js"></script><meta name="viewport" content="width=device-width,initial-scale=1 user-scalable=0" /><script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script><!-- 引入JSAPI --><script src="https://g.alicdn.com/dingding/dingtalk-jsapi/2.10.3/dingtalk.open.js"></script><title>企业内部应用钉钉免登录</title>
</head>
<script type="text/javascript">function relevance(){// 此方法必须在钉钉环境下才能执行dd.ready(function() {// 获取免登授权码codedd.runtime.permission.requestAuthCode({corpId : "dingxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" , // 企业idonSuccess : function(result) {var code = result.code;getUserInfo(code); //通过该code可以获取用户身份},onFail : function(err) {alert('获取授权码失败: ' + JSON.stringify(err));}});});}function getUserInfo(code) {$.ajax({type : "GET",url : "/ddUser/getUserInfo?code=" + code,contentType : "application/json;charset=utf-8",success : (function(res) {if(res.isLogin){alert("登陆成功!")}else{alert("登录失败!");}}),error: (function (err) {alert("调用getUserInfo失败 err为:" + JSON.stringify(err));}),});}
</script>
<body style="padding-top: 52px;text-align: center;"><button onclick="relevance()">立即绑定</button>
</body>
</html>

后端代码

将钉钉开放平台中得到的CorpId,AgentId,AppKey,AppSecret放到application.yml里面。

azure:corpid: dingxxxxxxxxxxxxxxxxxxxxxxxxxxxappkey: dingxxxxxxxxxxxxxxxappsecret: RVYcJvDtymXWsD9lwXBJRd1qKxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxagentid: 9718xxxxx

创建工具类

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Value;import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;public class HttpHelper {@Value("${azure.corpid}")private static String corpid;@Value("${azure.appsecret}")private static String appsecret;@Value("${azure.agentid}")private static String agentid;@Value("${azure.appkey}")private static String appkey;public static JSONObject httpGet(String url){//创建httpClientCloseableHttpClient httpClient= HttpClients.createDefault();HttpGet httpGet = new HttpGet(url);                             //生成一个请求RequestConfig requestConfig = RequestConfig.custom().         //配置请求的一些属性setSocketTimeout(2000).setConnectTimeout(2000).build();httpGet.setConfig(requestConfig);                             //为请求设置属性CloseableHttpResponse response = null;try {response=httpClient.execute(httpGet);//如果返回结果的code不等于200,说明出错了if (response.getStatusLine().getStatusCode() != 200) {return null;}HttpEntity entity = response.getEntity();                 //reponse返回的数据在entity中if(entity!=null){String resultStr= EntityUtils.toString(entity,"utf-8");//将数据转化为string格式JSONObject result= JSONObject.parseObject(resultStr);  //将结果转化为json格式if(result.getInteger("errcode")==0){                  //如果返回值得errcode值为0,则成功//移除一些没用的元素result.remove("errcode");result.remove("errmsg");return result;                                    //返回有用的信息}else{                                                 //返回结果出错了,则打印出来int errCode = result.getInteger("errcode");String errMsg = result.getString("errmsg");throw new Exception("ErrorCode:"+errCode+"ErrorMsg"+errMsg);}}} catch (ClientProtocolException e) {e.printStackTrace();} catch (Exception e) {e.printStackTrace();} finally {if (response != null) try {response.close();} catch (IOException e) {e.printStackTrace();}}return null;}// 调用httpGet方法获得access_token的代码实现:public static String getAccess_Token(String appkey,String appsecret){String url="https://oapi.dingtalk.com/gettoken?"+"appkey="+appkey+"&appsecret="+appsecret;JSONObject res= HttpHelper.httpGet(url);                      //将httpGet方法封装在HttpHelper类中String access_token="";if(res!=null){access_token=res.getString("access_token");}else{new Exception("获取token异常");}return access_token;}// 执行POST请求(如果免登录成功后不需要推送钉钉消息,则不需要此方法)public static String httpPost(String url, Map<String, Object> params, String encoding) throws Exception {String result = "";// 创建默认的httpClient实例.CloseableHttpClient httpclient = HttpClients.createDefault();// 创建httppostHttpPost httppost = new HttpPost(url);//参数List<NameValuePair> formparams = new ArrayList<NameValuePair>();if (params != null) {Set<String> keys = params.keySet();for (String key : keys) {formparams.add(new BasicNameValuePair(key, params.get(key).toString()));}}UrlEncodedFormEntity uefEntity;try {uefEntity = new UrlEncodedFormEntity(formparams, encoding);httppost.setEntity(uefEntity);CloseableHttpResponse response = httpclient.execute(httppost);try {Header[] headers = response.getAllHeaders();for (Header header : headers) {log.debug(header.getName() + "-->" + header.getValue());}HttpEntity entity = response.getEntity();if (entity != null) {result = EntityUtils.toString(entity, encoding);}} finally {response.close();}} catch (IOException e) {throw e;} finally {// 关闭连接,释放资源try {httpclient.close();} catch (IOException e) {}}return result;}
}

Controller层

import com.alibaba.fastjson.JSONObject;
import com.totyu.mmc.controller.dingding2.model.contact.User;
import io.swagger.annotations.Api;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;import java.util.Date;
import java.util.HashMap;
import java.util.Map;@RestController
@RequestMapping("/ddUser")
@Api(value = "/ddUser")
public class DingdingController {@Value("${azure.corpid}")private String corpid;@Value("${azure.appkey}")private String appkey;@Value("${azure.appsecret}")private String appsecret;@Value("${azure.agentid}")private String agentid;private static final String GET_USERINFO_BYCODE_URL="https://oapi.dingtalk.com/user/getuserinfo?access_token=ACCESSTOKEN&code=CODE";private static final String GET_USER_URL="https://oapi.dingtalk.com/user/get?access_token=ACCESSTOKEN&userid=USERID";/** 根据免登授权码Code查询免登用户* @param code*/@GetMapping("/getUserInfo")public JSONObject getUserInfo(@RequestParam("code") String code) {JSONObject jsonObject = new JSONObject();try {// 获取access_tokenString accessToken = HttpHelper.getAccess_Token(appkey,appsecret);// UserId的URLString getUserIdURL = GET_USERINFO_BYCODE_URL.replace("ACCESSTOKEN", accessToken).replace("CODE", code);// 发起GET请求,获取返回结果jsonObject = HttpHelper.httpGet(getUserIdURL);String userid = (String)jsonObject.get("userid");// User详情的URLString getUserURL = GET_USER_URL.replace("ACCESSTOKEN", accessToken).replace("USERID", userid);// 发起GET请求,获取返回结果jsonObject = HttpHelper.httpGet(getUserURL);// 钉钉发送消息给用户sendMessage(accessToken,userid,(String)jsonObject.get("name"));jsonObject.put("isLogin",true);} catch (Exception e) {e.printStackTrace();jsonObject.put("isLogin",false);}return jsonObject;}// 钉钉发送消息给用户private void sendMessage(String token, String userid, String userName) throws Exception{String messageUrl = "https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2?access_token="+token;Map<String, Object> map = new HashMap<>();map.put("agent_id", agentid);map.put("userid_list", userid);map.put("to_all_user", false);SimpleDateFormat dateformat = new SimpleDateFormat("yyyy年MM月dd日HH时mm分ss秒");String date = dateformat.format(new Date());String content = "用户"+userName+"在"+ date +"时成功登录xxx!";String msg = "{\"msgtype\":\"text\",\"text\":{\"content\":"+"\""+content+"\""+"}}";JSONObject jsonObj = JSONObject.parseObject(msg);map.put("msg",jsonObj);HttpHelper.httpPost(messageUrl,map,"UTF-8");}
}

到此就可以实现免登录钉钉了,业务层可以根据需求自己加。

企业内部应用实现钉钉免登录及登录成功后推送消息相关推荐

  1. 蒲公英上传应用后推送消息到钉钉、微信、QQ

    蒲公英上传生产包,测试人员通过后,就直接下载发布到应用商店的.当发布应用时,推送消息给相关人员,不需要开发一个一个私聊.发下载链接的了. 一.绑定钉钉群,上传应用后,会推送到钉钉群 1.在钉钉群创建机 ...

  2. 插件实现了钉钉和企业微信推送消息

    项目需要开发一个消息推送插件,今天整理一下做一个记录. 消息推送插件实现了钉钉和企业微信推送消息的功能. 首先介绍的是钉钉的实现方式: 1.需要在钉钉后台创建一个应用,并且需要记录下agentId.a ...

  3. 通过GitHub Actions给微信公众测试号和钉钉群定时推送消息(Python)

    通过GitHub Actions给微信公众测试号和钉钉群定时推送消息(Python) https://github.com/QInzhengk/Math-Model-and-Machine-Learn ...

  4. java消息推送怎么实现_调用钉钉接口实现机器人推送消息

    一.摘要 现实交易中为了能及时了解发明者量化机器人交易状态,有时候我们需要将机器人所执行的交易结果发送到微信.邮箱.短信等等.但每天上百条各种各样的信息,使得对这些信息已经不敏感,导致重要的信息不能及 ...

  5. 持续集成之钉钉消息推送:2:推送消息格式说明

    这篇文章介绍一下目前企业微信所支持的推送消息的格式和使用方法,大部分内容与消息示例均来源于目前钉钉的开发文档. 推送消息示例 curl 'https://oapi.dingtalk.com/robot ...

  6. python发钉钉消息_Python调用钉钉机器人推送消息

    1.创建钉钉机器人 群机器人是钉钉群的高级扩展功能,群机器人可以将第三方服务的信息聚合到群聊中,实现自动化的信息同步: 进入一个钉钉群,点击右上角的"群设置"进入群设置页面: 选择 ...

  7. dingtalk 推送手机号信息 golang_Python学习第九十六天:Python调用钉钉机器人推送消息...

    1.创建钉钉机器人 群机器人是钉钉群的高级扩展功能,群机器人可以将第三方服务的信息聚合到群聊中,实现自动化的信息同步: 进入一个钉钉群,点击右上角的"群设置"进入群设置页面: 选择 ...

  8. 钉钉机器人(1)创建钉钉群机器人推送消息

    创建钉钉群机器人发送消息 钉钉群机器人是一个高级扩展功能,只要有一个钉钉账号,就可以使用它.它可以将第三方信息聚合到钉钉群中,实现信息自动同步.支持Webhook协议的自定义接入,通过发明者量化机器人 ...

  9. 持续集成之企业微信通知:5:在Jenkins中向企业微信推送消息

    在这篇文章中结合具体的示例来介绍在Jenkins中如何向企业微信群推送消息. 环境准备 这里使用Easypack的Jenkins 2.164.3来创建验证用的Jenkins环境.使用如下步骤即可完成. ...

最新文章

  1. 线程基类的构建与代码实践
  2. python编码解码的过程_使用Python过程中的编码和解码
  3. 安卓进阶系列-03上弹选择框(PopupDialog)的使用
  4. python 扫盲系列(1)
  5. VSftp常规服务配置
  6. 如何通过PHP将excel的数据导入MySQL中
  7. 【Java】计算1!+2!+.....+20!的值
  8. jQuery1.4.2新特性
  9. 20155301 Exp4 恶意代码分析
  10. cassandra写数据CommitLog
  11. 设计模式(十一):享元模式
  12. 如何将图片批量压缩大小?怎样一次性压缩多张图片?
  13. 【OpenCV C++】照片修改像素(尺寸大小)
  14. 树莓派学习笔记(通过网线连接)
  15. 见微知著,细节上雕花:SVG生成矢量格式网站图标(Favicon)探究
  16. 经典SQL查询语句大全
  17. 【c语言】(函数)利用麦克劳林公式求sinx,cosx,tanx
  18. 基于linux的oracle_rac实时应用集群研究,基于Linux的OracleRAC实时应用集群研究毕业设计论文...
  19. 以Edge浏览器为例演示清除浏览器的缓存
  20. 动态分析Android App之动态调试

热门文章

  1. 计算三角形的周长和面积(海伦公式)
  2. 安卓工程师:秋招21家公司的面试真题总结
  3. 计算机完成一篇文稿制作步骤,PPT制作一篇简单的演示文稿的详细步骤
  4. 千锋ui设计基础视频教程icon图标入门篇
  5. 投影仪贵的和便宜的区别?业内公认千元投影仪性价比排行
  6. 我们发现了点餐系统的严重Bug !!!
  7. 微信PC端 微信浏览器打开控制台
  8. 好用的VIVO手机技巧,有几个是你知道的
  9. Java中浅拷贝和深拷贝的区别
  10. 2017年会成为比WiFi快10倍的“WiGig技术”元年吗?