Merge remote-tracking branch 'base-version/main' into test

# Conflicts:
#	zt-module-bpm/zt-module-bpm-server/src/main/java/com/zt/plat/module/bpm/api/task/BpmProcessInstanceApiImpl.java
#	zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/service/auth/AdminAuthServiceImpl.java
This commit is contained in:
chenbowen
2025-09-28 00:40:55 +08:00
26 changed files with 1382 additions and 30 deletions

View File

@@ -179,4 +179,28 @@ public class AuthController {
return success(authService.socialLogin(reqVO));
}
@PostMapping("/oauth2/callback")
@PermitAll
@Operation(summary = "OAuth2回调处理", description = "处理第三方OAuth2认证回调")
@TenantIgnore
public CommonResult<AuthLoginRespVO> oauth2Callback(@RequestBody @Valid AuthOAuth2CallbackReqVO reqVO) {
return success(authService.oauth2Callback(reqVO));
}
@GetMapping("/check-user-type")
@PermitAll
@Operation(summary = "检查用户类型", description = "根据用户名判断是内部用户还是外部用户")
@TenantIgnore
public CommonResult<AuthUserTypeRespVO> checkUserType(@RequestParam("username") String username) {
return success(authService.checkUserType(username));
}
@GetMapping("/get-eban-login-url")
@PermitAll
@Operation(summary = "获取e办登录URL", description = "获取e办系统的OAuth2登录地址")
@TenantIgnore
public CommonResult<String> getEbanLoginUrl() {
return success(authService.getEbanLoginUrl());
}
}

View File

@@ -0,0 +1,24 @@
package com.zt.plat.module.system.controller.admin.auth.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Schema(description = "管理后台 - OAuth2回调 Request VO")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class AuthOAuth2CallbackReqVO {
@Schema(description = "授权码", requiredMode = Schema.RequiredMode.REQUIRED, example = "abc123")
@NotEmpty(message = "授权码不能为空")
private String code;
@Schema(description = "状态参数", example = "111")
private String state;
}

View File

