diff --git a/powerjob-server/powerjob-server-auth/src/main/java/tech/powerjob/server/auth/common/AuthConstants.java b/powerjob-server/powerjob-server-auth/src/main/java/tech/powerjob/server/auth/common/AuthConstants.java new file mode 100644 index 00000000..ab467721 --- /dev/null +++ b/powerjob-server/powerjob-server-auth/src/main/java/tech/powerjob/server/auth/common/AuthConstants.java @@ -0,0 +1,12 @@ +package tech.powerjob.server.auth.common; + +/** + * 常量 + * + * @author tjq + * @since 2024/2/11 + */ +public class AuthConstants { + + public static final String JWT_NAME = "power_jwt"; +} diff --git a/powerjob-server/powerjob-server-auth/src/main/java/tech/powerjob/server/auth/common/PowerJobAuthException.java b/powerjob-server/powerjob-server-auth/src/main/java/tech/powerjob/server/auth/common/PowerJobAuthException.java index adec56f4..5a8fbb9f 100644 --- a/powerjob-server/powerjob-server-auth/src/main/java/tech/powerjob/server/auth/common/PowerJobAuthException.java +++ b/powerjob-server/powerjob-server-auth/src/main/java/tech/powerjob/server/auth/common/PowerJobAuthException.java @@ -1,6 +1,7 @@ package tech.powerjob.server.auth.common; import lombok.Getter; +import tech.powerjob.common.exception.PowerJobException; /** * 鉴权相关错误 @@ -9,7 +10,7 @@ import lombok.Getter; * @since 2024/2/10 */ @Getter -public class PowerJobAuthException extends RuntimeException { +public class PowerJobAuthException extends PowerJobException { private final String code; diff --git a/powerjob-server/powerjob-server-auth/src/main/java/tech/powerjob/server/auth/jwt/impl/DefaultSecretProvider.java b/powerjob-server/powerjob-server-auth/src/main/java/tech/powerjob/server/auth/jwt/impl/DefaultSecretProvider.java index 0a26a557..e5ae481f 100644 --- a/powerjob-server/powerjob-server-auth/src/main/java/tech/powerjob/server/auth/jwt/impl/DefaultSecretProvider.java +++ b/powerjob-server/powerjob-server-auth/src/main/java/tech/powerjob/server/auth/jwt/impl/DefaultSecretProvider.java @@ -1,7 +1,13 @@ package tech.powerjob.server.auth.jwt.impl; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.core.env.Environment; import org.springframework.stereotype.Component; import tech.powerjob.server.auth.jwt.SecretProvider; +import tech.powerjob.server.common.utils.DigestUtils; + +import javax.annotation.Resource; /** * PowerJob 默认实现 @@ -9,10 +15,33 @@ import tech.powerjob.server.auth.jwt.SecretProvider; * @author tjq * @since 2023/3/20 */ +@Slf4j @Component public class DefaultSecretProvider implements SecretProvider { + + @Resource + private Environment environment; + + private static final String PROPERTY_KEY = "spring.datasource.core.jdbc-url"; + @Override public String fetchSecretKey() { + + // 考虑到大部分用户都是开箱即用,此处还是提供一个相对安全的默认实现。JDBC URL 部署时必会改,skey 不固定,更安全 + try { + String propertyValue = environment.getProperty(PROPERTY_KEY); + if (StringUtils.isNotEmpty(propertyValue)) { + String md5 = DigestUtils.md5(propertyValue); + + log.debug("[DefaultSecretProvider] propertyValue: {} ==> md5: {}", propertyValue, md5); + + if (StringUtils.isNotEmpty(md5)) { + return md5; + } + } + } catch (Exception ignore) { + } + return "ZQQZJ"; } } diff --git a/powerjob-server/powerjob-server-auth/src/main/java/tech/powerjob/server/auth/login/ThirdPartyLoginService.java b/powerjob-server/powerjob-server-auth/src/main/java/tech/powerjob/server/auth/login/ThirdPartyLoginService.java index 87653b3f..edbed635 100644 --- a/powerjob-server/powerjob-server-auth/src/main/java/tech/powerjob/server/auth/login/ThirdPartyLoginService.java +++ b/powerjob-server/powerjob-server-auth/src/main/java/tech/powerjob/server/auth/login/ThirdPartyLoginService.java @@ -18,14 +18,14 @@ public interface ThirdPartyLoginService { /** * 生成登陆的重定向 URL - * @param loginContext 上下文 + * @param httpServletRequest http请求 * @return 重定向地址 */ String generateLoginUrl(HttpServletRequest httpServletRequest); /** * 执行第三方登录 - * @param loginContext 上下文 + * @param loginRequest 上下文 * @return 登录地址 */ ThirdPartyUser login(ThirdPartyLoginRequest loginRequest); diff --git a/powerjob-server/powerjob-server-auth/src/main/java/tech/powerjob/server/auth/service/login/LoginRequest.java b/powerjob-server/powerjob-server-auth/src/main/java/tech/powerjob/server/auth/service/login/LoginRequest.java index b20d86b0..77b66bf2 100644 --- a/powerjob-server/powerjob-server-auth/src/main/java/tech/powerjob/server/auth/service/login/LoginRequest.java +++ b/powerjob-server/powerjob-server-auth/src/main/java/tech/powerjob/server/auth/service/login/LoginRequest.java @@ -1,6 +1,7 @@ package tech.powerjob.server.auth.service.login; import lombok.Data; +import lombok.experimental.Accessors; import javax.servlet.http.HttpServletRequest; @@ -11,6 +12,7 @@ import javax.servlet.http.HttpServletRequest; * @since 2024/2/10 */ @Data +@Accessors(chain = true) public class LoginRequest { /** diff --git a/powerjob-server/powerjob-server-auth/src/main/java/tech/powerjob/server/auth/service/login/PowerJobLoginService.java b/powerjob-server/powerjob-server-auth/src/main/java/tech/powerjob/server/auth/service/login/PowerJobLoginService.java index 0c570a6d..f932b5be 100644 --- a/powerjob-server/powerjob-server-auth/src/main/java/tech/powerjob/server/auth/service/login/PowerJobLoginService.java +++ b/powerjob-server/powerjob-server-auth/src/main/java/tech/powerjob/server/auth/service/login/PowerJobLoginService.java @@ -25,10 +25,11 @@ public interface PowerJobLoginService { /** * 获取第三方登录链接 + * @param loginType 登录类型 * @param httpServletRequest http请求 * @return 重定向地址 */ - String fetchThirdPartyLoginUrl(HttpServletRequest httpServletRequest); + String fetchThirdPartyLoginUrl(String loginType, HttpServletRequest httpServletRequest); /** * 执行真正的登录请求,底层调用第三方登录服务完成登录 diff --git a/powerjob-server/powerjob-server-auth/src/main/java/tech/powerjob/server/auth/service/login/impl/PowerJobLoginServiceImpl.java b/powerjob-server/powerjob-server-auth/src/main/java/tech/powerjob/server/auth/service/login/impl/PowerJobLoginServiceImpl.java index 9e9f074d..2e955ab0 100644 --- a/powerjob-server/powerjob-server-auth/src/main/java/tech/powerjob/server/auth/service/login/impl/PowerJobLoginServiceImpl.java +++ b/powerjob-server/powerjob-server-auth/src/main/java/tech/powerjob/server/auth/service/login/impl/PowerJobLoginServiceImpl.java @@ -8,6 +8,7 @@ import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import tech.powerjob.server.auth.PowerJobUser; +import tech.powerjob.server.auth.common.AuthConstants; import tech.powerjob.server.auth.common.AuthErrorCode; import tech.powerjob.server.auth.common.PowerJobAuthException; import tech.powerjob.server.auth.jwt.JwtService; @@ -43,7 +44,7 @@ public class PowerJobLoginServiceImpl implements PowerJobLoginService { private final UserInfoRepository userInfoRepository; private final Map code2ThirdPartyLoginService; - private static final String JWT_NAME = "power_jwt"; + private static final String KEY_USERNAME = "userName"; @@ -66,8 +67,9 @@ public class PowerJobLoginServiceImpl implements PowerJobLoginService { } @Override - public String fetchThirdPartyLoginUrl(HttpServletRequest httpServletRequest) { - return null; + public String fetchThirdPartyLoginUrl(String type, HttpServletRequest httpServletRequest) { + final ThirdPartyLoginService thirdPartyLoginService = fetchBizLoginService(type); + return thirdPartyLoginService.generateLoginUrl(httpServletRequest); } @Override @@ -137,10 +139,10 @@ public class PowerJobLoginServiceImpl implements PowerJobLoginService { private Optional parseUserName(HttpServletRequest httpServletRequest) { // header、cookie 都能获取 - String jwtStr = httpServletRequest.getHeader(JWT_NAME); + String jwtStr = httpServletRequest.getHeader(AuthConstants.JWT_NAME); if (StringUtils.isEmpty(jwtStr)) { for (Cookie cookie : httpServletRequest.getCookies()) { - if (cookie.getName().equals(JWT_NAME)) { + if (cookie.getName().equals(AuthConstants.JWT_NAME)) { jwtStr = cookie.getValue(); } } diff --git a/powerjob-server/powerjob-server-starter/src/main/java/tech/powerjob/server/web/controller/AuthController.java b/powerjob-server/powerjob-server-starter/src/main/java/tech/powerjob/server/web/controller/AuthController.java index 1ec4bd05..5b0195f2 100644 --- a/powerjob-server/powerjob-server-starter/src/main/java/tech/powerjob/server/web/controller/AuthController.java +++ b/powerjob-server/powerjob-server-starter/src/main/java/tech/powerjob/server/web/controller/AuthController.java @@ -1,12 +1,19 @@ package tech.powerjob.server.web.controller; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import tech.powerjob.common.response.ResultDTO; +import tech.powerjob.server.auth.PowerJobUser; +import tech.powerjob.server.auth.common.AuthConstants; import tech.powerjob.server.auth.login.LoginTypeInfo; +import tech.powerjob.server.auth.service.login.LoginRequest; +import tech.powerjob.server.auth.service.login.PowerJobLoginService; +import javax.annotation.Resource; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import java.util.List; +import java.util.Optional; /** * 登录 & 权限相关 @@ -18,9 +25,68 @@ import java.util.List; @RequestMapping("/auth") public class AuthController { - @GetMapping("/listSupportLoginTypes") + @Resource + private PowerJobLoginService powerJobLoginService; + + @GetMapping("/supportLoginTypes") public ResultDTO> listSupportLoginTypes() { - return null; + return ResultDTO.success(powerJobLoginService.fetchSupportLoginTypes()); } + @GetMapping("/thirdPartyLoginUrl") + public ResultDTO getThirdPartyLoginUrl(String type, HttpServletRequest request) { + String url = powerJobLoginService.fetchThirdPartyLoginUrl(type, request); + return ResultDTO.success(url); + } + + /** + * 第三方账号体系回调登录接口,eg, 接受钉钉登录回调 + * @param httpServletRequest 请求 + * @param httpServletResponse 响应 + * @return 登录结果 + */ + @RequestMapping(value = "/thirdPartyLoginCallback", method = {RequestMethod.GET, RequestMethod.POST}) + public ResultDTO loginCallback(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) { + + LoginRequest loginContext = new LoginRequest().setHttpServletRequest(httpServletRequest); + + // 常见登录组件的标准规范(钉钉、企业微信、飞书),第三方原样透传。开发者在对接第三方登录体系时,可能需要修改此处,将 type 回填 + final String state = httpServletRequest.getParameter("state"); + loginContext.setLoginType(state); + + final PowerJobUser powerJobUser = powerJobLoginService.doLogin(loginContext); + fillJwt4LoginUser(powerJobUser, httpServletResponse); + + return ResultDTO.success(powerJobUser); + } + + /** + * 第三方账号体系直接登录接口,eg, 接受 PowerJob 自带账号密码体系的登录请求 + * @param loginRequest 登录请求 + * @param httpServletResponse 响应 + * @return 登录结果 + */ + @PostMapping("/thirdPartyLoginDirect") + public ResultDTO selfLogin(LoginRequest loginRequest, HttpServletResponse httpServletResponse) { + try { + final PowerJobUser powerJobUser = powerJobLoginService.doLogin(loginRequest); + if (powerJobUser == null) { + return ResultDTO.failed("USER_NOT_FOUND"); + } + fillJwt4LoginUser(powerJobUser, httpServletResponse); + return ResultDTO.success(powerJobUser); + } catch (Exception e) { + return ResultDTO.failed(e.getMessage()); + } + } + + @GetMapping(value = "/ifLogin") + public ResultDTO ifLogin(HttpServletRequest httpServletRequest) { + final Optional powerJobUser = powerJobLoginService.ifLogin(httpServletRequest); + return powerJobUser.map(ResultDTO::success).orElseGet(() -> ResultDTO.failed("LOGIN_FAILED")); + } + + private void fillJwt4LoginUser(PowerJobUser powerJobUser, HttpServletResponse httpServletResponse) { + httpServletResponse.addCookie(new Cookie(AuthConstants.JWT_NAME, powerJobUser.getJwtToken())); + } }