feat: OpenApiInterceptor

This commit is contained in:
tjq 2024-08-09 21:47:47 +08:00
parent 84b90a366c
commit bee4795027
18 changed files with 144 additions and 50 deletions

View File

@ -5,6 +5,7 @@ import lombok.Setter;
import lombok.ToString; import lombok.ToString;
import java.io.Serializable; import java.io.Serializable;
import java.util.Map;
/** /**
* App 鉴权响应 * App 鉴权响应
@ -21,5 +22,9 @@ public class AppAuthResult implements Serializable {
private String token; private String token;
private String extra; /**
* 额外参数
* 有安全需求的开发者可执行扩展
*/
private Map<String, Object> extra;
} }

View File

@ -1,4 +1,4 @@
package tech.powerjob.server.auth.common; package tech.powerjob.common.enums;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
@ -11,7 +11,7 @@ import lombok.Getter;
*/ */
@Getter @Getter
@AllArgsConstructor @AllArgsConstructor
public enum AuthErrorCode { public enum ErrorCodes {
USER_NOT_LOGIN("-100", "UserNotLoggedIn"), USER_NOT_LOGIN("-100", "UserNotLoggedIn"),
USER_NOT_EXIST("-101", "UserNotExist"), USER_NOT_EXIST("-101", "UserNotExist"),
@ -33,7 +33,18 @@ public enum AuthErrorCode {
INVALID_TOKEN("-401", "INVALID_TOKEN"), INVALID_TOKEN("-401", "INVALID_TOKEN"),
OPEN_API_AUTH_FAILED("-1001", "OPEN_API_AUTH_FAILED"), INVALID_APP("-402", "INVALID_APP"),
/**
* 系统内部异常
*/
SYSTEM_UNKNOWN_ERROR("-500", "SYS_UNKNOWN_ERROR"),
/**
* OPENAPI 错误码号段 -10XX
*/
OPEN_API_PASSWORD_ERROR("-1001", "OPEN_API_PASSWORD_ERROR"),
OPEN_API_AUTH_FAILED("-1002", "OPEN_API_AUTH_FAILED"),
; ;

View File

@ -2,6 +2,7 @@ package tech.powerjob.common.exception;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import tech.powerjob.common.enums.ErrorCodes;
/** /**
* PowerJob 运行时异常 * PowerJob 运行时异常
@ -22,6 +23,11 @@ public class PowerJobException extends RuntimeException {
super(message); super(message);
} }
public PowerJobException(ErrorCodes errorCode, String extraMsg) {
super(extraMsg == null ? errorCode.getMsg() : errorCode.getMsg().concat(":").concat(extraMsg));
this.code = errorCode.getCode();
}
public PowerJobException(String message, Throwable cause) { public PowerJobException(String message, Throwable cause) {
super(message, cause); super(message, cause);
} }

View File

@ -3,6 +3,8 @@ package tech.powerjob.common.response;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import org.apache.commons.lang3.exception.ExceptionUtils; import org.apache.commons.lang3.exception.ExceptionUtils;
import tech.powerjob.common.enums.ErrorCodes;
import tech.powerjob.common.exception.PowerJobException;
/** /**
* 新的 Result带状态码 * 新的 Result带状态码
@ -31,7 +33,15 @@ public class PowerResultDTO<T> extends ResultDTO<T> {
} }
public static <T> PowerResultDTO<T> f(Throwable t) { public static <T> PowerResultDTO<T> f(Throwable t) {
return f(ExceptionUtils.getStackTrace(t)); PowerResultDTO<T> f = f(ExceptionUtils.getStackTrace(t));
f.setCode(ErrorCodes.SYSTEM_UNKNOWN_ERROR.getCode());
return f;
}
public static <T> PowerResultDTO<T> f(PowerJobException pje) {
PowerResultDTO<T> f = f(pje.getMessage());
f.setCode(pje.getCode());
return f;
} }
} }

View File

@ -1,6 +1,7 @@
package tech.powerjob.server.auth.common; package tech.powerjob.server.auth.common;
import lombok.Getter; import lombok.Getter;
import tech.powerjob.common.enums.ErrorCodes;
import tech.powerjob.common.exception.PowerJobException; import tech.powerjob.common.exception.PowerJobException;
/** /**
@ -12,12 +13,11 @@ import tech.powerjob.common.exception.PowerJobException;
@Getter @Getter
public class PowerJobAuthException extends PowerJobException { public class PowerJobAuthException extends PowerJobException {
public PowerJobAuthException(AuthErrorCode errorCode) { public PowerJobAuthException(ErrorCodes errorCode) {
this(errorCode, null); this(errorCode, null);
} }
public PowerJobAuthException(AuthErrorCode errorCode, String extraMsg) { public PowerJobAuthException(ErrorCodes errorCode, String extraMsg) {
super(extraMsg == null ? errorCode.getMsg() : errorCode.getMsg().concat(":").concat(extraMsg)); super(errorCode, extraMsg);
this.code = errorCode.getCode();
} }
} }

View File

@ -13,7 +13,7 @@ import tech.powerjob.server.auth.LoginUserHolder;
import tech.powerjob.server.auth.Permission; import tech.powerjob.server.auth.Permission;
import tech.powerjob.server.auth.PowerJobUser; import tech.powerjob.server.auth.PowerJobUser;
import tech.powerjob.server.auth.RoleScope; import tech.powerjob.server.auth.RoleScope;
import tech.powerjob.server.auth.common.AuthErrorCode; import tech.powerjob.common.enums.ErrorCodes;
import tech.powerjob.server.auth.common.PowerJobAuthException; import tech.powerjob.server.auth.common.PowerJobAuthException;
import tech.powerjob.server.auth.common.utils.HttpServletUtils; import tech.powerjob.server.auth.common.utils.HttpServletUtils;
import tech.powerjob.server.auth.service.login.PowerJobLoginService; import tech.powerjob.server.auth.service.login.PowerJobLoginService;
@ -59,7 +59,7 @@ public class PowerJobAuthInterceptor implements HandlerInterceptor {
// 未登录直接报错返回固定状态码前端拦截后跳转到登录页 // 未登录直接报错返回固定状态码前端拦截后跳转到登录页
if (!loginUserOpt.isPresent()) { if (!loginUserOpt.isPresent()) {
throw new PowerJobAuthException(AuthErrorCode.USER_NOT_LOGIN); throw new PowerJobAuthException(ErrorCodes.USER_NOT_LOGIN);
} }
// 登陆用户进行权限校验 // 登陆用户进行权限校验

View File

@ -6,7 +6,7 @@ import org.springframework.stereotype.Service;
import tech.powerjob.common.exception.PowerJobException; import tech.powerjob.common.exception.PowerJobException;
import tech.powerjob.common.serialize.JsonUtils; import tech.powerjob.common.serialize.JsonUtils;
import tech.powerjob.server.auth.common.AuthConstants; import tech.powerjob.server.auth.common.AuthConstants;
import tech.powerjob.server.auth.common.AuthErrorCode; import tech.powerjob.common.enums.ErrorCodes;
import tech.powerjob.server.auth.common.PowerJobAuthException; import tech.powerjob.server.auth.common.PowerJobAuthException;
import tech.powerjob.server.auth.login.*; import tech.powerjob.server.auth.login.*;
import tech.powerjob.server.common.Loggers; import tech.powerjob.server.common.Loggers;
@ -64,13 +64,13 @@ public class PwjbAccountLoginService implements ThirdPartyLoginService {
if (StringUtils.isAnyEmpty(username, password)) { if (StringUtils.isAnyEmpty(username, password)) {
Loggers.WEB.debug("[PowerJobLoginService] username or password is empty, login failed!"); Loggers.WEB.debug("[PowerJobLoginService] username or password is empty, login failed!");
throw new PowerJobAuthException(AuthErrorCode.INVALID_REQUEST); throw new PowerJobAuthException(ErrorCodes.INVALID_REQUEST);
} }
final Optional<PwjbUserInfoDO> userInfoOpt = pwjbUserInfoRepository.findByUsername(username); final Optional<PwjbUserInfoDO> userInfoOpt = pwjbUserInfoRepository.findByUsername(username);
if (!userInfoOpt.isPresent()) { if (!userInfoOpt.isPresent()) {
Loggers.WEB.debug("[PowerJobLoginService] can't find user by username: {}", username); Loggers.WEB.debug("[PowerJobLoginService] can't find user by username: {}", username);
throw new PowerJobAuthException(AuthErrorCode.USER_NOT_EXIST); throw new PowerJobAuthException(ErrorCodes.USER_NOT_EXIST);
} }
final PwjbUserInfoDO dbUser = userInfoOpt.get(); final PwjbUserInfoDO dbUser = userInfoOpt.get();

View File

@ -14,7 +14,7 @@ import tech.powerjob.common.serialize.JsonUtils;
import tech.powerjob.server.auth.LoginUserHolder; import tech.powerjob.server.auth.LoginUserHolder;
import tech.powerjob.server.auth.PowerJobUser; import tech.powerjob.server.auth.PowerJobUser;
import tech.powerjob.server.auth.common.AuthConstants; import tech.powerjob.server.auth.common.AuthConstants;
import tech.powerjob.server.auth.common.AuthErrorCode; import tech.powerjob.common.enums.ErrorCodes;
import tech.powerjob.server.auth.common.PowerJobAuthException; import tech.powerjob.server.auth.common.PowerJobAuthException;
import tech.powerjob.server.auth.common.utils.HttpServletUtils; import tech.powerjob.server.auth.common.utils.HttpServletUtils;
import tech.powerjob.server.auth.jwt.JwtService; import tech.powerjob.server.auth.jwt.JwtService;
@ -145,7 +145,7 @@ public class PowerJobLoginServiceImpl implements PowerJobLoginService {
Optional<UserInfoDO> dbUserInfoOpt = userInfoRepository.findByUsername(jwtBody.getUsername()); Optional<UserInfoDO> dbUserInfoOpt = userInfoRepository.findByUsername(jwtBody.getUsername());
if (!dbUserInfoOpt.isPresent()) { if (!dbUserInfoOpt.isPresent()) {
throw new PowerJobAuthException(AuthErrorCode.USER_NOT_EXIST); throw new PowerJobAuthException(ErrorCodes.USER_NOT_EXIST);
} }
UserInfoDO dbUser = dbUserInfoOpt.get(); UserInfoDO dbUser = dbUserInfoOpt.get();
@ -160,14 +160,14 @@ public class PowerJobLoginServiceImpl implements PowerJobLoginService {
// DB 中的 encryptedToken 存在代表需要二次校验 // DB 中的 encryptedToken 存在代表需要二次校验
if (StringUtils.isNotEmpty(tokenLoginVerifyInfo.getEncryptedToken())) { if (StringUtils.isNotEmpty(tokenLoginVerifyInfo.getEncryptedToken())) {
if (!StringUtils.equals(jwtBody.getEncryptedToken(), tokenLoginVerifyInfo.getEncryptedToken())) { if (!StringUtils.equals(jwtBody.getEncryptedToken(), tokenLoginVerifyInfo.getEncryptedToken())) {
throw new PowerJobAuthException(AuthErrorCode.INVALID_TOKEN); throw new PowerJobAuthException(ErrorCodes.INVALID_TOKEN);
} }
ThirdPartyLoginService thirdPartyLoginService = code2ThirdPartyLoginService.get(dbUser.getAccountType()); ThirdPartyLoginService thirdPartyLoginService = code2ThirdPartyLoginService.get(dbUser.getAccountType());
boolean tokenLoginVerifyOk = thirdPartyLoginService.tokenLoginVerify(dbUser.getOriginUsername(), tokenLoginVerifyInfo); boolean tokenLoginVerifyOk = thirdPartyLoginService.tokenLoginVerify(dbUser.getOriginUsername(), tokenLoginVerifyInfo);
if (!tokenLoginVerifyOk) { if (!tokenLoginVerifyOk) {
throw new PowerJobAuthException(AuthErrorCode.USER_AUTH_FAILED); throw new PowerJobAuthException(ErrorCodes.USER_AUTH_FAILED);
} }
} }
@ -186,14 +186,14 @@ public class PowerJobLoginServiceImpl implements PowerJobLoginService {
private void checkUserStatus(UserInfoDO dbUser) { private void checkUserStatus(UserInfoDO dbUser) {
int accountStatus = Optional.ofNullable(dbUser.getStatus()).orElse(SwitchableStatus.ENABLE.getV()); int accountStatus = Optional.ofNullable(dbUser.getStatus()).orElse(SwitchableStatus.ENABLE.getV());
if (accountStatus == SwitchableStatus.DISABLE.getV()) { if (accountStatus == SwitchableStatus.DISABLE.getV()) {
throw new PowerJobAuthException(AuthErrorCode.USER_DISABLED); throw new PowerJobAuthException(ErrorCodes.USER_DISABLED);
} }
} }
private ThirdPartyLoginService fetchBizLoginService(String loginType) { private ThirdPartyLoginService fetchBizLoginService(String loginType) {
final ThirdPartyLoginService loginService = code2ThirdPartyLoginService.get(loginType); final ThirdPartyLoginService loginService = code2ThirdPartyLoginService.get(loginType);
if (loginService == null) { if (loginService == null) {
throw new PowerJobAuthException(AuthErrorCode.INVALID_REQUEST, "can't find ThirdPartyLoginService by type: " + loginType); throw new PowerJobAuthException(ErrorCodes.INVALID_REQUEST, "can't find ThirdPartyLoginService by type: " + loginType);
} }
return loginService; return loginService;
} }

View File

@ -20,7 +20,7 @@ public interface AppInfoService {
*/ */
Long assertApp(String appName, String password); Long assertApp(String appName, String password);
Long assertAppWithEncryptedPassword(String appName, String encryptedPassword); Optional<AppInfoDO> findByAppName(String appName);
/** /**
* 获取 AppInfo带缓存 * 获取 AppInfo带缓存

View File

@ -6,7 +6,6 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import tech.powerjob.common.exception.PowerJobException; import tech.powerjob.common.exception.PowerJobException;
import tech.powerjob.common.utils.DigestUtils;
import tech.powerjob.server.core.service.AppInfoService; import tech.powerjob.server.core.service.AppInfoService;
import tech.powerjob.server.persistence.remote.model.AppInfoDO; import tech.powerjob.server.persistence.remote.model.AppInfoDO;
import tech.powerjob.server.persistence.remote.repository.AppInfoRepository; import tech.powerjob.server.persistence.remote.repository.AppInfoRepository;
@ -51,12 +50,8 @@ public class AppInfoServiceImpl implements AppInfoService {
} }
@Override @Override
public Long assertAppWithEncryptedPassword(String appName, String encryptedPassword) { public Optional<AppInfoDO> findByAppName(String appName) {
AppInfoDO appInfo = appInfoRepository.findByAppName(appName).orElseThrow(() -> new PowerJobException("can't find appInfo by appName: " + appName)); return appInfoRepository.findByAppName(appName);
if (Objects.equals(DigestUtils.md5(appInfo.getPassword()), encryptedPassword)) {
return appInfo.getId();
}
throw new PowerJobException("password error!");
} }
@Override @Override

View File

@ -8,7 +8,7 @@ import org.springframework.stereotype.Service;
import tech.powerjob.common.serialize.JsonUtils; import tech.powerjob.common.serialize.JsonUtils;
import tech.powerjob.server.auth.*; import tech.powerjob.server.auth.*;
import tech.powerjob.server.auth.common.AuthConstants; import tech.powerjob.server.auth.common.AuthConstants;
import tech.powerjob.server.auth.common.AuthErrorCode; import tech.powerjob.common.enums.ErrorCodes;
import tech.powerjob.server.auth.common.PowerJobAuthException; import tech.powerjob.server.auth.common.PowerJobAuthException;
import tech.powerjob.server.auth.service.WebAuthService; import tech.powerjob.server.auth.service.WebAuthService;
import tech.powerjob.server.auth.service.permission.PowerJobPermissionService; import tech.powerjob.server.auth.service.permission.PowerJobPermissionService;
@ -35,7 +35,7 @@ public class WebAuthServiceImpl implements WebAuthService {
public void grantRole2LoginUser(RoleScope roleScope, Long target, Role role, String extra) { public void grantRole2LoginUser(RoleScope roleScope, Long target, Role role, String extra) {
Long userId = LoginUserHolder.getUserId(); Long userId = LoginUserHolder.getUserId();
if (userId == null) { if (userId == null) {
throw new PowerJobAuthException(AuthErrorCode.USER_NOT_LOGIN); throw new PowerJobAuthException(ErrorCodes.USER_NOT_LOGIN);
} }
powerJobPermissionService.grantRole(roleScope, target, userId, role, extra); powerJobPermissionService.grantRole(roleScope, target, userId, role, extra);
} }
@ -82,7 +82,7 @@ public class WebAuthServiceImpl implements WebAuthService {
PowerJobUser powerJobUser = LoginUserHolder.get(); PowerJobUser powerJobUser = LoginUserHolder.get();
if (powerJobUser == null) { if (powerJobUser == null) {
throw new PowerJobAuthException(AuthErrorCode.USER_NOT_LOGIN); throw new PowerJobAuthException(ErrorCodes.USER_NOT_LOGIN);
} }
// 展示不考虑穿透权限的问题即拥有 namespace 权限也可以看到全部的 apps // 展示不考虑穿透权限的问题即拥有 namespace 权限也可以看到全部的 apps

View File

@ -7,7 +7,9 @@ import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.socket.config.annotation.EnableWebSocket; import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.server.standard.ServerEndpointExporter; import org.springframework.web.socket.server.standard.ServerEndpointExporter;
import tech.powerjob.common.OpenAPIConstant;
import tech.powerjob.server.auth.interceptor.PowerJobAuthInterceptor; import tech.powerjob.server.auth.interceptor.PowerJobAuthInterceptor;
import tech.powerjob.server.openapi.OpenApiInterceptor;
import javax.annotation.Resource; import javax.annotation.Resource;
@ -21,6 +23,8 @@ import javax.annotation.Resource;
@EnableWebSocket @EnableWebSocket
public class WebConfig implements WebMvcConfigurer { public class WebConfig implements WebMvcConfigurer {
@Resource
private OpenApiInterceptor openApiInterceptor;
@Resource @Resource
private PowerJobAuthInterceptor powerJobAuthInterceptor; private PowerJobAuthInterceptor powerJobAuthInterceptor;
@ -48,5 +52,9 @@ public class WebConfig implements WebMvcConfigurer {
.addPathPatterns("/**") .addPathPatterns("/**")
.excludePathPatterns("/css/**", "/js/**", "/images/**", "/img/**", "/fonts/**", "/favicon.ico") .excludePathPatterns("/css/**", "/js/**", "/images/**", "/img/**", "/fonts/**", "/favicon.ico")
.order(0); .order(0);
registry.addInterceptor(openApiInterceptor)
.addPathPatterns(OpenAPIConstant.WEB_PATH.concat("/**"))
.order(1);
} }
} }

View File

@ -1,12 +1,16 @@
package tech.powerjob.server.openapi; package tech.powerjob.server.openapi;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import tech.powerjob.client.module.AppAuthRequest; import tech.powerjob.client.module.AppAuthRequest;
import tech.powerjob.client.module.AppAuthResult; import tech.powerjob.client.module.AppAuthResult;
import tech.powerjob.common.OpenAPIConstant; import tech.powerjob.common.OpenAPIConstant;
import tech.powerjob.common.PowerQuery; import tech.powerjob.common.PowerQuery;
import tech.powerjob.common.enums.ErrorCodes;
import tech.powerjob.common.enums.InstanceStatus; import tech.powerjob.common.enums.InstanceStatus;
import tech.powerjob.common.exception.PowerJobException;
import tech.powerjob.common.request.http.SaveJobInfoRequest; import tech.powerjob.common.request.http.SaveJobInfoRequest;
import tech.powerjob.common.request.http.SaveWorkflowNodeRequest; import tech.powerjob.common.request.http.SaveWorkflowNodeRequest;
import tech.powerjob.common.request.http.SaveWorkflowRequest; import tech.powerjob.common.request.http.SaveWorkflowRequest;
@ -31,6 +35,7 @@ import java.util.List;
* @author tjq * @author tjq
* @since 2020/4/15 * @since 2020/4/15
*/ */
@Slf4j
@RestController @RestController
@RequestMapping(OpenAPIConstant.WEB_PATH) @RequestMapping(OpenAPIConstant.WEB_PATH)
@RequiredArgsConstructor @RequiredArgsConstructor
@ -63,7 +68,20 @@ public class OpenAPIController {
*/ */
@PostMapping(OpenAPIConstant.AUTH_APP) @PostMapping(OpenAPIConstant.AUTH_APP)
public PowerResultDTO<AppAuthResult> auth(@RequestBody AppAuthRequest appAuthRequest) { public PowerResultDTO<AppAuthResult> auth(@RequestBody AppAuthRequest appAuthRequest) {
return PowerResultDTO.s(openApiSecurityService.authAppByParam(appAuthRequest)); try {
return PowerResultDTO.s(openApiSecurityService.authAppByParam(appAuthRequest));
} catch (PowerJobException pje) {
PowerResultDTO<AppAuthResult> f = PowerResultDTO.f(pje.getMessage());
f.setCode(pje.getCode());
return f;
} catch (Throwable t) {
log.error("[OpenAPIController] auth failed for request: {}", appAuthRequest, t);
PowerResultDTO<AppAuthResult> f = PowerResultDTO.f(ExceptionUtils.getMessage(t));
f.setCode(ErrorCodes.SYSTEM_UNKNOWN_ERROR.getCode());
return f;
}
} }
/* ************* Job 区 ************* */ /* ************* Job 区 ************* */

View File

@ -1,15 +1,20 @@
package tech.powerjob.server.openapi; package tech.powerjob.server.openapi;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.lang.NonNull; import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.HandlerInterceptor;
import tech.powerjob.common.exception.PowerJobException;
import tech.powerjob.common.response.PowerResultDTO;
import tech.powerjob.common.serialize.JsonUtils;
import tech.powerjob.server.openapi.security.OpenApiSecurityService; import tech.powerjob.server.openapi.security.OpenApiSecurityService;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
/** /**
* OpenAPI 拦截器 * OpenAPI 拦截器
@ -38,9 +43,33 @@ public class OpenApiInterceptor implements HandlerInterceptor {
return true; return true;
} }
openApiSecurityService.authAppByToken(request); try {
openApiSecurityService.authAppByToken(request);
} catch (PowerJobException pje) {
PowerResultDTO<Object> ret = PowerResultDTO.f(pje);
writeResponse(JsonUtils.toJSONString(ret), response);
return false;
} catch (Exception e) {
PowerResultDTO<Object> ret = PowerResultDTO.f(e);
writeResponse(JsonUtils.toJSONString(ret), response);
return false;
}
return true; return true;
} }
@SneakyThrows
private void writeResponse(String content, HttpServletResponse response) {
// 设置响应状态码通常是 400, 401, 403 等错误码
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
// 设置响应的 Content-Type
response.setContentType("application/json;charset=UTF-8");
// JSON 写入响应
PrintWriter writer = response.getWriter();
writer.write(content);
writer.flush();
}
} }

View File

@ -8,17 +8,19 @@ import org.springframework.stereotype.Service;
import tech.powerjob.client.module.AppAuthRequest; import tech.powerjob.client.module.AppAuthRequest;
import tech.powerjob.client.module.AppAuthResult; import tech.powerjob.client.module.AppAuthResult;
import tech.powerjob.common.OpenAPIConstant; import tech.powerjob.common.OpenAPIConstant;
import tech.powerjob.server.auth.common.AuthErrorCode; import tech.powerjob.common.exception.PowerJobException;
import tech.powerjob.common.utils.DigestUtils;
import tech.powerjob.common.enums.ErrorCodes;
import tech.powerjob.server.auth.common.PowerJobAuthException; import tech.powerjob.server.auth.common.PowerJobAuthException;
import tech.powerjob.server.auth.common.utils.HttpServletUtils; import tech.powerjob.server.auth.common.utils.HttpServletUtils;
import tech.powerjob.server.auth.jwt.JwtService; import tech.powerjob.server.auth.jwt.JwtService;
import tech.powerjob.common.utils.DigestUtils;
import tech.powerjob.server.core.service.AppInfoService; import tech.powerjob.server.core.service.AppInfoService;
import tech.powerjob.server.persistence.remote.model.AppInfoDO; import tech.powerjob.server.persistence.remote.model.AppInfoDO;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.Optional; import java.util.Optional;
/** /**
@ -46,11 +48,11 @@ public class OpenApiSecurityServiceImpl implements OpenApiSecurityService {
String appIdFromHeader = HttpServletUtils.fetchFromHeader(OpenAPIConstant.HEADER_APP_ID, httpServletRequest); String appIdFromHeader = HttpServletUtils.fetchFromHeader(OpenAPIConstant.HEADER_APP_ID, httpServletRequest);
if (StringUtils.isEmpty(appIdFromHeader)) { if (StringUtils.isEmpty(appIdFromHeader)) {
throw new IllegalArgumentException("can't find appId in HTTP header"); throw new PowerJobException(ErrorCodes.INVALID_REQUEST, "lack_of_appId_in_header");
} }
if (StringUtils.isEmpty(token)) { if (StringUtils.isEmpty(token)) {
throw new PowerJobAuthException(AuthErrorCode.OPEN_API_AUTH_FAILED); throw new PowerJobException(ErrorCodes.OPEN_API_AUTH_FAILED, "token_is_empty");
} }
Map<String, Object> jwtResult = jwtService.parse(token, null); Map<String, Object> jwtResult = jwtService.parse(token, null);
@ -60,18 +62,18 @@ public class OpenApiSecurityServiceImpl implements OpenApiSecurityService {
// 校验 appId 一致性 // 校验 appId 一致性
if (!StringUtils.equals(appIdFromHeader, String.valueOf(appIdFromJwt))) { if (!StringUtils.equals(appIdFromHeader, String.valueOf(appIdFromJwt))) {
throw new IllegalArgumentException("Inconsistent appId from header and token"); throw new PowerJobException(ErrorCodes.INVALID_REQUEST, "Inconsistent_appId_from_token_and_header");
} }
// 此处不考虑改密码后的缓存时间毕竟只要改了密码一定会报错换言之 OpenAPI 模式下密码不可更改 // 此处不考虑改密码后的缓存时间毕竟只要改了密码一定会报错换言之 OpenAPI 模式下密码不可更改
Optional<AppInfoDO> appInfoOpt = appInfoService.findByIdWithCache(appIdFromJwt); Optional<AppInfoDO> appInfoOpt = appInfoService.findByIdWithCache(appIdFromJwt);
if (!appInfoOpt.isPresent()) { if (!appInfoOpt.isPresent()) {
throw new IllegalArgumentException("can't find app by appId: " + appIdFromJwt); throw new PowerJobException(ErrorCodes.INVALID_APP, "can_not_find_app");
} }
String dbOriginPassword = appInfoOpt.get().getPassword(); String dbOriginPassword = appInfoOpt.get().getPassword();
if (!StringUtils.equals(passwordFromJwt, DigestUtils.md5(dbOriginPassword))) { if (!StringUtils.equals(passwordFromJwt, DigestUtils.md5(dbOriginPassword))) {
throw new PowerJobAuthException(AuthErrorCode.OPEN_API_AUTH_FAILED); throw new PowerJobException(ErrorCodes.OPEN_API_PASSWORD_ERROR, "password_compare_failed");
} }
} }
@ -82,15 +84,25 @@ public class OpenApiSecurityServiceImpl implements OpenApiSecurityService {
String appName = appAuthRequest.getAppName(); String appName = appAuthRequest.getAppName();
String encryptedPassword = appAuthRequest.getEncryptedPassword(); String encryptedPassword = appAuthRequest.getEncryptedPassword();
Long appId = appInfoService.assertAppWithEncryptedPassword(appName, encryptedPassword); Optional<AppInfoDO> appInfoOpt = appInfoService.findByAppName(appName);
if (!appInfoOpt.isPresent()) {
throw new PowerJobAuthException(ErrorCodes.INVALID_APP);
}
AppInfoDO appInfo = appInfoOpt.get();
// 密码验证失败
if (!Objects.equals(DigestUtils.md5(appInfo.getPassword()), encryptedPassword)) {
throw new PowerJobAuthException(ErrorCodes.OPEN_API_PASSWORD_ERROR);
}
Map<String, Object> jwtBody = Maps.newHashMap(); Map<String, Object> jwtBody = Maps.newHashMap();
jwtBody.put(JWT_KEY_APP_ID, appId); jwtBody.put(JWT_KEY_APP_ID, appInfo.getId());
jwtBody.put(JWT_KEY_APP_PASSWORD, encryptedPassword); jwtBody.put(JWT_KEY_APP_PASSWORD, encryptedPassword);
AppAuthResult appAuthResult = new AppAuthResult(); AppAuthResult appAuthResult = new AppAuthResult();
appAuthResult.setAppId(appId); appAuthResult.setAppId(appInfo.getId());
appAuthResult.setToken(jwtService.build(jwtBody, null)); appAuthResult.setToken(jwtService.build(jwtBody, null));
return appAuthResult; return appAuthResult;

View File

@ -22,7 +22,7 @@ import tech.powerjob.server.auth.Permission;
import tech.powerjob.server.auth.Role; import tech.powerjob.server.auth.Role;
import tech.powerjob.server.auth.RoleScope; import tech.powerjob.server.auth.RoleScope;
import tech.powerjob.server.auth.common.AuthConstants; import tech.powerjob.server.auth.common.AuthConstants;
import tech.powerjob.server.auth.common.AuthErrorCode; import tech.powerjob.common.enums.ErrorCodes;
import tech.powerjob.server.auth.common.PowerJobAuthException; import tech.powerjob.server.auth.common.PowerJobAuthException;
import tech.powerjob.server.auth.interceptor.ApiPermission; import tech.powerjob.server.auth.interceptor.ApiPermission;
import tech.powerjob.server.auth.plugin.ModifyOrCreateDynamicPermission; import tech.powerjob.server.auth.plugin.ModifyOrCreateDynamicPermission;
@ -193,7 +193,7 @@ public class AppInfoController {
throw new IllegalArgumentException("can't find app by appName: " + appName); throw new IllegalArgumentException("can't find app by appName: " + appName);
} }
if (!StringUtils.equals(appInfoOpt.get().getPassword(), appAssertRequest.getPassword())) { if (!StringUtils.equals(appInfoOpt.get().getPassword(), appAssertRequest.getPassword())) {
throw new PowerJobAuthException(AuthErrorCode.INCORRECT_PASSWORD); throw new PowerJobAuthException(ErrorCodes.INCORRECT_PASSWORD);
} }
Map<String, Object> extra = Maps.newHashMap(); Map<String, Object> extra = Maps.newHashMap();

View File

@ -15,7 +15,7 @@ import tech.powerjob.server.auth.Permission;
import tech.powerjob.server.auth.PowerJobUser; import tech.powerjob.server.auth.PowerJobUser;
import tech.powerjob.server.auth.Role; import tech.powerjob.server.auth.Role;
import tech.powerjob.server.auth.RoleScope; import tech.powerjob.server.auth.RoleScope;
import tech.powerjob.server.auth.common.AuthErrorCode; import tech.powerjob.common.enums.ErrorCodes;
import tech.powerjob.server.auth.common.PowerJobAuthException; import tech.powerjob.server.auth.common.PowerJobAuthException;
import tech.powerjob.server.auth.interceptor.ApiPermission; import tech.powerjob.server.auth.interceptor.ApiPermission;
import tech.powerjob.server.auth.service.WebAuthService; import tech.powerjob.server.auth.service.WebAuthService;
@ -133,7 +133,7 @@ public class UserInfoController {
public ResultDTO<UserDetailVO> getUserDetail(HttpServletRequest httpServletRequest) { public ResultDTO<UserDetailVO> getUserDetail(HttpServletRequest httpServletRequest) {
Optional<PowerJobUser> powerJobUserOpt = powerJobLoginService.ifLogin(httpServletRequest); Optional<PowerJobUser> powerJobUserOpt = powerJobLoginService.ifLogin(httpServletRequest);
if (!powerJobUserOpt.isPresent()) { if (!powerJobUserOpt.isPresent()) {
throw new PowerJobAuthException(AuthErrorCode.USER_NOT_LOGIN); throw new PowerJobAuthException(ErrorCodes.USER_NOT_LOGIN);
} }
Optional<UserInfoDO> userinfoDoOpt = userInfoRepository.findById(powerJobUserOpt.get().getId()); Optional<UserInfoDO> userinfoDoOpt = userInfoRepository.findById(powerJobUserOpt.get().getId());
if (!userinfoDoOpt.isPresent()) { if (!userinfoDoOpt.isPresent()) {
@ -226,7 +226,7 @@ public class UserInfoController {
private void checkModifyUserPermission(Long uid, HttpServletRequest httpServletRequest) { private void checkModifyUserPermission(Long uid, HttpServletRequest httpServletRequest) {
Optional<PowerJobUser> powerJobUserOpt = powerJobLoginService.ifLogin(httpServletRequest); Optional<PowerJobUser> powerJobUserOpt = powerJobLoginService.ifLogin(httpServletRequest);
if (!powerJobUserOpt.isPresent()) { if (!powerJobUserOpt.isPresent()) {
throw new PowerJobAuthException(AuthErrorCode.USER_NOT_LOGIN); throw new PowerJobAuthException(ErrorCodes.USER_NOT_LOGIN);
} }
PowerJobUser currentLoginUser = powerJobUserOpt.get(); PowerJobUser currentLoginUser = powerJobUserOpt.get();

View File

@ -6,7 +6,7 @@ import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import tech.powerjob.common.serialize.JsonUtils; import tech.powerjob.common.serialize.JsonUtils;
import tech.powerjob.common.utils.CommonUtils; import tech.powerjob.common.utils.CommonUtils;
import tech.powerjob.server.auth.common.AuthErrorCode; import tech.powerjob.common.enums.ErrorCodes;
import tech.powerjob.server.auth.common.PowerJobAuthException; import tech.powerjob.server.auth.common.PowerJobAuthException;
import tech.powerjob.common.utils.DigestUtils; import tech.powerjob.common.utils.DigestUtils;
import tech.powerjob.server.persistence.remote.model.PwjbUserInfoDO; import tech.powerjob.server.persistence.remote.model.PwjbUserInfoDO;
@ -84,7 +84,7 @@ public class PwjbUserWebServiceImplImpl implements PwjbUserWebService {
String oldPasswordInDb = dbUser.getPassword(); String oldPasswordInDb = dbUser.getPassword();
String oldPasswordInReq = DigestUtils.rePassword(changePasswordRequest.getOldPassword(), dbUser.getUsername()); String oldPasswordInReq = DigestUtils.rePassword(changePasswordRequest.getOldPassword(), dbUser.getUsername());
if (!StringUtils.equals(oldPasswordInDb, oldPasswordInReq)) { if (!StringUtils.equals(oldPasswordInDb, oldPasswordInReq)) {
throw new PowerJobAuthException(AuthErrorCode.INCORRECT_PASSWORD); throw new PowerJobAuthException(ErrorCodes.INCORRECT_PASSWORD);
} }
// 测试账号特殊处理 // 测试账号特殊处理