项目场景:
公司的组织架构下有多个部门,最近在其中一个部门下做了一个h5微应用,但这几天需要把这个h5微应用移到更上级的一个部门下,项目前后端地址不变。此时就出现了这个有意思的问题。问题描述:
在进行钉钉免登陆时,报错"不存在的临时授权码40078"。
钉钉免登陆代码:
@ApiOperation(value="钉钉授权免登陆", notes="钉钉授权免登陆")
@GetMapping(value = "/login")
public Result<?> login(@ApiParam(name = "authCode",value = "免登授权码",required = true) @RequestParam("authCode") String authCode) {
if (StrUtil.isBlank(authCode)){
throw new JeecgBootException("授权码不能为空");
}
String accessToken = dingtalkTokenService.getAccessToken();
DingTalkClient dingTalkClient = new DefaultDingTalkClient(getuserinfo);
OapiUserGetuserinfoRequest oapiUserGetuserinfoRequest = new OapiUserGetuserinfoRequest();
oapiUserGetuserinfoRequest.setCode(authCode);
oapiUserGetuserinfoRequest.setHttpMethod(Method.GET.toString());
try {
OapiUserGetuserinfoResponse oapiUserGetuserinfoResponse = dingTalkClient.execute(oapiUserGetuserinfoRequest, accessToken);
Console.log("oapiUserGetuserinfoResponse:"+oapiUserGetuserinfoResponse.getBody());
if (oapiUserGetuserinfoResponse.getErrcode() == 0){
// 40078 授权码不存在
JSONObject userInfoJSONObject = JSONUtil.parseObj(oapiUserGetuserinfoResponse.getBody()).getJSONObject("result");
String userid = userInfoJSONObject.getStr("userid");
dingTalkClient = new DefaultDingTalkClient(userGet);
OapiV2UserGetRequest oapiV2UserGetRequest = new OapiV2UserGetRequest();
oapiV2UserGetRequest.setUserid(userid);
OapiV2UserGetResponse oapiV2UserGetResponse = dingTalkClient.execute(oapiV2UserGetRequest, accessToken);
OapiV2UserGetResponse.UserGetResponse userGetResponse = oapiV2UserGetResponse.getResult();
DingtalkUserVo dingtalkUserVo = new DingtalkUserVo();
break;
int expire = RedisKeyConstant.DXC_H5_USER_TOKEN_EXPIRE*168; //3600
dingtalkUserVo
.setAccessToken(IdUtil.fastSimpleUUID())
.setTokenTime(new Date())
.setExpire(expire)
.setUserId(userid)
.setUserName(userInfoJSONObject.getStr("name"))
.setUserMobile(userGetResponse.getMobile())
.setAvatar(userGetResponse.getAvatar());
redisUtil.set(RedisKeyConstant.DXC_H5_USER_TOKEN+dingtalkUserVo.getAccessToken(),
JSONUtil.parseObj(dingtalkUserVo,true)
.setDateFormat("yyyy-MM-dd HH:mm:ss").toString(), expire);
return Result.ok(dingtalkUserVo);
}else {
throw new JeecgBootException(oapiUserGetuserinfoResponse.getErrmsg());
}
} catch (Exception e) {
e.printStackTrace();
throw new JeecgBootException(e.getMessage());
}
}
原因分析:
项目移植前是没有问题的,但移植后就开始报这个问题,然后就查了一下导致此问题的原因:
1、前端没有获取到code
2、获取到的code没有正确传入后台接口参数中
3、code超过了五分钟的有效期
4、code在传入接口参数之前已经被使用过了,code只能使用一次
在此处分析一下这四个原因,明显可以看到是在获取和使用code时出现的问题,因为项目移植前后代码没有发生变化,只有微应用的appkey、appsecret、AgentId和corp-id发生了变化,主要涉及的是获取code用到的crop-id,我们先来看一下获取code的过程:
首先,获取到code的方式没有问题,而且在拿到code后立马请求的免登陆接口,所以上述4个原因都不是。那么到底是哪里出现的问题呢???
让我们来想一想移植前后有哪些变化:
1、应用凭证(appkey、appsecret、AgentId、corp-id)
2、部门
由此可以看出来,项目根本就没有什么变动,移植前没有任何问题,为什么移植后就这样了???
解决方案:
这个问题还没有解决,但第二天就莫名其妙的好了。 在此说我的一个猜想(这个解决方法还没有实行就自己好了): 为了防止每次都要去请求获取token,所以带代码中已经把获取到的token放入缓存中,并行失效时间与钉钉token保持一致。那么重点来了!!!因为项目位置不变,所以在移植后,缓存中的token可能还没有失效,并且在调用免登陆接口的时候被获取到,从而导致出错。等有时间模拟验证一下,有相似经历的也可以试一下这个解决方法,然后告知一下怎么样,一起讨论