钉钉提供的免登功能
如下
- 企业应用免登
- ISV应用免登
- 微应用后台管理员免登
- 第三方WEB网站免登
- 第三方WEB网站扫码登录
这里要讲解的是4,5;即第三方Web网站免登:点击网站上登录页面的钉钉图标,显示二维码,然后扫码登录功能;
钉钉Web网站扫码登录文档
一.前期准备
- 第三方网站的网址
- 第三方网站logo的网址
- 操作:
创建要填写的一些相关信息。授权LOGO地址,建议就放你网站的logo好啦。
确定之后就会生成APPID和appSecret,先放着。appSecret后面拿取钉钉的用户信息会用到。
通过以上步骤得到:appId,appSecret ,后面会用到(必须值)
二.流程说明
1.流程图
2.流程文字说明
- 用户点击Web网站上钉钉图标,展示二维码
- 用户使用钉钉app,扫码授权
- 钉钉服务器往回调地址发送code和state
- 在回调地址的action中,由appid,appSecret获取accessToken
- 由3中的code和4中的accessToken获取持久授权码persistent_code
- 由accessToken和5中得到的persistent_code和openid获取用户授权的sns_token
- 再由6中的sns_token获取钉钉用户信息
详情请参考官方文档
三.编码实现
下面的代码因为项目需要除了免登以外,还有一些通讯录的操作,使用者自行选取
注:免登(appid,appsecret)获取的AccessToken与用CorpID和CorpSecret来换取AccessToken不同
1.后台操作代码
using EClaim.Common;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace EClaim.Service.DingDingHelper
{
public class DingDingHelper
{
//免登必需参数
private static string appid = "";
//免登必需参数
private static string appsecret = "";
//其他操作必需参数(例如:通讯录)
private static string corpid = "";
//其他操作必需参数(例如:通讯录)
private static string corpsecret = "";
//由corpid和corpsecret获取accessToken
public static AccessTokenResult GetAccessToken0()
{
string url = "https://oapi.dingtalk.com/gettoken?corpid="+corpid+"&corpsecret="+corpsecret;
try
{
var response = HttpGet(url);
//Log.LogMsg("DingDing_GetAccessToken0", DateTime.Now, response);
var result = Newtonsoft.Json.JsonConvert.DeserializeObject<AccessTokenResult>(response);
return result;
}
catch (Exception ex)
{
//Log.LogMsg("DingDing_GetAccessToken0_Exception", DateTime.Now, ex.Message);
throw new Exception(ex.Message);
}
}
/// <summary>
/// 获取钉钉开放应用的ACCESS_TOKEN(免登功能使用)
/// </summary>
/// <returns></returns>
public static AccessTokenResult GetAccessToken()
{
string url = "https://oapi.dingtalk.com/sns/gettoken?appid=" + appid + "&appsecret=" + appsecret;
try
{
var response = HttpGet(url);
//Log.LogMsg("DingDing_GetAccessToken", DateTime.Now, response);
var result = Newtonsoft.Json.JsonConvert.DeserializeObject<AccessTokenResult>(response);
return result;
}
catch (Exception ex)
{
//Log.LogMsg("DingDing_GetAccessToken_Exception", DateTime.Now, ex.Message);
throw new Exception(ex.Message);
}
}
/// <summary>
/// 获取用户授权的持久授权码(免登功能使用)
/// </summary>
/// <param name="accessToken"></param>
/// <param name="code"></param>
/// <returns></returns>
public static PersistentCodeResult GetPersistentCode(string accessToken, string code)
{
string url = "https://oapi.dingtalk.com/sns/get_persistent_code?access_token=" + accessToken;
string param = "{ \"tmp_auth_code\": \""+code+"\"}";
try
{
//Log.LogMsg("进入HttpPost之前", DateTime.Now, "[url:"+url+"]--[param:"+param+"]");
var response = HttpPost(url, param);
//var response = PostHttp(url, param, Encoding.GetEncoding("utf-8"));
//Log.LogMsg("DingDing_GetPersistentCode", DateTime.Now, response);
var result = Newtonsoft.Json.JsonConvert.DeserializeObject<PersistentCodeResult>(response);
return result;
}
catch (Exception ex)
{
//Log.LogMsg("DingDing_GetPersistentCode_Exception", DateTime.Now, ex.Message);
throw new Exception(ex.Message);
}
}
/// <summary>
/// 获取用户授权的SNS_TOKEN(免登功能使用)
/// </summary>
/// <param name="accessToken"></param>
/// <param name="openId"></param>
/// <param name="persistentCode"></param>
/// <returns></returns>
public static Sns_tokenResult GetSnsToken(string accessToken, string openId, string persistentCode)
{
string url = "https://oapi.dingtalk.com/sns/get_sns_token?access_token=" + accessToken;
string param = "{\"openid\": \""+openId+"\",\"persistent_code\": \""+persistentCode+"\"}";
try
{
var response = HttpPost(url, param);
//Log.LogMsg("DingDing_GetSnsToken", DateTime.Now, response);
var result = Newtonsoft.Json.JsonConvert.DeserializeObject<Sns_tokenResult>(response);
return result;
}
catch (Exception ex)
{
//Log.LogMsg("DingDing_GetSnsToken_Exception", DateTime.Now, ex.Message);
throw new Exception(ex.Message);
}
}
/// <summary>
/// 获取用户授权的个人信息(免登功能使用)
/// </summary>
/// <param name="sns_token"></param>
/// <returns></returns>
public static UserInfoResult GetUserInfo(string sns_token)
{
string url = "https://oapi.dingtalk.com/sns/getuserinfo?sns_token=" + sns_token;
try
{
var response = HttpGet(url);
//Log.LogMsg("DingDing_GetUserInfo", DateTime.Now, response);
var result = Newtonsoft.Json.JsonConvert.DeserializeObject<UserInfoResult>(response);
return result;
}
catch (Exception ex)
{
//Log.LogMsg("DingDing_GetUserInfo_Exception", DateTime.Now, ex.Message);
throw new Exception(ex.Message);
}
}
/// <summary>
/// 根据unionid获取userId
/// </summary>
/// <param name="accessToken"></param>
/// <param name="unionid"></param>
/// <returns></returns>
public static UserIdResult GetUserIdByUnionId(string unionid)
{
var accessToken = GetAccessToken0();
string url = "https://oapi.dingtalk.com/user/getUseridByUnionid?access_token=" + accessToken.access_token + "&unionid=" + unionid;
try
{
var response = HttpGet(url);
//Log.LogMsg("DingDing_GetUserId", DateTime.Now, response);
var result = Newtonsoft.Json.JsonConvert.DeserializeObject<UserIdResult>(response);
return result;
}
catch (Exception ex)
{
//Log.LogMsg("DingDing_GetUserId_Exception", DateTime.Now, ex.Message);
throw new Exception(ex.Message);
}
}
/// <summary>
/// 获取成员详情
/// </summary>
/// <param name="accessToken"></param>
/// <param name="userid"></param>
/// <returns></returns>
public static UserDetailResult GetUserDetail(string userid)
{
var accessToken = GetAccessToken0();
string url = "https://oapi.dingtalk.com/user/get?access_token="+ accessToken.access_token + "&userid="+userid;
try
{
var response = HttpGet(url);
//Log.LogMsg("DingDing_GetUserDetail", DateTime.Now, response);
var result = Newtonsoft.Json.JsonConvert.DeserializeObject<UserDetailResult>(response);
return result;
}
catch(Exception ex)
{
//Log.LogMsg("DingDing_GetUserDetail_Exception", DateTime.Now, ex.Message);
throw new Exception(ex.Message);
}
}
#region 发送请求方法
/// <summary>
/// get方式发送请求
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
public static string HttpGet(string url)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "GET";
request.ContentType = "text/html;charset=UTF-8";
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream myResponseStream = response.GetResponseStream();
StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.GetEncoding("utf-8"));
string retString = myStreamReader.ReadToEnd();
myStreamReader.Close();
myResponseStream.Close();
return retString;
}
public static string HttpPost(string url, string body)
{
//ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
Encoding encoding = Encoding.UTF8;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
request.Accept = "text/html, application/xhtml+xml, */*";
request.ContentType = "application/json";
byte[] buffer = encoding.GetBytes(body);
request.ContentLength = buffer.Length;
request.GetRequestStream().Write(buffer, 0, buffer.Length);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8))
{
return reader.ReadToEnd();
}
}
#endregion
}
public class AccessTokenResult
{
public string access_token { get; set; }
public int errcode { get; set; }
public string errmsg { get; set; }
}
public class PersistentCodeResult
{
public int errcode { get; set; }
public string errmsg { get; set; }
public string openid { get; set; }
public string persistent_code { get; set; }
public string unionid { get; set; }
}
public class Sns_tokenResult
{
public int errcode { get; set; }
public string errmsg { get; set; }
public int expires_in { get; set; }
public string sns_token { get; set; }
}
public class UserInfoResult
{
public int errcode { get; set; }
public string errmsg { get; set; }
public UserInfo user_info { get; set; }
}
public class UserInfo
{
public string maskedMobile { get; set; }
public string nick { get; set; }
public string openid { get; set; }
public string unionid { get; set; }
}
public class UserIdResult
{
public int errcode { get; set; }
public string errmsg { get; set; }
public int contactType { get; set; }
public string userid { get; set; }
}
public class UserDetailResult
{
public int errcode { get; set; }
public string unionid { get; set; }
public string openId { get; set; }
public string roles { get; set; }
public string remark { get; set; }
public string userid { get; set; }
public string isLeaderInDepts { get; set; }
public bool isBoss { get; set; }
public string hiredDate { get; set; }
public bool isSenior { get; set; }
public string tel { get; set; }
public int[] department { get; set; }
public string workPlace { get; set; }
public string email { get; set; }
public string orderInDepts { get; set; }
public string mobile { get; set; }
public string errmsg { get; set; }
public bool active { get; set; }
public string avatar { get; set; }
public bool isAdmin { get; set; }
public bool isHide { get; set; }
public string jobnumber { get; set; }
public string name { get; set; }
public object extattr { get; set; }
public string stateCode { get; set; }
public string position { get; set; }
}
}
2.前台代码实现
<p class="dingdinglogin" onclick="dingdingLogin();">钉钉扫码登录</p>
<script src="//g.alicdn.com/dingding/dinglogin/0.0.5/ddLogin.js"></script>
<script>
var appid = "必填值";
var redirect_uri = "必填值";
var dingurl="https://oapi.dingtalk.com/connect/oauth2/sns_authorize?appid="+appid+"&response_type=code&scope=snsapi_login&state=STATE&redirect_uri="+redirect_uri;
function dingdingLogin() {
debugger;
//$(".login-content-2").hide();
//$("#login_container").show();
var obj = DDLogin({
id: "login_container",//这里需要你在自己的页面定义一个HTML标签并设置id,例如<div id="login_container"></div>或<span id="login_container"></span>
goto: encodeURIComponent(dingurl),
width: "365",
height: "400",
});
var hanndleMessage = function (event) {
var origin = event.origin;
console.log("origin", event.origin);
if (origin == "https://login.dingtalk.com") { //判断是否来自ddLogin扫码事件。
var loginTmpCode = event.data; //拿到loginTmpCode后就可以在这里构造跳转链接进行跳转了
console.log("loginTmpCode", loginTmpCode);
window.location.href = dingurl+"&loginTmpCode=" + loginTmpCode;
}
};
if (typeof window.addEventListener != 'undefined') {
window.addEventListener('message', hanndleMessage, false);
} else if (typeof window.attachEvent != 'undefined') {
window.attachEvent('onmessage', hanndleMessage);
}
}
</script>