@@ -0,0 +1,22 @@
package com.zt.plat.module.system.controller.admin.auth.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Schema(description = "管理后台 - 用户类型检查 Response VO")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class AuthUserTypeRespVO {
@Schema(description = "是否为内部用户E办用户", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
private Boolean isInternal;
@Schema(description = "E办登录跳转URL", example = "http://10.2.137.42/idp/oauth2/authorize?...")
private String ebanLoginUrl;
}

View File

@@ -93,4 +93,27 @@ public interface AdminAuthService {
*/
void resetPassword(AuthResetPasswordReqVO reqVO);
/**
* OAuth2回调处理
*
* @param reqVO OAuth2回调信息
* @return 登录结果
*/
AuthLoginRespVO oauth2Callback(AuthOAuth2CallbackReqVO reqVO);
/**
* 检查用户类型
*
* @param username 用户名
* @return 用户类型信息
*/
AuthUserTypeRespVO checkUserType(String username);
/**
* 获取e办登录URL
*
* @return e办系统的OAuth2登录地址
*/
String getEbanLoginUrl();
}

View File

@@ -1,10 +1,6 @@
package com.zt.plat.module.system.service.auth;
import cn.hutool.core.util.ObjectUtil;
import com.anji.captcha.model.common.ResponseModel;
import com.anji.captcha.model.vo.CaptchaVO;
import com.anji.captcha.service.CaptchaService;
import com.google.common.annotations.VisibleForTesting;
import com.zt.plat.framework.common.enums.CommonStatusEnum;
import com.zt.plat.framework.common.enums.UserTypeEnum;
import com.zt.plat.framework.common.util.monitor.TracerUtils;
@@ -26,8 +22,14 @@ import com.zt.plat.module.system.enums.sms.SmsSceneEnum;
import com.zt.plat.module.system.service.logger.LoginLogService;
import com.zt.plat.module.system.service.member.MemberService;
import com.zt.plat.module.system.service.oauth2.OAuth2TokenService;
import com.zt.plat.module.system.service.oauth2.EbanOAuth2Service;
import com.zt.plat.module.system.service.social.SocialUserService;
import com.zt.plat.module.system.service.user.AdminUserService;
import com.zt.plat.module.system.enums.user.UserSourceEnum;
import com.anji.captcha.model.common.ResponseModel;
import com.anji.captcha.model.vo.CaptchaVO;
import com.anji.captcha.service.CaptchaService;
import com.google.common.annotations.VisibleForTesting;
import jakarta.annotation.Resource;
import jakarta.validation.Validator;
import lombok.Setter;
@@ -68,9 +70,24 @@ public class AdminAuthServiceImpl implements AdminAuthService {
private CaptchaService captchaService;
@Resource
private SmsCodeApi smsCodeApi;
@Resource
private EbanOAuth2Service ebanOAuth2Service;
@Value("${sync.encrypt-key}")
private String encryptKey;
// E办OAuth2配置
@Value("${eban.oauth2.authorize-url:http://10.2.137.42/idp/oauth2/authorize}")
private String ebanAuthorizeUrl;
@Value("${eban.oauth2.client-id:tyszhjyglxt}")
private String ebanClientId;
@Value("${eban.oauth2.redirect-uri:http://172.16.46.63:30080/system/oauth2/callback}")
private String ebanRedirectUri;
@Value("${eban.oauth2.response-type:code}")
private String ebanResponseType;
/**
* 验证码的开关,默认为 true
*/
@@ -113,6 +130,12 @@ public class AdminAuthServiceImpl implements AdminAuthService {
// 使用账号密码,进行登录
AdminUserDO user = authenticate(reqVO.getUsername(), reqVO.getPassword());
// 检查是否为内部用户,内部用户不允许账号密码登录
if (isInternalUser(user)) {
createLoginLog(user.getId(), reqVO.getUsername(), LoginLogTypeEnum.LOGIN_USERNAME, LoginResultEnum.BAD_CREDENTIALS);
throw exception(AUTH_LOGIN_INTERNAL_USER_PASSWORD_NOT_ALLOWED);
}
// 如果 socialType 非空,说明需要绑定社交用户
if (reqVO.getSocialType() != null) {
@@ -130,6 +153,12 @@ public class AdminAuthServiceImpl implements AdminAuthService {
// 使用账号密码,进行登录(跳过验证码校验)
AdminUserDO user = authenticate(reqVO.getUsername(), reqVO.getPassword());
// 检查是否为内部用户,内部用户不允许账号密码登录
if (isInternalUser(user)) {
createLoginLog(user.getId(), reqVO.getUsername(), LoginLogTypeEnum.LOGIN_USERNAME, LoginResultEnum.BAD_CREDENTIALS);
throw exception(AUTH_LOGIN_INTERNAL_USER_PASSWORD_NOT_ALLOWED);
}
// 创建 Token 令牌,记录登录日志
return createTokenAfterLoginSuccess(user.getId(), reqVO.getUsername(), LoginLogTypeEnum.LOGIN_USERNAME);
@@ -345,4 +374,75 @@ public class AdminAuthServiceImpl implements AdminAuthService {
throw exception(AUTH_TEST_LOGIN_NOT_ALLOWED);
}
}
@Override
public AuthLoginRespVO oauth2Callback(AuthOAuth2CallbackReqVO reqVO) {
// 委托给专门的E办OAuth2服务处理
return ebanOAuth2Service.handleCallback(reqVO);
}
@Override
public AuthUserTypeRespVO checkUserType(String username) {
AdminUserDO user = userService.getUserByUsername(username);
// 用户不存在,抛出异常
if (user == null) {
throw exception(USER_NOT_EXISTS);
}
// 判断用户类型
boolean isInternal = isInternalUser(user);
AuthUserTypeRespVO.AuthUserTypeRespVOBuilder builder = AuthUserTypeRespVO.builder()
.isInternal(isInternal);
// 如果是内部用户生成E办登录URL
if (isInternal) {
String ebanLoginUrl = buildEbanLoginUrl();
builder.ebanLoginUrl(ebanLoginUrl);
}
return builder.build();
}
/**
* 判断是否为内部用户
* 根据UserSourceEnum判断同步用户为内部用户外部用户为外部用户
*/
private boolean isInternalUser(AdminUserDO user) {
// 根据userSource字段判断用户类型
Integer userSource = user.getUserSource();
// 同步用户(SYNC = 2)为内部用户需要使用E办登录
if (userSource != null && userSource.equals(UserSourceEnum.SYNC.getSource())) {
return true;
}
// 外部用户(EXTERNAL = 1)或其他情况为外部用户,使用账号密码登录
return false;
}
/**
* 根据部门ID获取部门名称
*/
private String getDeptName(Long deptId) {
// 这里需要调用部门服务获取部门信息
// 暂时返回null实际项目中需要实现
return null;
}
/**
* 构建E办登录URL
*/
private String buildEbanLoginUrl() {
String state = "login_" + System.currentTimeMillis();
return String.format("%s?client_id=%s&redirect_uri=%s&response_type=%s&state=%s",
ebanAuthorizeUrl, ebanClientId, ebanRedirectUri, ebanResponseType, state);
}
@Override
public String getEbanLoginUrl() {
return buildEbanLoginUrl();
}
}

View File

@@ -0,0 +1,71 @@
package com.zt.plat.module.system.service.oauth2;
import com.zt.plat.module.system.controller.admin.auth.vo.AuthOAuth2CallbackReqVO;
import com.zt.plat.module.system.controller.admin.auth.vo.AuthLoginRespVO;
/**
* E办OAuth2服务接口
*
* @author ZT
*/
public interface EbanOAuth2Service {
/**
* 处理E办OAuth2回调
*
* @param reqVO OAuth2回调请求
* @return 登录结果
*/
AuthLoginRespVO handleCallback(AuthOAuth2CallbackReqVO reqVO);
/**
* 通过授权码获取用户信息
*
* @param code 授权码
* @param state 状态参数
* @return 用户信息
*/
EbanUserInfo getUserInfo(String code, String state);
/**
* E办用户信息
*/
class EbanUserInfo {
private String username;
private String realName;
private String email;
private String mobile;
private String deptName;
private EbanOAuth2ServiceImpl.EbanTokenInfo tokenInfo; // 添加Token信息
// 构造函数
public EbanUserInfo() {}
public EbanUserInfo(String username, String realName, String email, String mobile, String deptName) {
this.username = username;
this.realName = realName;
this.email = email;
this.mobile = mobile;
this.deptName = deptName;
}
// getter和setter方法
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public String getRealName() { return realName; }
public void setRealName(String realName) { this.realName = realName; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
public String getMobile() { return mobile; }
public void setMobile(String mobile) { this.mobile = mobile; }
public String getDeptName() { return deptName; }
public void setDeptName(String deptName) { this.deptName = deptName; }
public EbanOAuth2ServiceImpl.EbanTokenInfo getTokenInfo() { return tokenInfo; }
public void setTokenInfo(EbanOAuth2ServiceImpl.EbanTokenInfo tokenInfo) { this.tokenInfo = tokenInfo; }
}
}

View File

@@ -0,0 +1,341 @@
package com.zt.plat.module.system.service.oauth2;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.zt.plat.framework.common.enums.CommonStatusEnum;
import com.zt.plat.module.system.controller.admin.auth.vo.AuthOAuth2CallbackReqVO;
import com.zt.plat.module.system.controller.admin.auth.vo.AuthLoginRespVO;
import com.zt.plat.module.system.convert.auth.AuthConvert;
import com.zt.plat.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
import com.zt.plat.module.system.dal.dataobject.user.AdminUserDO;
import com.zt.plat.module.system.enums.logger.LoginLogTypeEnum;
import com.zt.plat.module.system.enums.logger.LoginResultEnum;
import com.zt.plat.module.system.enums.oauth2.OAuth2ClientConstants;
import com.zt.plat.module.system.service.logger.LoginLogService;
import com.zt.plat.module.system.service.user.AdminUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
import static com.zt.plat.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.zt.plat.framework.common.util.servlet.ServletUtils.getClientIP;
import static com.zt.plat.module.system.enums.ErrorCodeConstants.*;
/**
* E办OAuth2服务实现类
*
* @author ZT
*/
@Service
@Slf4j
public class EbanOAuth2ServiceImpl implements EbanOAuth2Service {
@Resource
private AdminUserService userService;
@Resource
private LoginLogService loginLogService;
@Resource
private OAuth2TokenService oauth2TokenService;
@Resource
private EbanTokenService ebanTokenService;
@Value("${eban.oauth2.auth-server.base-url:http://10.2.137.42/idp/oauth2}")
private String authServerBaseUrl;
@Value("${eban.oauth2.auth-server.client-id:tyszhjyglxt}")
private String clientId;
@Value("${eban.oauth2.auth-server.client-secret:}")
private String clientSecret;
@Value("${eban.oauth2.user-info.url:http://10.2.137.42/idp/oauth2/getUserInfo}")
private String userInfoUrl;
@Value("${eban.oauth2.token.url:http://10.2.137.42/idp/oauth2/getToken}")
private String tokenUrl;
@Override
public AuthLoginRespVO handleCallback(AuthOAuth2CallbackReqVO reqVO) {
log.info("处理E办OAuth2回调: code={}, state={}", reqVO.getCode(), reqVO.getState());
try {
// 1. 通过授权码获取用户信息
EbanUserInfo userInfo = getUserInfo(reqVO.getCode(), reqVO.getState());
if (userInfo == null || StrUtil.isBlank(userInfo.getUsername())) {
throw exception(AUTH_LOGIN_BAD_CREDENTIALS);
}
// 2. 根据用户名查找系统用户
AdminUserDO user = userService.getUserByUsername(userInfo.getUsername());
if (user == null) {
// 用户不存在,记录登录失败日志
createLoginLog(null, userInfo.getUsername(), LoginLogTypeEnum.LOGIN_SOCIAL, LoginResultEnum.BAD_CREDENTIALS);
throw exception(USER_NOT_EXISTS);
}
// 3. 校验用户状态
if (CommonStatusEnum.isDisable(user.getStatus())) {
createLoginLog(user.getId(), userInfo.getUsername(), LoginLogTypeEnum.LOGIN_SOCIAL, LoginResultEnum.USER_DISABLED);
throw exception(AUTH_LOGIN_USER_DISABLED);
}
// 4. 保存E办token到现有OAuth2表中
try {
EbanTokenInfo tokenInfo = userInfo.getTokenInfo();
if (tokenInfo != null) {
// 将用户信息转换为JSON字符串
JSONObject ebanUserInfoJson = new JSONObject();
ebanUserInfoJson.put("username", userInfo.getUsername());
ebanUserInfoJson.put("realName", userInfo.getRealName());
ebanUserInfoJson.put("email", userInfo.getEmail());
ebanUserInfoJson.put("mobile", userInfo.getMobile());
ebanUserInfoJson.put("deptName", userInfo.getDeptName());
ebanTokenService.createEbanToken(
user.getId(), // 使用用户ID
tokenInfo.getAccessToken(),
tokenInfo.getRefreshToken(),
tokenInfo.getExpiresIn(),
tokenInfo.getUid(),
ebanUserInfoJson.toString()
);
log.info("成功保存E办token到OAuth2表用户ID: {}, 用户名: {}, uid: {}",
user.getId(), userInfo.getUsername(), tokenInfo.getUid());
}
} catch (Exception e) {
log.error("保存E办token失败用户: " + userInfo.getUsername(), e);
// 保存token失败不影响登录流程继续执行
}
// 5. 创建Token令牌记录登录日志
return createTokenAfterLoginSuccess(user.getId(), userInfo.getUsername(), LoginLogTypeEnum.LOGIN_SOCIAL);
} catch (Exception e) {
log.error("E办OAuth2回调处理失败", e);
if (e.getMessage().contains("USER_NOT_EXISTS") || e.getMessage().contains("AUTH_LOGIN_USER_DISABLED")) {
throw e; // 重新抛出业务异常
}
throw exception(AUTH_LOGIN_BAD_CREDENTIALS);
}
}
@Override
public EbanUserInfo getUserInfo(String code, String state) {
try {
// 1. 使用授权码换取access_token
EbanTokenInfo tokenInfo = exchangeAccessToken(code, state);
if (tokenInfo == null || StrUtil.isBlank(tokenInfo.getAccessToken())) {
log.error("获取access_token失败");
return null;
}
// 2. 使用access_token获取用户信息
EbanUserInfo userInfo = fetchUserInfo(tokenInfo.getAccessToken());
if (userInfo != null) {
// 将Token信息保存到用户信息中以便后续使用
userInfo.setTokenInfo(tokenInfo);
}
return userInfo;
} catch (Exception e) {
log.error("获取E办用户信息失败", e);
return null;
}
}
/**
* E办Token信息
*/
public static class EbanTokenInfo {
private String accessToken;
private String refreshToken;
private Integer expiresIn;
private String uid;
private String createDate;
// 构造函数和getter/setter方法
public EbanTokenInfo() {}
public EbanTokenInfo(String accessToken, String refreshToken, Integer expiresIn, String uid, String createDate) {
this.accessToken = accessToken;
this.refreshToken = refreshToken;
this.expiresIn = expiresIn;
this.uid = uid;
this.createDate = createDate;
}
public String getAccessToken() { return accessToken; }
public void setAccessToken(String accessToken) { this.accessToken = accessToken; }
public String getRefreshToken() { return refreshToken; }
public void setRefreshToken(String refreshToken) { this.refreshToken = refreshToken; }
public Integer getExpiresIn() { return expiresIn; }
public void setExpiresIn(Integer expiresIn) { this.expiresIn = expiresIn; }
public String getUid() { return uid; }
public void setUid(String uid) { this.uid = uid; }
public String getCreateDate() { return createDate; }
public void setCreateDate(String createDate) { this.createDate = createDate; }
}
/**
* 使用授权码换取access_token
*/
private EbanTokenInfo exchangeAccessToken(String code, String state) {
try {
// 根据e办API规范构建请求参数
Map<String, Object> params = new HashMap<>();
params.put("client_id", clientId);
params.put("client_secret", clientSecret);
params.put("code", code);
params.put("grant_type", "authorization_code");
log.info("请求e办获取token参数: client_id={}, code={}", clientId, code);
HttpResponse response = HttpRequest.post(tokenUrl)
.form(params)
.timeout(10000)
.execute();
if (!response.isOk()) {
log.error("获取access_token失败HTTP状态码: {}, 响应: {}", response.getStatus(), response.body());
return null;
}
JSONObject jsonResponse = JSONUtil.parseObj(response.body());
// 检查是否有错误码
if (jsonResponse.containsKey("errcode")) {
log.error("获取access_token失败错误码: {}, 错误信息: {}",
jsonResponse.getStr("errcode"), jsonResponse.getStr("msg"));
return null;
}
String accessToken = jsonResponse.getStr("access_token");
String refreshToken = jsonResponse.getStr("refresh_token");
Integer expiresIn = jsonResponse.getInt("expires_in");
String uid = jsonResponse.getStr("uid");
String createDate = jsonResponse.getStr("createDate");
log.info("成功获取access_tokenuid: {}, expires_in: {}", uid, expiresIn);
return new EbanTokenInfo(accessToken, refreshToken, expiresIn, uid, createDate);
} catch (Exception e) {
log.error("调用e办token接口异常", e);
return null;
}
}
/**
* 使用access_token获取用户信息
*/
private EbanUserInfo fetchUserInfo(String accessToken) {
try {
// 根据e办API规范构建请求参数
Map<String, Object> params = new HashMap<>();
params.put("client_id", clientId);
params.put("access_token", accessToken);
log.info("请求e办获取用户信息client_id: {}", clientId);
HttpResponse response = HttpRequest.get(userInfoUrl)
.form(params)
.timeout(10000)
.execute();
if (!response.isOk()) {
log.error("获取用户信息失败HTTP状态码: {}, 响应: {}", response.getStatus(), response.body());
return null;
}
JSONObject userJson = JSONUtil.parseObj(response.body());
// 检查是否有错误码
if (userJson.containsKey("errcode")) {
log.error("获取用户信息失败,错误码: {}, 错误信息: {}",
userJson.getStr("errcode"), userJson.getStr("msg"));
return null;
}
// 解析用户信息根据e办系统的实际返回格式调整
EbanUserInfo userInfo = new EbanUserInfo();
// 根据API文档主要字段是loginName和spRoleList
String loginName = userJson.getStr("loginName");
if (StrUtil.isBlank(loginName)) {
log.error("用户信息中缺少loginName字段");
return null;
}
userInfo.setUsername(loginName); // 使用loginName作为用户名
// 如果有spRoleList可以取第一个作为真实姓名或其他用途
if (userJson.containsKey("spRoleList")) {
Object spRoleListObj = userJson.get("spRoleList");
if (spRoleListObj instanceof java.util.List) {
@SuppressWarnings("unchecked")
java.util.List<String> spRoleList = (java.util.List<String>) spRoleListObj;
if (!spRoleList.isEmpty()) {
userInfo.setRealName(spRoleList.get(0));
}
}
}
// 其他可能的字段根据实际e办返回的字段调整
userInfo.setEmail(userJson.getStr("email"));
userInfo.setMobile(userJson.getStr("mobile"));
userInfo.setDeptName(userJson.getStr("deptName"));
log.info("成功获取用户信息: username={}, realName={}", userInfo.getUsername(), userInfo.getRealName());
return userInfo;
} catch (Exception e) {
log.error("调用e办用户信息接口异常", e);
return null;
}
}
/**
* 创建登录日志
*/
private void createLoginLog(Long userId, String username, LoginLogTypeEnum logType, LoginResultEnum loginResult) {
// 这里可以复用AdminAuthServiceImpl中的createLoginLog逻辑
// 为了简化,这里省略实现
log.info("创建登录日志: userId={}, username={}, logType={}, result={}",
userId, username, logType, loginResult);
}
/**
* 登录成功后创建Token
*/
private AuthLoginRespVO createTokenAfterLoginSuccess(Long userId, String username, LoginLogTypeEnum logType) {
// 插入登陆日志
createLoginLog(userId, username, logType, LoginResultEnum.SUCCESS);
// 创建访问令牌
OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.createAccessToken(
userId,
com.zt.plat.framework.common.enums.UserTypeEnum.ADMIN.getValue(),
OAuth2ClientConstants.CLIENT_ID_DEFAULT,
null
);
// 构建返回结果
return AuthConvert.INSTANCE.convert(accessTokenDO);
}
}

View File

@@ -0,0 +1,65 @@
package com.zt.plat.module.system.service.oauth2;
import com.zt.plat.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
import com.zt.plat.module.system.dal.dataobject.oauth2.OAuth2RefreshTokenDO;
/**
* E办Token管理服务接口基于现有OAuth2 Token体系
*
* @author ZT
*/
public interface EbanTokenService {
/**
* 创建E办Token信息到现有OAuth2表中
*
* @param userId 系统用户ID
* @param accessToken E办访问令牌
* @param refreshToken E办刷新令牌
* @param expiresIn 过期时间(秒)
* @param uid E办用户唯一标识
* @param userInfo E办用户信息JSON格式
* @return OAuth2AccessTokenDO
*/
OAuth2AccessTokenDO createEbanToken(Long userId, String accessToken, String refreshToken,
Integer expiresIn, String uid, String userInfo);
/**
* 根据用户ID获取E办Token
*
* @param userId 系统用户ID
* @return OAuth2AccessTokenDO
*/
OAuth2AccessTokenDO getEbanTokenByUserId(Long userId);
/**
* 刷新E办Token
*
* @param userId 系统用户ID
* @return 是否刷新成功
*/
boolean refreshEbanToken(Long userId);
/**
* 删除E办Token
*
* @param userId 系统用户ID
*/
void deleteEbanToken(Long userId);
/**
* 检查E办Token是否有效
*
* @param userId 系统用户ID
* @return 是否有效
*/
boolean isEbanTokenValid(Long userId);
/**
* 根据access_token获取E办Token信息
*
* @param accessToken 访问令牌
* @return OAuth2AccessTokenDO
*/
OAuth2AccessTokenDO getEbanTokenByAccessToken(String accessToken);
}

View File

@@ -0,0 +1,97 @@
package com.zt.plat.module.system.service.oauth2;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.zt.plat.framework.common.enums.UserTypeEnum;
import com.zt.plat.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
import com.zt.plat.module.system.dal.dataobject.oauth2.OAuth2RefreshTokenDO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
/**
* E办Token管理服务实现类基于现有OAuth2 Token体系
*
* @author ZT
*/
@Service
@Slf4j
public class EbanTokenServiceImpl implements EbanTokenService {
@Resource
private OAuth2TokenService oauth2TokenService;
@Value("${eban.oauth2.auth-server.client-id:tyszhjyglxt}")
private String clientId;
@Value("${eban.oauth2.auth-server.client-secret:}")
private String clientSecret;
@Value("${eban.oauth2.token.refresh-url:http://10.2.137.42/idp/oauth2/refreshToken}")
private String refreshTokenUrl;
@Value("${eban.oauth2.token.check-url:http://10.2.137.42/idp/oauth2/checkTokenValid}")
private String checkTokenUrl;
private static final String EBAN_CLIENT_ID = "eban-oauth2-client";
private static final String EBAN_SCOPES = "user:read";
@Override
public OAuth2AccessTokenDO createEbanToken(Long userId, String accessToken, String refreshToken,
Integer expiresIn, String uid, String userInfo) {
try {
// 使用现有的OAuth2TokenService创建token
// 由于原方法签名不匹配,我们先简单实现
OAuth2AccessTokenDO token = oauth2TokenService.createAccessToken(
userId,
UserTypeEnum.ADMIN.getValue(),
EBAN_CLIENT_ID,
java.util.Arrays.asList(EBAN_SCOPES)
);
log.info("成功创建E办Token: userId={}, uid={}", userId, uid);
return token;
} catch (Exception e) {
log.error("创建E办Token失败: userId=" + userId + ", uid=" + uid, e);
throw new RuntimeException("创建E办Token失败", e);
}
}
@Override
public OAuth2AccessTokenDO getEbanTokenByUserId(Long userId) {
// 暂时返回null需要根据实际的OAuth2TokenService方法实现
return null;
}
@Override
public OAuth2AccessTokenDO getEbanTokenByAccessToken(String accessToken) {
return oauth2TokenService.getAccessToken(accessToken);
}
@Override
public boolean refreshEbanToken(Long userId) {
// 暂时简单实现
return false;
}
@Override
public void deleteEbanToken(Long userId) {
// 暂时简单实现
log.info("删除E办Token: userId={}", userId);
}
@Override
public boolean isEbanTokenValid(Long userId) {
// 暂时简单实现
return false;
}
}

View File

@@ -203,6 +203,25 @@ zt:
begin-code: 9999 # 这里配置 9999 的原因是,测试方便。
end-code: 9999 # 这里配置 9999 的原因是,测试方便。
# E办OAuth2配置文件
eban:
oauth2:
# E办OAuth2服务端配置
auth-server:
base-url: http://10.2.137.42/idp/oauth2
client-id: tyszhjyglxt
client-secret: your_client_secret_here # 需要从e办系统获取
callback-uri: http://172.16.46.63:30080/system/oauth2/callback
# 用户信息获取配置
user-info:
url: http://10.2.137.42/idp/oauth2/getUserInfo
# 令牌交换配置
token:
url: http://10.2.137.42/idp/oauth2/getToken
debug: false
sync: