package cn.stylefeng.rest.core.security.base; import cn.hutool.core.util.StrUtil; import cn.stylefeng.roses.kernel.auth.api.AuthServiceApi; import cn.stylefeng.roses.kernel.auth.api.SessionManagerApi; import cn.stylefeng.roses.kernel.auth.api.constants.AuthConstants; import cn.stylefeng.roses.kernel.auth.api.context.LoginContext; import cn.stylefeng.roses.kernel.auth.api.exception.AuthException; import cn.stylefeng.roses.kernel.auth.api.exception.enums.AuthExceptionEnum; import cn.stylefeng.roses.kernel.auth.api.expander.AuthConfigExpander; import cn.stylefeng.roses.kernel.jwt.api.pojo.payload.DefaultJwtPayload; import cn.stylefeng.roses.kernel.rule.util.AntPathMatcherUtil; import cn.stylefeng.roses.kernel.scanner.api.pojo.resource.ResourceDefinition; import cn.stylefeng.roses.kernel.system.api.ResourceServiceApi; import lombok.extern.slf4j.Slf4j; import org.springframework.web.servlet.HandlerInterceptor; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * 基础的Filter,一般用在权限过滤 * * @author fengshuonan * @since 2020/12/15 22:50 */ @Slf4j public abstract class BaseSecurityInterceptor implements HandlerInterceptor { @Resource private ResourceServiceApi resourceServiceApi; @Resource private AuthServiceApi authServiceApi; @Resource private SessionManagerApi sessionManagerApi; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { // 1. 获取当前请求的路径 String requestURI = request.getRequestURI(); requestURI = requestURI.replaceAll("/+", "/"); // 2. 不需要权限过滤的资源,直接放行 Boolean noneSecurityFlag = AntPathMatcherUtil.getAntMatchFLag(requestURI, request.getContextPath(), AuthConfigExpander.getNoneSecurityConfig()); if (noneSecurityFlag) { return true; } // 3. 获取当前用户的token,可能为null String token = request.getHeader(AuthConstants.DEFAULT_AUTH_HEADER_NAME); try { token = LoginContext.me().getToken(); } catch (Exception e) { // 不做处理,因为本接口可能是不需要鉴权 } // 4. 如果token不为空,则先判断是否登录过期了,过期了就直接打回,不过期不做处理 if (StrUtil.isNotBlank(token)) { DefaultJwtPayload defaultJwtPayload = null; try { defaultJwtPayload = authServiceApi.validateToken(token); } catch (AuthException authException) { if (AuthExceptionEnum.AUTH_EXPIRED_ERROR.getErrorCode().equals(authException.getErrorCode())) { sessionManagerApi.destroySessionCookie(); throw authException; } } // 5. 刷新用户的session的过期时间 sessionManagerApi.refreshSession(token); // 5.1 token没过期,但是session过期了,则从新进行会话创建操作,因为只有开启remember的用户才有这种情况 if (defaultJwtPayload != null && !sessionManagerApi.haveSession(token)) { authServiceApi.createNewLoginInfo(token, defaultJwtPayload); } } // 6. 获取ResourceDefinition,可能为null // ResourceUrlParam resourceUrlParam = new ResourceUrlParam(); // resourceUrlParam.setUrl(requestURI); ResourceDefinition resourceDefinition = new ResourceDefinition(); resourceDefinition.setUrl(requestURI); resourceDefinition.setRequiredLoginFlag(true); resourceDefinition.setRequiredPermissionFlag(false); // ResourceDefinition resourceDefinition = resourceServiceApi.getResourceByUrl(resourceUrlParam); // // // 7. 资源找不到,则当前url不被权限控制,直接打回 // if (resourceDefinition == null) { // throw new AuthException(AuthExceptionEnum.CANT_REQUEST_UN_OPEN_API, requestURI); // } // 8.执行真正过滤器业务,如果拦截器执行不成功会抛出异常 this.filterAction(request, response, resourceDefinition, token); return true; } /** * 过滤器的具体业务执行逻辑 * * @author fengshuonan * @since 2020/12/15 22:52 */ public abstract void filterAction(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, ResourceDefinition resourceDefinition, String token); }