记录一下钉钉一键登录的流程,虽然文档写的很详细,但还是有一些地方写的不是很详细。
流程图:
文档:
获取微应用免登授权码文档:获取微应用免登授权码 - 钉钉开放平台
获取微应用免登授权码接口:API Explorer
获取登录用户的访问凭证:获取登录用户的访问凭证 - 钉钉开放平台
获取用户通讯录个人信息文档:获取用户通讯录个人信息 - 钉钉开放平台
获取用户通讯录个人信息接口:API Explorer
第三方企业应用免登:第三方企业应用免登 - 钉钉开放平台
查看用户详情:查询用户详情 - 钉钉开放平台
获取用户token接口:API Explorer
这里是我整理的一些文档和API在线测试的地址。
首先是进入钉钉的访问凭证,也就是咱们的授权页面,这个是钉钉已经集成好的,咱们只需要更改一下配置就好了。
https://login.dingtalk.com/oauth2/auth?
redirect_uri=https%3A%2F%2Fwww.aaaaa.com%2Fa%2Fb
&response_type=code
&client_id=dingbbbbbbb
&scope=openid
&state=dddd
&prompt=consent
咱们重点介绍一下redirect_uri
这个参数是干啥的,以及从哪里配置。
咱们做单点登录肯定是需要把获取的用户信息进行入库的,所以redirect_uri
填写咱们的业务接口,除非不需要进行数据绑定只需要跳转页面,这里就可以填写一个页面地址。
我这里是需要进行用户绑定,因此填写的是一个接口地址。
下面的一些参数,参考文档就可以查看详情内容。
接口方式采用Get请求,授权成功之后会从请求后面拼接一个参数。
参数名:authCode
这个参数咱们后面会用来获取token
。
拿到authCode
调用获取Token,文档参数介绍的都很详细,唯独code
和refreshToken
没有过多的介绍。这两个参数从哪里获取?如何使用?
文档没有过多介绍,这里说明:其实这两个参数就是咱们上一步授权获得的authCode
这两个参数都填写authCode
就可以。其他的参数没有什么异议。
咱们拿到token
就可以获取其他的信息。例如获取 用户通讯录个人信息。
unionId
咱们通过前面的方式,是没有返回的,钉钉也给咱们做了处理可以传me
就可以获取当前授权用户的信息。这里说明获取这个是需要授权 权限的。搜索个人信息,开通标注的两个权限,就可以获取到用户的信息。
咱们获取到手机号和邮箱,就可以写咱们自己的业务逻辑了。
需要注意一个问题,咱们这个接口是钉钉回调的,前端是没办法知道咱们是否成功,所以页面的跳转也是咱们控制的。
如何控制呢,咱们接口返回值使用String
然后使用redirect:
重定向咱们需要的页面就可以了。登录失败就可以重定向账号密码页面,登录成功就可以返回咱们的首页或者自定义的页面。
这样流程就走完了。
我这里整理了一个util,帖到下面:
import com.aliyun.dingtalkcontact_1_0.models.GetUserResponse;
import com.aliyun.dingtalkoauth2_1_0.models.GetUserTokenResponse;
import com.aliyun.tea.TeaException;
import com.aliyun.teautil.models.RuntimeOptions;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiServiceGetCorpTokenRequest;
import com.dingtalk.api.request.OapiV2UserGetuserinfoRequest;
import com.dingtalk.api.response.OapiServiceGetCorpTokenResponse;
import com.dingtalk.api.response.OapiV2UserGetuserinfoResponse;
import com.pdm.core.cache.redis.RedisUtil;
import com.pdm.predamo.basis.constants.SystemCacheConstants;
import com.taobao.api.ApiException;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* @author king
* @date 2022年09月16日 09:34
*/
@Component
public class DingTalkUtil {
@Resource
RedisUtil redisUtil;
public static com.aliyun.dingtalkoauth2_1_0.Client createClientV2() throws Exception {
com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config();
config.protocol = "https";
config.regionId = "central";
return new com.aliyun.dingtalkoauth2_1_0.Client(config);
}
public static com.aliyun.dingtalkcontact_1_0.Client createClientV1() throws Exception {
com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config();
config.protocol = "https";
config.regionId = "central";
return new com.aliyun.dingtalkcontact_1_0.Client(config);
}
/**
* 获取用户Token
*
* @param authCode:授权Code,用于获取Token
* @return GetUserTokenResponse
* @author king<fsyvip666 @ gmail.com>
* @date 2022/9/16 10:20
*/
public static GetUserTokenResponse getUserToken(String authCode) throws Exception {
com.aliyun.dingtalkoauth2_1_0.Client client = createClientV2();
com.aliyun.dingtalkoauth2_1_0.models.GetUserTokenRequest getUserTokenRequest = new com.aliyun.dingtalkoauth2_1_0.models.GetUserTokenRequest()
.setClientSecret(DingtalkConstant.SUITE_SECRET)
.setClientId(DingtalkConstant.SUITE_KEY)
.setCode(authCode)
.setGrantType(DingtalkConstant.REFRESH_TOKEN)
.setRefreshToken(authCode);
try {
return client.getUserToken(getUserTokenRequest);
} catch (TeaException err) {
if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
// err 中含有 code 和 message 属性,可帮助开发定位问题
throw new RuntimeException(err);
}
} catch (Exception _err) {
TeaException err = new TeaException(_err.getMessage(), _err);
if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
// err 中含有 code 和 message 属性,可帮助开发定位问题
throw new RuntimeException(_err);
}
}
return null;
}
/**
* 获取用户通讯录个人信息
*
* @param accessToken : 鉴权Token
* @return GetUserResponse
* @author king<fsyvip666 @ gmail.com>
* @date 2022/9/16 10:31
*/
public static GetUserResponse getUserInfoByToken(String accessToken) throws Exception {
com.aliyun.dingtalkcontact_1_0.Client client = createClientV1();
com.aliyun.dingtalkcontact_1_0.models.GetUserHeaders getUserHeaders = new com.aliyun.dingtalkcontact_1_0.models.GetUserHeaders();
getUserHeaders.xAcsDingtalkAccessToken = accessToken;
try {
return client.getUserWithOptions(DingtalkConstant.ME, getUserHeaders, new RuntimeOptions());
} catch (TeaException err) {
if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
// err 中含有 code 和 message 属性
throw new RuntimeException(err);
}
} catch (Exception _err) {
TeaException err = new TeaException(_err.getMessage(), _err);
if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
// err 中含有 code 和 message 属性
throw new RuntimeException(_err);
}
}
return null;
}
我这里使用的是钉钉的SDK,直接引入SDK依赖就好了。
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>alibaba-dingtalk-service-sdk</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>dingtalk</artifactId>
<version>1.4.33</version>
</dependency>
就这么简单,到这里就完事了。其他的跟着文档来就好了。
积极向上:下一篇记录一下,钉钉内部第三方应用一键登录
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。