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

钉钉免密

上级 a6bae625
......@@ -103,7 +103,14 @@
<artifactId>spring-ldap-core</artifactId>
</dependency>
</dependencies>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>alibaba-dingtalk-service-sdk</artifactId>
<version>1.0.1</version>
</dependency>
</dependencies>
<properties>
<maven.build.timestamp.format>yyyyMMddHHmmss</maven.build.timestamp.format>
......
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.service.ISysOpenAccessService;
import cn.ibizlab.core.uaa.service.ISysUserAuthService;
import cn.ibizlab.util.domain.IBZUSER;
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 com.alibaba.fastjson.JSONObject;
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 org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
......@@ -25,6 +40,8 @@ import java.io.IOException;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.sql.Wrapper;
import java.util.Date;
/**
* 实体[IBZUSER] 钉钉用户注册接口实现
......@@ -35,6 +52,10 @@ public class UserDingtalkRegisterService {
@Autowired
private IBZUSERService ibzuserService;
@Autowired
private AuthenticationUserService authenticationUserService;
@Autowired
private ISysUserAuthService sysUserAuthService;
......@@ -75,76 +96,120 @@ public class UserDingtalkRegisterService {
*/
public JSONObject requestDingtalkUserByCode(String code, long currentTimeMillis, String appId, String appSecret) {
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 {
// 根据timestamp, appSecret计算签名值
String stringToSign = String.valueOf(currentTimeMillis);
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(appSecret.getBytes("UTF-8"), "HmacSHA256"));
byte[] signatureBytes = mac.doFinal(stringToSign.getBytes("UTF-8"));
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", "");
}
OapiSnsGetuserinfoBycodeResponse response = client.execute(req,appId,appSecret);
if(response.getErrcode()!=0)
{
throw new BadRequestAlertException(response.getErrmsg(), "UserDingtalkRegisterService", "");
}
returnObj = (JSONObject)JSONObject.toJSON(response.getUserInfo());
} catch (ApiException e) {
e.printStackTrace();
throw new InternalServerErrorException("获取access_token失败");
}
return returnObj;
}
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
throw new BadRequestAlertException("钉钉生成安全签名失败", "UserDingtalkRegisterService", "");
} catch (IOException e) {
throw new BadRequestAlertException("连接钉钉服务端失败", "UserDingtalkRegisterService", "");
private long lastRefreshTime=System.currentTimeMillis()-7200001;
private String accessToken="";
public boolean isExpire()
{
if(System.currentTimeMillis()<(lastRefreshTime+7200000))
{
System.currentTimeMillis();
return false;
}
finally {
if(client != null) {
try {
client.close();
} catch (IOException e) {
}
return true;
}
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;
import cn.ibizlab.util.errors.BadRequestAlertException;
import cn.ibizlab.util.helper.CachedBeanCopier;
import cn.ibizlab.util.security.AuthTokenUtil;
import cn.ibizlab.util.security.AuthenticationInfo;
import cn.ibizlab.util.security.AuthenticationUser;
import cn.ibizlab.util.service.AuthenticationUserService;
import cn.ibizlab.util.service.IBZUSERService;
......@@ -18,10 +19,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import java.util.UUID;
......@@ -46,15 +44,16 @@ public class UserDingtalkRegisterResource {
/**
* 获取钉钉开放平台创建的网站应用appid
*/
@GetMapping(value = "/uaa/getDingtalkAppId")
public ResponseEntity<JSONObject> getDingtalkAppId() {
@GetMapping(value = {"/uaa/getDingtalkAppId","/uaa/open/dingtalk/access_token","/uaa/open/dingtalk/appid"})
public ResponseEntity<JSONObject> getDingtalkAppId(@RequestParam(value = "id",required = false) String id) {
JSONObject obj = new JSONObject();
SysOpenAccess openAccess = openAccessService.getById("dingtalk");
SysOpenAccess openAccess = userDingtalkRegisterService.getOpenAccess(id);
if (openAccess==null || (openAccess.getDisabled()!=null && openAccess.getDisabled()==1))
return ResponseEntity.ok(obj);
String appId = openAccess.getAccessKey();// qq互联appid
String appId = openAccess.getAccessKey();
if (!StringUtils.isEmpty(appId)) {
obj.put("appid", appId);
obj.put("access_token",openAccess.getAccessToken());
}
return ResponseEntity.ok(obj);
......@@ -68,15 +67,17 @@ public class UserDingtalkRegisterResource {
* @return
*/
@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();
// 空校验
String code = param.getString("code");
if (StringUtils.isEmpty(code))
code = tmpcode;
if (StringUtils.isEmpty(code))
throw new BadRequestAlertException("code为空", "UserDingtalkRegisterResource", "");
// 从数据库中获取钉钉授权应用信息
SysOpenAccess openAccess = openAccessService.getById("dingtalk");
SysOpenAccess openAccess = userDingtalkRegisterService.getOpenAccess(id);
if (openAccess==null || (openAccess.getDisabled()!=null && openAccess.getDisabled()==1))
throw new BadRequestAlertException("未找到配置", "UserDingtalkRegisterResource", "");
String appId = openAccess.getAccessKey();// 个人应用开发过程中的唯一性标识AppId
......@@ -95,7 +96,7 @@ public class UserDingtalkRegisterResource {
}
// 根据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)) {
IBZUSER ibzuser = ibzuserService.getById(userAuth.getUserid());
......@@ -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 到此讨论。请谨慎行事。
先完成此消息的编辑!
想要评论请 注册