提交 626ceb22 编写于 作者: sq3536's avatar sq3536

钉钉免密

上级 a6bae625
...@@ -103,7 +103,14 @@ ...@@ -103,7 +103,14 @@
<artifactId>spring-ldap-core</artifactId> <artifactId>spring-ldap-core</artifactId>
</dependency> </dependency>
</dependencies> <dependency>
<groupId>com.aliyun</groupId>
<artifactId>alibaba-dingtalk-service-sdk</artifactId>
<version>1.0.1</version>
</dependency>
</dependencies>
<properties> <properties>
<maven.build.timestamp.format>yyyyMMddHHmmss</maven.build.timestamp.format> <maven.build.timestamp.format>yyyyMMddHHmmss</maven.build.timestamp.format>
......
package cn.ibizlab.core.uaa.extensions.service; package cn.ibizlab.core.uaa.extensions.service;
import cn.ibizlab.core.uaa.domain.SysOpenAccess;
import cn.ibizlab.core.uaa.domain.SysUserAuth; import cn.ibizlab.core.uaa.domain.SysUserAuth;
import cn.ibizlab.core.uaa.service.ISysOpenAccessService;
import cn.ibizlab.core.uaa.service.ISysUserAuthService; import cn.ibizlab.core.uaa.service.ISysUserAuthService;
import cn.ibizlab.util.domain.IBZUSER; import cn.ibizlab.util.domain.IBZUSER;
import cn.ibizlab.util.errors.BadRequestAlertException; import cn.ibizlab.util.errors.BadRequestAlertException;
import cn.ibizlab.util.errors.InternalServerErrorException;
import cn.ibizlab.util.security.AuthenticationUser;
import cn.ibizlab.util.service.AuthenticationUserService;
import cn.ibizlab.util.service.IBZUSERService; import cn.ibizlab.util.service.IBZUSERService;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.client.identify.Base64; import com.alibaba.nacos.client.identify.Base64;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiGettokenRequest;
import com.dingtalk.api.request.OapiSnsGetuserinfoBycodeRequest;
import com.dingtalk.api.request.OapiUserGetuserinfoRequest;
import com.dingtalk.api.response.OapiGettokenResponse;
import com.dingtalk.api.response.OapiSnsGetuserinfoBycodeResponse;
import com.dingtalk.api.response.OapiUserGetuserinfoResponse;
import com.taobao.api.ApiException;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity; import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.CloseableHttpResponse;
...@@ -25,6 +40,8 @@ import java.io.IOException; ...@@ -25,6 +40,8 @@ import java.io.IOException;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.security.InvalidKeyException; import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.sql.Wrapper;
import java.util.Date;
/** /**
* 实体[IBZUSER] 钉钉用户注册接口实现 * 实体[IBZUSER] 钉钉用户注册接口实现
...@@ -35,6 +52,10 @@ public class UserDingtalkRegisterService { ...@@ -35,6 +52,10 @@ public class UserDingtalkRegisterService {
@Autowired @Autowired
private IBZUSERService ibzuserService; private IBZUSERService ibzuserService;
@Autowired
private AuthenticationUserService authenticationUserService;
@Autowired @Autowired
private ISysUserAuthService sysUserAuthService; private ISysUserAuthService sysUserAuthService;
...@@ -75,76 +96,120 @@ public class UserDingtalkRegisterService { ...@@ -75,76 +96,120 @@ public class UserDingtalkRegisterService {
*/ */
public JSONObject requestDingtalkUserByCode(String code, long currentTimeMillis, String appId, String appSecret) { public JSONObject requestDingtalkUserByCode(String code, long currentTimeMillis, String appId, String appSecret) {
JSONObject returnObj = null; JSONObject returnObj = null;
CloseableHttpClient client = null; DefaultDingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/sns/getuserinfo_bycode");
OapiSnsGetuserinfoBycodeRequest req = new OapiSnsGetuserinfoBycodeRequest();
req.setTmpAuthCode(code);
try { try {
// 根据timestamp, appSecret计算签名值 OapiSnsGetuserinfoBycodeResponse response = client.execute(req,appId,appSecret);
String stringToSign = String.valueOf(currentTimeMillis);
Mac mac = Mac.getInstance("HmacSHA256"); if(response.getErrcode()!=0)
mac.init(new SecretKeySpec(appSecret.getBytes("UTF-8"), "HmacSHA256")); {
byte[] signatureBytes = mac.doFinal(stringToSign.getBytes("UTF-8")); throw new BadRequestAlertException(response.getErrmsg(), "UserDingtalkRegisterService", "");
String signature = new String(Base64.encodeBase64(signatureBytes));
String urlEncodeSignature = URLEncoder.encode(signature, "UTF-8");
// 通过临时授权码Code获取用户信息,临时授权码只能使用一次
String url = "https://oapi.dingtalk.com/sns/getuserinfo_bycode?accessKey=" + appId
+ "&timestamp=" + currentTimeMillis
+ "&signature=" + urlEncodeSignature;
// 创建httpclient对象
client = HttpClients.createDefault();
// 创建post方式请求对象
HttpPost httpPost = new HttpPost(url);
// 装填参数
JSONObject param = new JSONObject();
param.put("tmp_auth_code", code);
StringEntity jsonBody = new StringEntity(param.toString(), "UTF-8");
// 设置参数到请求对象中
httpPost.setEntity(jsonBody);
// 设置header信息
httpPost.setHeader("Content-type", "application/json");
httpPost.setHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
// 执行请求操作,并拿到结果(同步阻塞)
CloseableHttpResponse response = client.execute(httpPost);
// 获取结果实体
HttpEntity entity = response.getEntity();
JSONObject entityJson = null;
if (StringUtils.isEmpty(entity)) {
throw new BadRequestAlertException("钉钉服务端返回结果为空", "UserDingtalkRegisterService", "");
} else {
//按指定编码转换结果实体为String类型
entityJson = JSONObject.parseObject(EntityUtils.toString(entity, "UTF-8"));
// 是否获取钉钉用户信息成功
if (entityJson.getInteger("errcode")==0) {
// 这里只有简单的信息:nick、openid、unionid
returnObj = entityJson.getJSONObject("user_info");
} else {
throw new BadRequestAlertException(entityJson.getString("errmsg"), "UserDingtalkRegisterService", "");
}
} }
returnObj = (JSONObject)JSONObject.toJSON(response.getUserInfo());
} catch (ApiException e) {
e.printStackTrace();
throw new InternalServerErrorException("获取access_token失败");
}
return returnObj;
}
} catch (NoSuchAlgorithmException | InvalidKeyException e) { private long lastRefreshTime=System.currentTimeMillis()-7200001;
throw new BadRequestAlertException("钉钉生成安全签名失败", "UserDingtalkRegisterService", ""); private String accessToken="";
} catch (IOException e) { public boolean isExpire()
throw new BadRequestAlertException("连接钉钉服务端失败", "UserDingtalkRegisterService", ""); {
if(System.currentTimeMillis()<(lastRefreshTime+7200000))
{
System.currentTimeMillis();
return false;
} }
finally { return true;
if(client != null) { }
try {
client.close();
} catch (IOException e) { public synchronized String getAccessToken(String appKey,String appSecret)
} {
if(isExpire()) {
DefaultDingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/gettoken");
OapiGettokenRequest request = new OapiGettokenRequest();
request.setAppkey("appKey");
request.setAppsecret("appSecret");
request.setHttpMethod("GET");
try {
OapiGettokenResponse response = client.execute(request);
if(response.getErrcode()!=0||StringUtils.isEmpty(response.getAccessToken()))
throw new BadRequestAlertException("获取access_token失败","UserDingtalkRegisterService",response.getErrmsg());
lastRefreshTime = System.currentTimeMillis();
accessToken = response.getAccessToken();
} catch (ApiException e) {
e.printStackTrace();
throw new InternalServerErrorException("获取access_token失败");
} }
} }
return accessToken;
}
@Autowired
private ISysOpenAccessService sysOpenAccessService;
public SysOpenAccess getOpenAccess(String id)
{
final String accessid = StringUtils.isEmpty(id)?"dingtalk":id;
SysOpenAccess sysOpenAccess=sysOpenAccessService.getOne(Wrappers.<SysOpenAccess>lambdaQuery().eq(SysOpenAccess::getOpenType,"dingtalk").
and(wrapper -> wrapper.eq(SysOpenAccess::getAccessKey,accessid).or().eq(SysOpenAccess::getId,accessid)),false);
if(sysOpenAccess==null|| (sysOpenAccess.getDisabled()!=null && sysOpenAccess.getDisabled()==1))
throw new BadRequestAlertException("获取接入配置失败","UserDingtalkRegisterService","");
String accessToken = getAccessToken(sysOpenAccess.getAccessKey(),sysOpenAccess.getSecretKey());
if(!accessToken.equals(sysOpenAccess.getAccessToken()))
{
sysOpenAccess.setAccessToken(accessToken);
sysOpenAccessService.update(sysOpenAccess);
}
return returnObj; return sysOpenAccess;
} }
public AuthenticationUser getUserByToken(String id,String requestAuthCode)
{
final String accessid = StringUtils.isEmpty(id)?"dingtalk":id;
DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/user/getuserinfo");
OapiUserGetuserinfoRequest request = new OapiUserGetuserinfoRequest();
request.setCode(requestAuthCode);
request.setHttpMethod("GET");
OapiUserGetuserinfoResponse response = null;
try {
response = client.execute(request, accessToken);
if(response.getErrcode()!=0||StringUtils.isEmpty(response.getUserid()))
throw new BadRequestAlertException("获取user失败","UserDingtalkRegisterService",response.getErrmsg());
} catch (ApiException e) {
e.printStackTrace();
throw new InternalServerErrorException("获取user失败");
}
String userId = response.getUserid();
//先按userid或者username查
IBZUSER user = ibzuserService.getOne(Wrappers.<IBZUSER>lambdaQuery().eq(IBZUSER::getUserid,userId).or().eq(IBZUSER::getUsername,userId),false);
if(user==null)
{
//查不到情况下到auth表查真实userId
SysUserAuth userAuth = sysUserAuthService.getOne(Wrappers.<SysUserAuth>lambdaQuery().eq(SysUserAuth::getIdentityType,"dingtalk").eq(SysUserAuth::getIdentifier, userId),false);
// 该钉钉用户注册过账号,登录系统
if (userAuth!=null) {
user = ibzuserService.getById(userAuth.getUserid());
if(user==null)
throw new BadRequestAlertException("未找到"+userId+"对应系统用户","UserDingtalkRegisterService","");
AuthenticationUser curUser = authenticationUserService.loadUserByUsername(user.getLoginname()+(StringUtils.isEmpty(user.getDomains())?"":("|"+user.getDomains())));
return curUser;
}
}
return null;
}
} }
\ No newline at end of file
...@@ -9,6 +9,7 @@ import cn.ibizlab.util.domain.IBZUSER; ...@@ -9,6 +9,7 @@ import cn.ibizlab.util.domain.IBZUSER;
import cn.ibizlab.util.errors.BadRequestAlertException; import cn.ibizlab.util.errors.BadRequestAlertException;
import cn.ibizlab.util.helper.CachedBeanCopier; import cn.ibizlab.util.helper.CachedBeanCopier;
import cn.ibizlab.util.security.AuthTokenUtil; import cn.ibizlab.util.security.AuthTokenUtil;
import cn.ibizlab.util.security.AuthenticationInfo;
import cn.ibizlab.util.security.AuthenticationUser; import cn.ibizlab.util.security.AuthenticationUser;
import cn.ibizlab.util.service.AuthenticationUserService; import cn.ibizlab.util.service.AuthenticationUserService;
import cn.ibizlab.util.service.IBZUSERService; import cn.ibizlab.util.service.IBZUSERService;
...@@ -18,10 +19,7 @@ import org.springframework.beans.factory.annotation.Autowired; ...@@ -18,10 +19,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.UUID; import java.util.UUID;
...@@ -46,15 +44,16 @@ public class UserDingtalkRegisterResource { ...@@ -46,15 +44,16 @@ public class UserDingtalkRegisterResource {
/** /**
* 获取钉钉开放平台创建的网站应用appid * 获取钉钉开放平台创建的网站应用appid
*/ */
@GetMapping(value = "/uaa/getDingtalkAppId") @GetMapping(value = {"/uaa/getDingtalkAppId","/uaa/open/dingtalk/access_token","/uaa/open/dingtalk/appid"})
public ResponseEntity<JSONObject> getDingtalkAppId() { public ResponseEntity<JSONObject> getDingtalkAppId(@RequestParam(value = "id",required = false) String id) {
JSONObject obj = new JSONObject(); JSONObject obj = new JSONObject();
SysOpenAccess openAccess = openAccessService.getById("dingtalk"); SysOpenAccess openAccess = userDingtalkRegisterService.getOpenAccess(id);
if (openAccess==null || (openAccess.getDisabled()!=null && openAccess.getDisabled()==1)) if (openAccess==null || (openAccess.getDisabled()!=null && openAccess.getDisabled()==1))
return ResponseEntity.ok(obj); return ResponseEntity.ok(obj);
String appId = openAccess.getAccessKey();// qq互联appid String appId = openAccess.getAccessKey();
if (!StringUtils.isEmpty(appId)) { if (!StringUtils.isEmpty(appId)) {
obj.put("appid", appId); obj.put("appid", appId);
obj.put("access_token",openAccess.getAccessToken());
} }
return ResponseEntity.ok(obj); return ResponseEntity.ok(obj);
...@@ -68,15 +67,17 @@ public class UserDingtalkRegisterResource { ...@@ -68,15 +67,17 @@ public class UserDingtalkRegisterResource {
* @return * @return
*/ */
@PostMapping(value = "/uaa/queryDingtalkUserByCode") @PostMapping(value = "/uaa/queryDingtalkUserByCode")
public ResponseEntity<JSONObject> queryDingtalkUserByCode(@RequestBody JSONObject param) { public ResponseEntity<JSONObject> queryDingtalkUserByCode(@RequestParam(value = "id",required = false) String id,@RequestParam(value = "code",required = false) String tmpcode,@RequestBody JSONObject param) {
JSONObject object = new JSONObject(); JSONObject object = new JSONObject();
// 空校验 // 空校验
String code = param.getString("code"); String code = param.getString("code");
if (StringUtils.isEmpty(code))
code = tmpcode;
if (StringUtils.isEmpty(code)) if (StringUtils.isEmpty(code))
throw new BadRequestAlertException("code为空", "UserDingtalkRegisterResource", ""); throw new BadRequestAlertException("code为空", "UserDingtalkRegisterResource", "");
// 从数据库中获取钉钉授权应用信息 // 从数据库中获取钉钉授权应用信息
SysOpenAccess openAccess = openAccessService.getById("dingtalk"); SysOpenAccess openAccess = userDingtalkRegisterService.getOpenAccess(id);
if (openAccess==null || (openAccess.getDisabled()!=null && openAccess.getDisabled()==1)) if (openAccess==null || (openAccess.getDisabled()!=null && openAccess.getDisabled()==1))
throw new BadRequestAlertException("未找到配置", "UserDingtalkRegisterResource", ""); throw new BadRequestAlertException("未找到配置", "UserDingtalkRegisterResource", "");
String appId = openAccess.getAccessKey();// 个人应用开发过程中的唯一性标识AppId String appId = openAccess.getAccessKey();// 个人应用开发过程中的唯一性标识AppId
...@@ -95,7 +96,7 @@ public class UserDingtalkRegisterResource { ...@@ -95,7 +96,7 @@ public class UserDingtalkRegisterResource {
} }
// 根据openid查用户授权信息 // 根据openid查用户授权信息
SysUserAuth userAuth = sysUserAuthService.getOne(Wrappers.<SysUserAuth>query().eq("identifier", openid)); SysUserAuth userAuth = sysUserAuthService.getOne(Wrappers.<SysUserAuth>lambdaQuery().eq(SysUserAuth::getIdentityType,"dingtalk").eq(SysUserAuth::getIdentifier, openid));
// 该钉钉用户注册过账号,登录系统 // 该钉钉用户注册过账号,登录系统
if (!StringUtils.isEmpty(userAuth)) { if (!StringUtils.isEmpty(userAuth)) {
IBZUSER ibzuser = ibzuserService.getById(userAuth.getUserid()); IBZUSER ibzuser = ibzuserService.getById(userAuth.getUserid());
...@@ -182,4 +183,21 @@ public class UserDingtalkRegisterResource { ...@@ -182,4 +183,21 @@ public class UserDingtalkRegisterResource {
} }
@GetMapping(value = {"/uaa/open/dingtalk/auth/{code}"})
public ResponseEntity<AuthenticationInfo> getUserByToken(@PathVariable(value = "code") String code, @RequestParam(value = "id",required = false) String id) {
AuthenticationUser user=userDingtalkRegisterService.getUserByToken(id,code);
final String token = jwtTokenUtil.generateToken(user);
AuthenticationUser user2=new AuthenticationUser();
CachedBeanCopier.copy(user,user2);
user2.setAuthorities(null);
user2.setPermissionList(null);
// 返回 token
return ResponseEntity.ok().body(new AuthenticationInfo(token,user2));
}
} }
Markdown 格式
0% or
您添加了 0 到此讨论。请谨慎行事。
先完成此消息的编辑!
想要评论请 注册