diff --git a/kernel-a-rule/src/main/java/cn/stylefeng/roses/kernel/rule/pojo/response/ErrorResponseData.java b/kernel-a-rule/src/main/java/cn/stylefeng/roses/kernel/rule/pojo/response/ErrorResponseData.java index 41dff6e3a..863db1051 100644 --- a/kernel-a-rule/src/main/java/cn/stylefeng/roses/kernel/rule/pojo/response/ErrorResponseData.java +++ b/kernel-a-rule/src/main/java/cn/stylefeng/roses/kernel/rule/pojo/response/ErrorResponseData.java @@ -22,7 +22,8 @@ public class ErrorResponseData extends ResponseData { super(Boolean.FALSE, code, message, null); } - ErrorResponseData(String code, String message, Object object) { + public ErrorResponseData(String code, String message, Object object) { super(Boolean.FALSE, code, message, object); } + } diff --git a/kernel-a-rule/src/main/java/cn/stylefeng/roses/kernel/rule/util/AntPathMatcherUtil.java b/kernel-a-rule/src/main/java/cn/stylefeng/roses/kernel/rule/util/AntPathMatcherUtil.java new file mode 100644 index 000000000..ea3a886da --- /dev/null +++ b/kernel-a-rule/src/main/java/cn/stylefeng/roses/kernel/rule/util/AntPathMatcherUtil.java @@ -0,0 +1,35 @@ +package cn.stylefeng.roses.kernel.rule.util; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.util.AntPathMatcher; + +import java.util.List; + +/** + * ant风格资源过滤工具 + * + * @author fengshuonan + * @date 2020/12/15 22:31 + */ +@Slf4j +public class AntPathMatcherUtil { + + /** + * 判断某个接口是否在一组ant资源表达式下匹配 + * + * @param requestURI 请求的url + * @param antPatterns ant风格资源表达式 + * @author fengshuonan + * @date 2020/12/15 22:31 + */ + public static Boolean getAntMatchFLag(String requestURI, List antPatterns) { + AntPathMatcher antPathMatcher = new AntPathMatcher(); + for (String notAuthResourcePattern : antPatterns) { + if (antPathMatcher.match(notAuthResourcePattern, requestURI)) { + return true; + } + } + return false; + } + +} diff --git a/kernel-a-rule/src/main/java/cn/stylefeng/roses/kernel/rule/util/ResponseRenderUtil.java b/kernel-a-rule/src/main/java/cn/stylefeng/roses/kernel/rule/util/ResponseRenderUtil.java new file mode 100644 index 000000000..48545d5f8 --- /dev/null +++ b/kernel-a-rule/src/main/java/cn/stylefeng/roses/kernel/rule/util/ResponseRenderUtil.java @@ -0,0 +1,41 @@ +package cn.stylefeng.roses.kernel.rule.util; + +import cn.hutool.core.util.CharsetUtil; +import cn.hutool.http.ContentType; +import cn.stylefeng.roses.kernel.rule.pojo.response.ErrorResponseData; +import com.alibaba.fastjson.JSON; +import lombok.extern.slf4j.Slf4j; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * http响应信息的直接渲染工具 + * + * @author fengshuonan + * @date 2020/12/15 21:39 + */ +@Slf4j +public class ResponseRenderUtil { + + /** + * 渲染接口json信息 + * + * @author fengshuonan + * @date 2020/12/15 21:40 + */ + public static void renderErrorResponse(HttpServletResponse response, + String code, String message, String exceptionClazz) { + response.setCharacterEncoding(CharsetUtil.UTF_8); + response.setContentType(ContentType.JSON.toString()); + ErrorResponseData errorResponseData = new ErrorResponseData(code, message); + errorResponseData.setExceptionClazz(exceptionClazz); + String errorResponseJsonData = JSON.toJSONString(errorResponseData); + try { + response.getWriter().write(errorResponseJsonData); + } catch (IOException e) { + log.error("渲染http json信息错误!", e); + } + } + +} diff --git a/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/AuthServiceApi.java b/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/AuthServiceApi.java index 5af2a4788..d3d0535fd 100644 --- a/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/AuthServiceApi.java +++ b/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/AuthServiceApi.java @@ -70,6 +70,12 @@ public interface AuthServiceApi { /** * 校验用户访问的url是否认证通过 + *

+ * 校验会进行两方面: + *

+ * 第一,校验用户的token是否过期 + *

+ * 第二,校验用户的session是否失效,但是记住我的session失效后会自动创建session,之道jwt失效后 * * @param token 用户登陆的token * @param requestUrl 被校验的url diff --git a/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/exception/enums/AuthExceptionEnum.java b/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/exception/enums/AuthExceptionEnum.java index 0010ab052..4805c0ed2 100644 --- a/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/exception/enums/AuthExceptionEnum.java +++ b/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/exception/enums/AuthExceptionEnum.java @@ -17,7 +17,7 @@ public enum AuthExceptionEnum implements AbstractExceptionEnum { /** * 认证异常 */ - AUTH_ERROR(RuleConstants.BUSINESS_ERROR_TYPE_CODE + AuthConstants.AUTH_EXCEPTION_STEP_CODE + "01", "认证失败,请检查您的操作是否正确"), + AUTH_ERROR(RuleConstants.BUSINESS_ERROR_TYPE_CODE + AuthConstants.AUTH_EXCEPTION_STEP_CODE + "01", "认证失败,请检查您的登录是否过期"), /** * 登陆时,账号或密码为空 diff --git a/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/auth/AuthServiceImpl.java b/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/auth/AuthServiceImpl.java index 5bfc888c3..af9634e2e 100644 --- a/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/auth/AuthServiceImpl.java +++ b/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/auth/AuthServiceImpl.java @@ -27,9 +27,6 @@ import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.Date; -import static cn.stylefeng.roses.kernel.auth.api.exception.enums.AuthExceptionEnum.RESOURCE_DEFINITION_ERROR; -import static cn.stylefeng.roses.kernel.auth.api.exception.enums.AuthExceptionEnum.TOKEN_ERROR; - /** * 认证服务的实现 * @@ -94,29 +91,39 @@ public class AuthServiceImpl implements AuthServiceApi { @Override public void checkAuth(String token, String requestUrl) { - // 获取url对应的资源信息ResourceDefinition + // 1. 获取url对应的资源信息ResourceDefinition ResourceUrlParam resourceUrlReq = new ResourceUrlParam(); resourceUrlReq.setUrl(requestUrl); ResourceDefinition resourceDefinition = resourceServiceApi.getResourceByUrl(resourceUrlReq); - // 获取token对应的用户信息 - LoginUser session = sessionManagerApi.getSession(token); - if (session == null) { - throw new AuthException(TOKEN_ERROR); + // 2. 如果此接口不需要权限校验或者查询到资源为空,则放开过滤 + if (resourceDefinition == null || !resourceDefinition.getRequiredLogin()) { + return; } - // 资源为空,直接响应异常,禁止用户访问 - if (resourceDefinition == null) { - throw new AuthException(RESOURCE_DEFINITION_ERROR); - } - - // 检查接口是否需要鉴权 - Boolean requiredLogin = resourceDefinition.getRequiredLogin(); - - // 需要鉴权,则判断token是否过期 - if (requiredLogin) { + // 3. 如果当前接口需要鉴权,则校验用户token是否正确,校验失败会抛出异常 + if (resourceDefinition.getRequiredLogin()) { this.validateToken(token); } + + // 4. 如果token校验通过,获取token的payload,以及是否开启了记住我功能 + DefaultJwtPayload defaultPayload = JwtContext.me().getDefaultPayload(token); + Boolean rememberMe = defaultPayload.getRememberMe(); + + // 5. 获取用户的当前会话信息 + LoginUser loginUser = sessionManagerApi.getSession(token); + + // 6. 如果开了记住我,但是会话为空,则创建一次会话信息 + if (rememberMe && loginUser == null) { + UserLoginInfoDTO userLoginInfo = userServiceApi.getUserLoginInfo(defaultPayload.getAccount()); + sessionManagerApi.createSession(token, userLoginInfo.getLoginUser()); + } + + // 7. 如果会话信息为空,则判定此次校验失败 + if (loginUser == null) { + throw new AuthException(AuthExceptionEnum.AUTH_ERROR); + } + } /** diff --git a/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/permission/PermissionServiceImpl.java b/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/permission/PermissionServiceImpl.java index ba11598da..8da8db19a 100644 --- a/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/permission/PermissionServiceImpl.java +++ b/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/permission/PermissionServiceImpl.java @@ -12,7 +12,8 @@ import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.Set; -import static cn.stylefeng.roses.kernel.auth.api.exception.enums.AuthExceptionEnum.*; +import static cn.stylefeng.roses.kernel.auth.api.exception.enums.AuthExceptionEnum.PERMISSION_RES_VALIDATE_ERROR; +import static cn.stylefeng.roses.kernel.auth.api.exception.enums.AuthExceptionEnum.TOKEN_ERROR; /** * 权限相关的service @@ -32,30 +33,31 @@ public class PermissionServiceImpl implements PermissionServiceApi { @Override public void checkPermission(String token, String requestUrl) { - // 获取token对应的用户信息 + // 1. 获取url对应的资源信息ResourceDefinition + ResourceUrlParam resourceUrlReq = new ResourceUrlParam(); + resourceUrlReq.setUrl(requestUrl); + ResourceDefinition resourceDefinition = resourceServiceApi.getResourceByUrl(resourceUrlReq); + + // 2. 如果此接口不需要权限校验或者查询到资源为空,则放开过滤 + if (resourceDefinition == null || !resourceDefinition.getRequiredPermission()) { + return; + } + + // 3. 获取token对应的用户信息 LoginUser session = sessionManagerApi.getSession(token); if (session == null) { throw new AuthException(TOKEN_ERROR); } - // 获取url对应的资源信息ResourceDefinition - ResourceUrlParam resourceUrlReq = new ResourceUrlParam(); - resourceUrlReq.setUrl(requestUrl); - ResourceDefinition resourceDefinition = resourceServiceApi.getResourceByUrl(resourceUrlReq); - - // 资源为空,直接响应异常,禁止用户访问 - if (resourceDefinition == null) { - throw new AuthException(RESOURCE_DEFINITION_ERROR); - } - - // 检查接口是否需要权限验证 - Boolean requiredPermission = resourceDefinition.getRequiredPermission(); - - // 需要权限认证,验证用户有没有当前url的权限 - if (requiredPermission) { + // 4. 如果需要权限认证,验证用户有没有当前url的权限 + if (resourceDefinition.getRequiredPermission()) { Set resourceUrls = session.getResourceUrls(); if (resourceUrls == null || resourceUrls.size() == 0) { throw new AuthException(PERMISSION_RES_VALIDATE_ERROR); + } else { + if (!resourceUrls.contains(requestUrl)) { + throw new AuthException(PERMISSION_RES_VALIDATE_ERROR); + } } } } diff --git a/kernel-d-jwt/jwt-api/src/main/java/cn/stylefeng/roses/kernel/jwt/api/pojo/payload/DefaultJwtPayload.java b/kernel-d-jwt/jwt-api/src/main/java/cn/stylefeng/roses/kernel/jwt/api/pojo/payload/DefaultJwtPayload.java index 2ca93d375..5dbcdce98 100644 --- a/kernel-d-jwt/jwt-api/src/main/java/cn/stylefeng/roses/kernel/jwt/api/pojo/payload/DefaultJwtPayload.java +++ b/kernel-d-jwt/jwt-api/src/main/java/cn/stylefeng/roses/kernel/jwt/api/pojo/payload/DefaultJwtPayload.java @@ -32,7 +32,7 @@ public class DefaultJwtPayload { /** * 是否记住我 */ - private boolean rememberMe; + private Boolean rememberMe; /** * 其他载体信息