diff --git a/blade-core-auth/blade-core-oauth2/src/main/java/org/springblade/core/oauth2/constant/OAuth2GranterConstant.java b/blade-core-auth/blade-core-oauth2/src/main/java/org/springblade/core/oauth2/constant/OAuth2GranterConstant.java index 020f558..0c905b1 100644 --- a/blade-core-auth/blade-core-oauth2/src/main/java/org/springblade/core/oauth2/constant/OAuth2GranterConstant.java +++ b/blade-core-auth/blade-core-oauth2/src/main/java/org/springblade/core/oauth2/constant/OAuth2GranterConstant.java @@ -77,4 +77,8 @@ public interface OAuth2GranterConstant { */ String REGISTER = "register"; + /** + * mk oauth模式 + */ + String MK = "mk"; } diff --git a/blade-core-auth/blade-core-oauth2/src/main/java/org/springblade/core/oauth2/endpoint/AbstractOAuth2MKEndpoint.java b/blade-core-auth/blade-core-oauth2/src/main/java/org/springblade/core/oauth2/endpoint/AbstractOAuth2MKEndpoint.java new file mode 100644 index 0000000..2df81d7 --- /dev/null +++ b/blade-core-auth/blade-core-oauth2/src/main/java/org/springblade/core/oauth2/endpoint/AbstractOAuth2MKEndpoint.java @@ -0,0 +1,134 @@ +package org.springblade.core.oauth2.endpoint; + +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springblade.core.oauth2.constant.OAuth2TokenConstant; +import org.springblade.core.oauth2.exception.ExceptionCode; +import org.springblade.core.oauth2.granter.TokenGranter; +import org.springblade.core.oauth2.granter.TokenGranterFactory; +import org.springblade.core.oauth2.handler.TokenHandler; +import org.springblade.core.oauth2.provider.OAuth2Request; +import org.springblade.core.oauth2.provider.OAuth2Token; +import org.springblade.core.oauth2.service.OAuth2User; +import org.springblade.core.oauth2.utils.OAuth2ExceptionUtil; +import org.springblade.core.tool.support.Kv; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.util.StringUtils; +import org.springframework.web.bind.annotation.GetMapping; + +import java.io.IOException; +import java.io.PrintWriter; +import java.nio.charset.StandardCharsets; + +import static org.springblade.core.oauth2.constant.OAuth2GranterConstant.MK; +import static org.springblade.core.oauth2.constant.OAuth2ParameterConstant.USERNAME; + + +/** + * mk oauth认证端点 + * @author bfhuange + * @date 2024/9/13 + */ +@Slf4j +@RequiredArgsConstructor +@Tag(name = "跳转mk认证", description = "跳转mk认证端点") +public abstract class AbstractOAuth2MKEndpoint { + + private final TokenGranterFactory granterFactory; + private final TokenHandler tokenHandler; + + /** + * 返回登录页面 + * @param request + * @return + */ + @GetMapping("/oauth/mk/login") + public ResponseEntity login(HttpServletRequest request, HttpServletResponse response) { + String referer = request.getHeader("referer"); + if (!checkRefererUrl(referer)) { + // 校验来源地址 + return ResponseEntity.status(HttpStatus.FORBIDDEN) + .body("非法来源地址"); + } + // 返回登录页面 + return ResponseEntity.ok(generateLoginUrl(referer)); + } + + /** + * 通过mk授权码换取本系统token + * @param mkCode + * @return + */ + @GetMapping("/oauth/mk/token") + public ResponseEntity token(String mkCode) { + log.info("mk 登录回调 mkCode:{}", mkCode); + if (!StringUtils.hasText(mkCode)) { + // 根据无效的mk code的错误代码抛出异常 + OAuth2ExceptionUtil.throwFromCode(ExceptionCode.INVALID_MK_CODE.getCode()); + } + + // 将mk code 转换成erp的账号/手机号 + String account = getAccountByMkCode(mkCode); + if (account == null) { + OAuth2ExceptionUtil.throwFromCode(ExceptionCode.MK_ACCOUNT_NOT_FIND.getCode()); + } + // 创建 OAuth2 请求对象并构建参数 + OAuth2Request request = OAuth2Request.create(); + // 默认管理组 + request.setTenantId(OAuth2TokenConstant.DEFAULT_TENANT_ID); + // 只设置账号 + request.getParameterArgs().set(USERNAME, account); + // 根据MK oauth的授权类型创建对应的 TokenGranter + TokenGranter tokenGranter = granterFactory.create(MK); + // 使用 TokenGranter 获取用户信息 + OAuth2User user = tokenGranter.user(request); + // 创建令牌 + OAuth2Token token = tokenGranter.token(user, request); + + // 对令牌进行增强处理 + OAuth2Token enhanceToken = tokenHandler.enhance(user, token, request); + + // 返回增强后的令牌 + return ResponseEntity.ok(enhanceToken.getArgs()); + } + + /** + * 输出消息 + * @param response + * @param message + */ + protected void writeMessage(HttpServletResponse response, String message) { + response.setCharacterEncoding(StandardCharsets.UTF_8.toString()); + try(PrintWriter writer = response.getWriter()) { + log.warn(message); + writer.println(message); + } catch (IOException e) { + log.error(message + "异常", e); + } + } + + /** + * 生成登录地址 + * @param refererUrl + * @return + */ + protected abstract String generateLoginUrl(String refererUrl); + + /** + * 根据mk授权码获取账号 + * @param mkCode + * @return + */ + protected abstract String getAccountByMkCode(String mkCode); + + /** + * 校验来源url,返回false,不跳转登录页面 + * @param refererUrl + * @return + */ + protected abstract boolean checkRefererUrl(String refererUrl); +} diff --git a/blade-core-auth/blade-core-oauth2/src/main/java/org/springblade/core/oauth2/exception/ExceptionCode.java b/blade-core-auth/blade-core-oauth2/src/main/java/org/springblade/core/oauth2/exception/ExceptionCode.java index 8567235..cfb57eb 100644 --- a/blade-core-auth/blade-core-oauth2/src/main/java/org/springblade/core/oauth2/exception/ExceptionCode.java +++ b/blade-core-auth/blade-core-oauth2/src/main/java/org/springblade/core/oauth2/exception/ExceptionCode.java @@ -74,6 +74,11 @@ public enum ExceptionCode implements Oauth2ExceptionCode { */ UNAUTHORIZED_USER(OAuth2ErrorCode.UNAUTHORIZED_USER, "认证信息错误或无效"), + /** + * 用户未授权 - 账号或密码不正确。 + */ + ACCOUNT_OR_PASSWORD_ERROR(OAuth2ErrorCode.ACCOUNT_OR_PASSWORD_ERROR, "账号或密码不正确"), + /** * 用户租户未授权 - 指定的用户租户未授权。 */ @@ -84,6 +89,21 @@ public enum ExceptionCode implements Oauth2ExceptionCode { */ INVALID_REFRESH_TOKEN(OAuth2ErrorCode.INVALID_REFRESH_TOKEN, "令牌刷新错误或无效"), + /** + * 用户未授权 - 无效的mk code + */ + INVALID_MK_CODE(OAuth2ErrorCode.INVALID_MK_CODE, "无效的mk code"), + + /** + * 用户未授权 - 获取mk账号错误 + */ + MK_ACCOUNT_NOT_FIND(OAuth2ErrorCode.MK_ACCOUNT_FETCH_ERROR, "获取MK账号错误"), + + /** + * 用户未授权 - mk账号未同步本系统 + */ + MK_ACCOUNT_NOT_SYNC_SYSTEM(OAuth2ErrorCode.MK_ACCOUNT_NOT_SYNC_SYSTEM, "MK账号【%s】未同步到本系统"), + /** * 客户端不存在 - 指定的客户端ID不存在或无效。 */ diff --git a/blade-core-auth/blade-core-oauth2/src/main/java/org/springblade/core/oauth2/exception/OAuth2ErrorCode.java b/blade-core-auth/blade-core-oauth2/src/main/java/org/springblade/core/oauth2/exception/OAuth2ErrorCode.java index 5e1d796..1f18834 100644 --- a/blade-core-auth/blade-core-oauth2/src/main/java/org/springblade/core/oauth2/exception/OAuth2ErrorCode.java +++ b/blade-core-auth/blade-core-oauth2/src/main/java/org/springblade/core/oauth2/exception/OAuth2ErrorCode.java @@ -59,10 +59,26 @@ public interface OAuth2ErrorCode { * 用户租户未授权 - 指定的用户租户未授权。 */ int UNAUTHORIZED_USER_TENANT = 2006; + /** + * 账号或密码不正确 + */ + int ACCOUNT_OR_PASSWORD_ERROR = 2007; /** * 令牌刷新错误或无效 - 刷新令牌认证信息错误或无效。 */ int INVALID_REFRESH_TOKEN = 2010; + /** + * 无效的mk code + */ + int INVALID_MK_CODE = 2020; + /** + * 获取mk账号错误 + */ + int MK_ACCOUNT_FETCH_ERROR = 2021; + /** + * mk账号未同步本系统 + */ + int MK_ACCOUNT_NOT_SYNC_SYSTEM = 2022; /** * 客户端不存在 - 指定的客户端ID不存在或无效。 */ diff --git a/blade-core-auth/blade-core-oauth2/src/main/java/org/springblade/core/oauth2/granter/AbstractTokenGranter.java b/blade-core-auth/blade-core-oauth2/src/main/java/org/springblade/core/oauth2/granter/AbstractTokenGranter.java index dd9f10d..8a2f11e 100644 --- a/blade-core-auth/blade-core-oauth2/src/main/java/org/springblade/core/oauth2/granter/AbstractTokenGranter.java +++ b/blade-core-auth/blade-core-oauth2/src/main/java/org/springblade/core/oauth2/granter/AbstractTokenGranter.java @@ -25,6 +25,7 @@ */ package org.springblade.core.oauth2.granter; +import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springblade.core.launch.constant.TokenConstant; @@ -66,8 +67,9 @@ public abstract class AbstractTokenGranter implements TokenGranter { * 认证失败原因:密码匹配失败 */ private static final String REASON_PASSWORD_MISMATCH = "密码匹配失败"; - + @Getter private final OAuth2ClientService clientService; + @Getter private final OAuth2UserService userService; private final PasswordHandler passwordHandler; diff --git a/blade-core-auth/blade-core-oauth2/src/main/java/org/springblade/core/oauth2/granter/MKTokenGranter.java b/blade-core-auth/blade-core-oauth2/src/main/java/org/springblade/core/oauth2/granter/MKTokenGranter.java new file mode 100644 index 0000000..71fbcea --- /dev/null +++ b/blade-core-auth/blade-core-oauth2/src/main/java/org/springblade/core/oauth2/granter/MKTokenGranter.java @@ -0,0 +1,81 @@ +package org.springblade.core.oauth2.granter; + +import org.springblade.core.oauth2.exception.ExceptionCode; +import org.springblade.core.oauth2.exception.OAuth2ErrorCode; +import org.springblade.core.oauth2.exception.OAuth2Exception; +import org.springblade.core.oauth2.handler.PasswordHandler; +import org.springblade.core.oauth2.provider.OAuth2Request; +import org.springblade.core.oauth2.service.OAuth2Client; +import org.springblade.core.oauth2.service.OAuth2ClientService; +import org.springblade.core.oauth2.service.OAuth2User; +import org.springblade.core.oauth2.service.OAuth2UserService; +import org.springblade.core.oauth2.utils.OAuth2ExceptionUtil; +import org.springframework.stereotype.Component; + +import java.util.Objects; +import java.util.Optional; + +/** + * PasswordTokenGranter + * + * @author BladeX + */ +@Component +public class MKTokenGranter extends AbstractTokenGranter { + /** + * MK client id + */ + private static final String MK_CLIENT_ID = "mk-oauth"; + + public MKTokenGranter(OAuth2ClientService clientService, OAuth2UserService userService, PasswordHandler passwordHandler) { + super(clientService, userService, passwordHandler); + } + + @Override + public String type() { + return MK; + } + + @Override + public OAuth2User user(OAuth2Request request) { + OAuth2User user = this.getUser(request); + return Optional.ofNullable(this.enhancer) + .map(enhancer -> enhancer.enhance(user, request)) + .orElse(user); + } + + @Override + public OAuth2Client client(OAuth2Request request) { + // 直接使用固定的client id + return getClientService().loadByClientId(MK_CLIENT_ID); + } + + private OAuth2User getUser(OAuth2Request request) { + // 获取用户信息 + OAuth2User user = getUserService().loadByUsername(request.getUsername(), request); + + // 用户不存在 + if (user == null) { + String message = String.format(ExceptionCode.MK_ACCOUNT_NOT_SYNC_SYSTEM.getMessage(), request.getUsername()); + throw new OAuth2Exception(ExceptionCode.MK_ACCOUNT_NOT_SYNC_SYSTEM, message); + } + + // 校验用户信息 + if (!getUserService().validateUser(Objects.requireNonNull(user))) { + OAuth2ExceptionUtil.throwFromCode(OAuth2ErrorCode.INVALID_USER); + } + + // 无需校验用户密码 + + //MK登进来检查是否是默认密码 + //MK登录跳过强制修改密码 + // user.setDefaultPwdFlag(false); + + // 设置客户端信息 + user.setClient(client(request)); + + // 返回用户信息 + return user; + } + +} diff --git a/blade-core-auth/blade-core-oauth2/src/main/java/org/springblade/core/oauth2/granter/TokenGranterFactory.java b/blade-core-auth/blade-core-oauth2/src/main/java/org/springblade/core/oauth2/granter/TokenGranterFactory.java index 01ac89e..082e62d 100644 --- a/blade-core-auth/blade-core-oauth2/src/main/java/org/springblade/core/oauth2/granter/TokenGranterFactory.java +++ b/blade-core-auth/blade-core-oauth2/src/main/java/org/springblade/core/oauth2/granter/TokenGranterFactory.java @@ -115,6 +115,7 @@ public class TokenGranterFactory { case WECHAT_APPLET -> properties.getGranter().getWechatApplet(); case SOCIAL -> properties.getGranter().getSocial(); case REGISTER -> properties.getGranter().getRegister(); + case MK -> properties.getGranter().getMk(); default -> true; }; } diff --git a/blade-core-auth/blade-core-oauth2/src/main/java/org/springblade/core/oauth2/handler/AbstractAuthorizationHandler.java b/blade-core-auth/blade-core-oauth2/src/main/java/org/springblade/core/oauth2/handler/AbstractAuthorizationHandler.java index 5a41c6a..241ef29 100644 --- a/blade-core-auth/blade-core-oauth2/src/main/java/org/springblade/core/oauth2/handler/AbstractAuthorizationHandler.java +++ b/blade-core-auth/blade-core-oauth2/src/main/java/org/springblade/core/oauth2/handler/AbstractAuthorizationHandler.java @@ -76,7 +76,7 @@ public abstract class AbstractAuthorizationHandler implements AuthorizationHandl */ @Override public OAuth2Validation authValidation(OAuth2User user, OAuth2Request request) { - if (request.isClientCredentials() || request.isImplicit() || request.isSocial()) { + if (request.isClientCredentials() || request.isImplicit() || request.isSocial() || request.isMk()) { return new OAuth2Validation(); } if (Func.hasEmpty(user, user.getUserId())) { diff --git a/blade-core-auth/blade-core-oauth2/src/main/java/org/springblade/core/oauth2/handler/OAuth2AuthorizationHandler.java b/blade-core-auth/blade-core-oauth2/src/main/java/org/springblade/core/oauth2/handler/OAuth2AuthorizationHandler.java index 8cd5852..864c2d9 100644 --- a/blade-core-auth/blade-core-oauth2/src/main/java/org/springblade/core/oauth2/handler/OAuth2AuthorizationHandler.java +++ b/blade-core-auth/blade-core-oauth2/src/main/java/org/springblade/core/oauth2/handler/OAuth2AuthorizationHandler.java @@ -61,7 +61,7 @@ public class OAuth2AuthorizationHandler extends AbstractAuthorizationHandler { */ @Override public void authFailure(OAuth2User user, OAuth2Request request, OAuth2Validation validation) { - + log.error("用户:{},认证失败,失败原因:{}", user.getAccount(), validation.getMessage()); } } diff --git a/blade-core-auth/blade-core-oauth2/src/main/java/org/springblade/core/oauth2/props/OAuth2Properties.java b/blade-core-auth/blade-core-oauth2/src/main/java/org/springblade/core/oauth2/props/OAuth2Properties.java index 515ee7e..9fa5559 100644 --- a/blade-core-auth/blade-core-oauth2/src/main/java/org/springblade/core/oauth2/props/OAuth2Properties.java +++ b/blade-core-auth/blade-core-oauth2/src/main/java/org/springblade/core/oauth2/props/OAuth2Properties.java @@ -65,6 +65,11 @@ public class OAuth2Properties { */ private String privateKey; + /** + * sm4密钥 + */ + private String sm4SecretKey; + /** * 授权模式 */ @@ -117,6 +122,10 @@ public class OAuth2Properties { * 是否开启注册模式 */ private Boolean register = true; + /** + * 是否开启 mk oauth模式 + */ + private Boolean mk = true; } } diff --git a/blade-core-auth/blade-core-oauth2/src/main/java/org/springblade/core/oauth2/provider/OAuth2Request.java b/blade-core-auth/blade-core-oauth2/src/main/java/org/springblade/core/oauth2/provider/OAuth2Request.java index 6ede858..92fa588 100644 --- a/blade-core-auth/blade-core-oauth2/src/main/java/org/springblade/core/oauth2/provider/OAuth2Request.java +++ b/blade-core-auth/blade-core-oauth2/src/main/java/org/springblade/core/oauth2/provider/OAuth2Request.java @@ -410,6 +410,14 @@ public class OAuth2Request { return SOCIAL.equals(getGrantType()); } + /** + * 是否mk oauth模式 + * @return + */ + public Boolean isMk() { + return MK.equals(getGrantType()); + } + /** * 设置租户ID * diff --git a/blade-core-auth/blade-core-oauth2/src/main/java/org/springblade/core/oauth2/utils/OAuth2ExceptionUtil.java b/blade-core-auth/blade-core-oauth2/src/main/java/org/springblade/core/oauth2/utils/OAuth2ExceptionUtil.java index 96f8e04..897ab4b 100644 --- a/blade-core-auth/blade-core-oauth2/src/main/java/org/springblade/core/oauth2/utils/OAuth2ExceptionUtil.java +++ b/blade-core-auth/blade-core-oauth2/src/main/java/org/springblade/core/oauth2/utils/OAuth2ExceptionUtil.java @@ -56,6 +56,9 @@ public class OAuth2ExceptionUtil { OAUTH2_EXCEPTION.put( ExceptionCode.INVALID_USER, () -> new UserInvalidException(ExceptionCode.INVALID_USER.getMessage(), new Throwable()) ); + OAUTH2_EXCEPTION.put( + ExceptionCode.ACCOUNT_OR_PASSWORD_ERROR, () -> new UserInvalidException(ExceptionCode.ACCOUNT_OR_PASSWORD_ERROR.getMessage()) + ); OAUTH2_EXCEPTION.put( ExceptionCode.UNAUTHORIZED_USER, () -> new UserUnauthorizedException(ExceptionCode.UNAUTHORIZED_USER.getMessage(), new Throwable()) ); @@ -95,6 +98,13 @@ public class OAuth2ExceptionUtil { OAUTH2_EXCEPTION.put( ExceptionCode.TEMPORARILY_UNAVAILABLE, () -> new OAuth2Exception(ExceptionCode.TEMPORARILY_UNAVAILABLE, ExceptionCode.TEMPORARILY_UNAVAILABLE.getMessage(), new Throwable()) ); + put(ExceptionCode.INVALID_MK_CODE); + put(ExceptionCode.MK_ACCOUNT_NOT_FIND); + put(ExceptionCode.MK_ACCOUNT_NOT_SYNC_SYSTEM); + } + + private static void put(ExceptionCode exceptionCode) { + OAUTH2_EXCEPTION.put(exceptionCode, () -> new OAuth2Exception(exceptionCode, exceptionCode.getMessage())); } /**