mirror of
https://github.com/PowerJob/PowerJob.git
synced 2025-07-17 00:00:04 +08:00
feat: PowerJobAuthInterceptor
This commit is contained in:
parent
926c8758ed
commit
ce6c62f786
@ -0,0 +1,18 @@
|
||||
package tech.powerjob.common;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* 统一定义日志
|
||||
*
|
||||
* @author tjq
|
||||
* @since 2023/3/25
|
||||
*/
|
||||
public class Loggers {
|
||||
|
||||
/**
|
||||
* Web 层统一日志
|
||||
*/
|
||||
public static final Logger WEB = LoggerFactory.getLogger("P_SERVER_LOGGER_WEB");
|
||||
}
|
@ -1,7 +1,8 @@
|
||||
package tech.powerjob.server.auth.login;
|
||||
package tech.powerjob.server.auth;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
@ -13,6 +14,7 @@ import javax.servlet.http.HttpServletRequest;
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@Accessors(chain = true)
|
||||
public class LoginContext {
|
||||
|
||||
private HttpServletRequest httpServletRequest;
|
@ -2,12 +2,19 @@ package tech.powerjob.server.auth.anno;
|
||||
|
||||
import tech.powerjob.server.auth.Permission;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* API 权限
|
||||
*
|
||||
* @author tjq
|
||||
* @since 2023/3/20
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface ApiPermission {
|
||||
/**
|
||||
* API 名称
|
||||
|
@ -0,0 +1,82 @@
|
||||
package tech.powerjob.server.auth.interceptor;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
import tech.powerjob.common.Loggers;
|
||||
import tech.powerjob.common.exception.PowerJobException;
|
||||
import tech.powerjob.server.auth.PowerJobUser;
|
||||
import tech.powerjob.server.auth.anno.ApiPermission;
|
||||
import tech.powerjob.server.auth.service.PowerJobAuthService;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* login auth and permission check
|
||||
*
|
||||
* @author tjq
|
||||
* @since 2023/3/25
|
||||
*/
|
||||
@Component
|
||||
public class PowerJobAuthInterceptor implements HandlerInterceptor {
|
||||
|
||||
@Resource
|
||||
private PowerJobAuthService powerJobAuthService;
|
||||
|
||||
@Override
|
||||
public boolean preHandle(@NonNull HttpServletRequest request,@NonNull HttpServletResponse response,@NonNull Object handler) throws Exception {
|
||||
if (!(handler instanceof HandlerMethod)) {
|
||||
return true;
|
||||
}
|
||||
HandlerMethod handlerMethod = (HandlerMethod) handler;
|
||||
final Method method = handlerMethod.getMethod();
|
||||
final ApiPermission apiPermissionAnno = method.getAnnotation(ApiPermission.class);
|
||||
|
||||
// 无注解代表不需要权限,无需登陆直接访问
|
||||
if (apiPermissionAnno == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 尝试直接解析登陆
|
||||
final Optional<PowerJobUser> loginUserOpt = powerJobAuthService.parse(request);
|
||||
|
||||
// 未登录前先使用302重定向到登录页面
|
||||
if (!loginUserOpt.isPresent()) {
|
||||
response.setStatus(302);
|
||||
response.setHeader("location", request.getContextPath() + "/login");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 登陆用户进行权限校验
|
||||
final PowerJobUser powerJobUser = loginUserOpt.get();
|
||||
final boolean hasPermission = powerJobAuthService.hasPermission(powerJobUser, apiPermissionAnno);
|
||||
if (hasPermission) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final String resourceName = parseResourceName(apiPermissionAnno, handlerMethod);
|
||||
Loggers.WEB.info("[PowerJobAuthInterceptor] user[{}] has no permission to access: {}", powerJobUser.getUsername(), resourceName);
|
||||
|
||||
throw new PowerJobException("Permission denied!");
|
||||
}
|
||||
|
||||
private static String parseResourceName(ApiPermission apiPermission, HandlerMethod handlerMethod) {
|
||||
final String name = apiPermission.name();
|
||||
if (StringUtils.isNotEmpty(name)) {
|
||||
return name;
|
||||
}
|
||||
try {
|
||||
final String clzName = handlerMethod.getBean().getClass().getSimpleName();
|
||||
final String methodName = handlerMethod.getMethod().getName();
|
||||
return String.format("%s_%s", clzName, methodName);
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
package tech.powerjob.server.auth.login.biz;
|
||||
package tech.powerjob.server.auth.login;
|
||||
|
||||
import tech.powerjob.server.auth.login.LoginContext;
|
||||
import tech.powerjob.server.auth.LoginContext;
|
||||
|
||||
import java.util.Optional;
|
||||
|
@ -1,4 +1,4 @@
|
||||
package tech.powerjob.server.auth.login.biz;
|
||||
package tech.powerjob.server.auth.login;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
@ -1,12 +1,12 @@
|
||||
package tech.powerjob.server.auth.login.biz.impl;
|
||||
package tech.powerjob.server.auth.login.impl;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import tech.powerjob.common.Loggers;
|
||||
import tech.powerjob.common.utils.DigestUtils;
|
||||
import tech.powerjob.server.auth.login.LoginContext;
|
||||
import tech.powerjob.server.auth.login.biz.BizLoginService;
|
||||
import tech.powerjob.server.auth.login.biz.BizUser;
|
||||
import tech.powerjob.server.auth.LoginContext;
|
||||
import tech.powerjob.server.auth.login.BizLoginService;
|
||||
import tech.powerjob.server.auth.login.BizUser;
|
||||
import tech.powerjob.server.common.SJ;
|
||||
import tech.powerjob.server.persistence.remote.model.UserInfoDO;
|
||||
import tech.powerjob.server.persistence.remote.repository.UserInfoRepository;
|
||||
@ -21,7 +21,6 @@ import java.util.Optional;
|
||||
* @author tjq
|
||||
* @since 2023/3/20
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class DefaultBizLoginService implements BizLoginService {
|
||||
|
||||
@ -51,13 +50,13 @@ public class DefaultBizLoginService implements BizLoginService {
|
||||
final String password = loginInfoMap.get(KEY_PASSWORD);
|
||||
|
||||
if (StringUtils.isAnyEmpty(username, password)) {
|
||||
log.debug("[DefaultBizLoginService] username or password is empty, login failed!");
|
||||
Loggers.WEB.debug("[DefaultBizLoginService] username or password is empty, login failed!");
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
final Optional<UserInfoDO> userInfoOpt = userInfoRepository.findByUsername(username);
|
||||
if (!userInfoOpt.isPresent()) {
|
||||
log.debug("[DefaultBizLoginService] can't find user by username: {}", username);
|
||||
Loggers.WEB.debug("[DefaultBizLoginService] can't find user by username: {}", username);
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@ -69,7 +68,7 @@ public class DefaultBizLoginService implements BizLoginService {
|
||||
return Optional.of(bizUser);
|
||||
}
|
||||
|
||||
log.debug("[DefaultBizLoginService] user[{}]'s password is not correct, login failed!", username);
|
||||
Loggers.WEB.debug("[DefaultBizLoginService] user[{}]'s password is not correct, login failed!", username);
|
||||
return Optional.empty();
|
||||
}
|
||||
|
@ -1,7 +1,10 @@
|
||||
package tech.powerjob.server.auth.login;
|
||||
package tech.powerjob.server.auth.service;
|
||||
|
||||
import tech.powerjob.server.auth.LoginContext;
|
||||
import tech.powerjob.server.auth.PowerJobUser;
|
||||
import tech.powerjob.server.auth.anno.ApiPermission;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
@ -10,7 +13,7 @@ import java.util.Optional;
|
||||
* @author tjq
|
||||
* @since 2023/3/21
|
||||
*/
|
||||
public interface PowerJobLoginService {
|
||||
public interface PowerJobAuthService {
|
||||
|
||||
/**
|
||||
* 执行真正的登陆操作
|
||||
@ -24,5 +27,7 @@ public interface PowerJobLoginService {
|
||||
* @param loginContext 登录上下文
|
||||
* @return PowerJob 用户
|
||||
*/
|
||||
Optional<PowerJobUser> parse(LoginContext loginContext);
|
||||
Optional<PowerJobUser> parse(HttpServletRequest httpServletRequest);
|
||||
|
||||
boolean hasPermission(PowerJobUser user, ApiPermission apiPermission);
|
||||
}
|
@ -1,14 +1,16 @@
|
||||
package tech.powerjob.server.auth.login;
|
||||
package tech.powerjob.server.auth.service;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import tech.powerjob.common.Loggers;
|
||||
import tech.powerjob.server.auth.LoginContext;
|
||||
import tech.powerjob.server.auth.PowerJobUser;
|
||||
import tech.powerjob.server.auth.login.biz.BizLoginService;
|
||||
import tech.powerjob.server.auth.login.biz.BizUser;
|
||||
import tech.powerjob.server.auth.anno.ApiPermission;
|
||||
import tech.powerjob.server.auth.login.BizLoginService;
|
||||
import tech.powerjob.server.auth.login.BizUser;
|
||||
import tech.powerjob.server.persistence.remote.model.UserInfoDO;
|
||||
import tech.powerjob.server.persistence.remote.repository.UserInfoRepository;
|
||||
|
||||
@ -23,9 +25,8 @@ import java.util.Optional;
|
||||
* @author tjq
|
||||
* @since 2023/3/21
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class PowerJobLoginServiceImpl implements PowerJobLoginService {
|
||||
public class PowerJobLoginServiceImpl implements PowerJobAuthService {
|
||||
|
||||
private final UserInfoRepository userInfoRepository;
|
||||
private final Map<String, BizLoginService> type2LoginService = Maps.newHashMap();
|
||||
@ -67,7 +68,7 @@ public class PowerJobLoginServiceImpl implements PowerJobLoginService {
|
||||
// 同步在 PowerJob 用户库创建该用户
|
||||
UserInfoDO newUser = new UserInfoDO();
|
||||
newUser.setUsername(dbUserName);
|
||||
log.info("[PowerJobLoginService] sync user to PowerJobUserSystem: {}", dbUserName);
|
||||
Loggers.WEB.info("[PowerJobLoginService] sync user to PowerJobUserSystem: {}", dbUserName);
|
||||
userInfoRepository.saveAndFlush(newUser);
|
||||
ret.setUsername(dbUserName);
|
||||
|
||||
@ -75,9 +76,9 @@ public class PowerJobLoginServiceImpl implements PowerJobLoginService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<PowerJobUser> parse(LoginContext loginContext) {
|
||||
public Optional<PowerJobUser> parse(HttpServletRequest httpServletRequest) {
|
||||
|
||||
final Optional<String> usernameOpt = parseUsername(loginContext);
|
||||
final Optional<String> usernameOpt = parseUsername(httpServletRequest);
|
||||
if (!usernameOpt.isPresent()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
@ -88,8 +89,12 @@ public class PowerJobLoginServiceImpl implements PowerJobLoginService {
|
||||
});
|
||||
}
|
||||
|
||||
private Optional<String> parseUsername(LoginContext loginContext) {
|
||||
final HttpServletRequest httpServletRequest = loginContext.getHttpServletRequest();
|
||||
@Override
|
||||
public boolean hasPermission(PowerJobUser user, ApiPermission apiPermission) {
|
||||
return false;
|
||||
}
|
||||
|
||||
private Optional<String> parseUsername(HttpServletRequest httpServletRequest) {
|
||||
final String tokenHeader = httpServletRequest.getHeader(TOKEN_HEADER_NAME);
|
||||
if (StringUtils.isEmpty(tokenHeader)) {
|
||||
return Optional.empty();
|
Loading…
x
Reference in New Issue
Block a user