钉钉内集成第三方免密登录(Vue+.Net)
需要实现的效果就是在钉钉内点击应用能跳转到第三方网站并且免密登录
1.登录钉钉PC端管理后台
2.通过管理后台进去开发者后台
3.应用开发 创建H5微应用
4.应用创建成功后直接点权限管理全部授权
5.设置H5登录地址
6. 应用管理发布
至此需要配置的步骤全部已完成,需要记住已下三个参数后续开发时候会用到
Client ID、Client Secret、CorpId
上代码
前端用的VUE
// 1.需要下载钉钉包
npm install dingtalk-jsapi --save
// 2.引入包
import * as dd from 'dingtalk-jsapi';
// 3.编写相关登录逻辑
async function initDD() {
//判断是不是通过钉钉内打开的应用
if (dd.env.platform !== "notInDingTalk") {
//进行钉钉登录操作
dd.ready(() => {
//获取登录一次性凭证
dd.runtime.permission.requestAuthCode({
corpId: '换成自己对应的参数以上有说明', // 企业id
}).then(ddRes => {
//凭证获取成功后调用后端登录接口完成相关自动登录逻辑
loginDingTalk(ddRes.code).then(res => {
//记录应用登录凭证到本地
userStore.updateToken(res.data.data.token);
nextTick(() => {
//跳转到主页
router.push(PageEnum.BASE_HOME);
});
});
}).catch(err => {
alert(JSON.stringify(err));
});
});
}
}
后端.NET
WebApi 接口
/// <summary>
/// 用户登录.
/// </summary>
/// <returns></returns>
[HttpPost("Login/DingTalk/{code}")]
[AllowAnonymous]
[IgnoreLog]
public async Task<dynamic> LoginDingTalk(string code)
{
DingUtil ding = new DingUtil();
//得到企业访问token
string accessToken = ding.GetDingToken("Client ID对应自己应用", "Client Secret对应自己应用");
//得到当前钉钉登录的用户信息
string strObj = ding.GetUserInfoInApp(code, accessToken);
JObject objData = strObj.ToObject();
//通过钉钉移动电话获取第三方本地用户信息
UserEntity userEntity = await _userRepository.GetFirstAsync(x => x.MobilePhone.Equals(objData["Mobile"]));
if (userEntity == null) throw Oops.Bah("当前应用无账号,请联系管理员");
//获取到用户信息后完成自动登录相关逻辑 并返回第三方应用登录凭证给登录界面进行缓存
var loginInput = await GetUserInfoByUserAccount(userEntity.Account);
var result = await Login(loginInput);
return new { code = 200, data = result };
}
using DingTalk.Api;
using DingTalk.Api.Request;
using DingTalk.Api.Response;
using Mapster;
using Minio.DataModel.Tracing;
using NetTaste;
using Org.BouncyCastle.Ocsp;
using System.Text.RegularExpressions;
using Tea;
using static DingTalk.Api.Request.OapiRobotSendRequest;
using static DingTalk.Api.Response.OapiV2DepartmentListsubResponse;
using static DingTalk.Api.Response.OapiV2UserListResponse;
namespace DingDing;
/// <summary>
/// 钉钉.
/// </summary>
public class DingUtil
{
/// <summary>
/// 访问令牌.
/// </summary>
public string token { get; private set; }
/// <summary>
/// token有效时间.
/// </summary>
public TimeSpan expiresTime { get; private set; }
/// <summary>
/// 构造函数.
/// </summary>
/// <param name="appKey">企业号ID.</param>
/// <param name="appSecret">凭证密钥.</param>
public DingUtil(string appKey, string appSecret)
{
token = GetDingToken(appKey, appSecret);
}
/// <summary>
/// 构造函数.
/// </summary>
/// <param name="appKey">企业号ID.</param>
/// <param name="appSecret">凭证密钥.</param>
public DingUtil()
{
}
/// <summary>
/// 钉钉token.
/// </summary>
/// <param name="appKey">企业号ID.</param>
/// <param name="appSecret">凭证密钥.</param>
/// <returns></returns>
public string GetDingToken(string appKey, string appSecret)
{
try
{
var tokenurl = "https://oapi.dingtalk.com/gettoken";
DefaultDingTalkClient client = new DefaultDingTalkClient(tokenurl);
OapiGettokenRequest req = new OapiGettokenRequest();
req.SetHttpMethod("GET");
req.Appkey = appKey;
req.Appsecret = appSecret;
OapiGettokenResponse response = client.Execute(req);
if (response.Errcode == 0)
{
// 过期时间
expiresTime = DateTime.Now.Subtract(DateTime.Now.AddSeconds(response.ExpiresIn));
return response.AccessToken;
}
else
{
throw new Exception("获取钉钉Token失败,失败原因:" + response.Errmsg);
}
}
catch (Exception ex)
{
return string.Empty;
}
}
public string GetUserInfoInApp(string code, string accessToken)
{
var client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/getuserinfo");
OapiV2UserGetuserinfoRequest req = new OapiV2UserGetuserinfoRequest();
req.Code = code;
OapiV2UserGetuserinfoResponse rsp = client.Execute(req, accessToken);
if (rsp.Errcode == 0)
{
// 根据unionid获取userid
string unionid = rsp.Result.Unionid;
DefaultDingTalkClient clientDingTalkClient = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/user/getbyunionid");
OapiUserGetbyunionidRequest reqGetbyunionidRequest = new OapiUserGetbyunionidRequest();
reqGetbyunionidRequest.Unionid = unionid;
OapiUserGetbyunionidResponse oapiUserGetbyunionidResponse = clientDingTalkClient.Execute(reqGetbyunionidRequest, accessToken);
if (oapiUserGetbyunionidResponse.Errcode == 0)
{
// 根据userId获取用户信息
string userid = oapiUserGetbyunionidResponse.Result.Userid;
var user = GetUserInfoByUserId(userid, accessToken);
return user;
}
}
return string.Empty;
}
/// <summary>
/// 根据用户UserId取得用户信息.
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
private string GetUserInfoByUserId(string userId, string accessToken)
{
var client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/get");
var req = new OapiV2UserGetRequest();
req.Userid = userId;
req.Language = "zh_CN";
var res = client.Execute(req, accessToken);
if (res.Errcode == 0) return res.Result.ToJsonString(); else throw new Exception(res.ErrMsg);
}
#region 用户
}