From ec77e4aba5f8045db282fd72983d0fd69d0557af Mon Sep 17 00:00:00 2001 From: raodeming <1130305001@qq.com> Date: Sun, 8 May 2022 11:22:02 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96-----TokenFilter=20update?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../business/constant/BusinessConstant.java | 5 + .../gaea/business/filter/TokenFilter.java | 128 ++++++++++-------- 2 files changed, 80 insertions(+), 53 deletions(-) diff --git a/report-core/src/main/java/com/anjiplus/template/gaea/business/constant/BusinessConstant.java b/report-core/src/main/java/com/anjiplus/template/gaea/business/constant/BusinessConstant.java index 08357c95..4e2aa8f5 100644 --- a/report-core/src/main/java/com/anjiplus/template/gaea/business/constant/BusinessConstant.java +++ b/report-core/src/main/java/com/anjiplus/template/gaea/business/constant/BusinessConstant.java @@ -11,6 +11,11 @@ public interface BusinessConstant { String RIGTH_BIG_BOAST = "}"; String LEFT_MIDDLE_BOAST = "["; String RIGHT_MIDDLE_BOAST = "]"; + String SLASH = "/"; + + String USER_GUEST = "guest"; + String USER_ADMIN = "admin"; + /** * 字典项重复 diff --git a/report-core/src/main/java/com/anjiplus/template/gaea/business/filter/TokenFilter.java b/report-core/src/main/java/com/anjiplus/template/gaea/business/filter/TokenFilter.java index 5462a378..feb26f26 100644 --- a/report-core/src/main/java/com/anjiplus/template/gaea/business/filter/TokenFilter.java +++ b/report-core/src/main/java/com/anjiplus/template/gaea/business/filter/TokenFilter.java @@ -1,6 +1,5 @@ package com.anjiplus.template.gaea.business.filter; - import com.alibaba.fastjson.JSONObject; import com.anji.plus.gaea.bean.ResponseBean; import com.anji.plus.gaea.cache.CacheHelper; @@ -16,7 +15,6 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import org.springframework.util.AntPathMatcher; -import org.springframework.util.CollectionUtils; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; @@ -24,9 +22,9 @@ import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.concurrent.atomic.AtomicBoolean; import java.util.regex.Pattern; -import java.util.stream.Collectors; import static com.anji.plus.gaea.constant.GaeaConstant.URL_REPLACEMENT; @@ -39,23 +37,23 @@ import static com.anji.plus.gaea.constant.GaeaConstant.URL_REPLACEMENT; @Order(Integer.MIN_VALUE + 99) public class TokenFilter implements Filter { private static final Pattern PATTERN = Pattern.compile(".*().*"); - private static final String USER_GUEST = "guest"; - @Value("${server.servlet.context-path:'/'}") + @Value("${server.servlet.context-path:/}") private String SLASH = "/"; + private AntPathMatcher antPathMatcher = new AntPathMatcher(); @Autowired private CacheHelper cacheHelper; @Autowired private JwtBean jwtBean; - /** 跳过token验证和权限验证的url清单*/ - @Value("#{'${customer.skip-authenticate-urls}'.split(',')}") + /** + * 跳过token验证和权限验证的url清单 + */ + @Value("#{'${customer.skip-authenticate-urls:}'.split(',')}") private List skipAuthenticateUrls; private Pattern skipAuthenticatePattern; - private AntPathMatcher antPathMatcher = new AntPathMatcher(); - @Override public void init(FilterConfig filterConfig) throws ServletException { // 生成匹配正则,跳过token验证和权限验证的url @@ -69,13 +67,25 @@ public class TokenFilter implements Filter { HttpServletResponse response = (HttpServletResponse) servletResponse; String uri = request.getRequestURI(); + // TODO 暂时先不校验 直接放行 + /*if (true) { + filterChain.doFilter(request, response); + return; + }*/ + //OPTIONS直接放行 if ("OPTIONS".equalsIgnoreCase(request.getMethod())) { filterChain.doFilter(request, response); return; } - if (SLASH.equals(uri) || SLASH.concat("/").equals(uri)) { + // swagger相关的直接放行 + if (uri.contains("swagger-ui") || uri.contains("swagger-resources")) { + filterChain.doFilter(request, response); + return; + } + + if (SLASH.equals(uri) || SLASH.concat(BusinessConstant.SLASH).equals(uri)) { response.sendRedirect(SLASH + "/index.html"); return; } @@ -125,51 +135,19 @@ public class TokenFilter implements Filter { return; } String gaeaUserJsonStr = cacheHelper.stringGet(userKey); + // 延长有效期 + cacheHelper.stringSetExpire(tokenKey, token, 3600); + cacheHelper.stringSetExpire(userKey, gaeaUserJsonStr, 3600); - //判断接口权限 - //请求路径 - //String requestUrl = request.getRequestURI(); requestUrl中可能会有contextpath,而底层扫描的controller是没有的 - String servletPath = request.getServletPath(); - String methodValue = request.getMethod(); - //请求方法+#+请求路径 - String urlKey = methodValue + GaeaConstant.URL_SPLIT + servletPath; - - GaeaUserDto gaeaUserDto = JSONObject.parseObject(gaeaUserJsonStr, GaeaUserDto.class); - List authorities = gaeaUserDto.getAuthorities(); - Map applicationNameAllAuthorities = cacheHelper.hashGet(BusinessConstant.GAEA_SECURITY_AUTHORITIES); - AtomicBoolean authFlag = new AtomicBoolean(false); - //查询当前请求是否在对应的权限里。即:先精确匹配(保证当前路由是需要精确匹配还是模糊匹配,防止精确匹配的被模糊匹配) - // 比如:/user/info和/user/**同时存在,/user/info,被/user/**匹配掉 - if (applicationNameAllAuthorities.containsKey(urlKey)) { - String permissionCode = applicationNameAllAuthorities.get(urlKey); - if (authorities.contains(permissionCode)) { - authFlag.set(true); - } - } else { - List collect = applicationNameAllAuthorities.keySet().stream() - .filter(key -> StringUtils.isNotBlank(key) && key.contains(URL_REPLACEMENT)) - .filter(key -> antPathMatcher.match(key, urlKey)).collect(Collectors.toList()); - if (CollectionUtils.isEmpty(collect)) { - authFlag.set(true); - }else { - collect.forEach(key -> { - String permissionCode = applicationNameAllAuthorities.getOrDefault(key, ""); - if (authorities.contains(permissionCode)) { - authFlag.set(true); - } - }); + // 判断用户是否有该url的权限 + if (!BusinessConstant.USER_ADMIN.equals(loginName)) { + AtomicBoolean authorizeFlag = authorize(request, gaeaUserJsonStr); + if (!authorizeFlag.get()) { + authError(response);//无权限 + return; } } - if (!authFlag.get()) { - //无权限 - authError(response); - return; - } - - // 延长有效期 - cacheHelper.stringSetExpire(tokenKey, token, 3600); - cacheHelper.stringSetExpire(userKey, gaeaUserJsonStr, 3600); //执行 filterChain.doFilter(request, response); @@ -205,14 +183,58 @@ public class TokenFilter implements Filter { return Pattern.compile(patternString.toString()); } + /** 判断用户是否有该接口的权限 + * @return + */ + private AtomicBoolean authorize(HttpServletRequest request, String gaeaUserJsonStr){ + + //判断接口权限 + //请求路径 + String requestUrl = request.getRequestURI(); + if (!BusinessConstant.SLASH.equals(SLASH)) { + requestUrl = requestUrl.substring(SLASH.length()); + } + String methodValue = request.getMethod(); + //请求方法+#+请求路径 + String path = methodValue + GaeaConstant.URL_SPLIT + requestUrl; + + GaeaUserDto gaeaUserDto = JSONObject.parseObject(gaeaUserJsonStr, GaeaUserDto.class); + List userAuthorities = gaeaUserDto.getAuthorities(); + Map authoritiesAllMap = cacheHelper.hashGet(BusinessConstant.GAEA_SECURITY_AUTHORITIES); + + AtomicBoolean authFlag = new AtomicBoolean(false); + + // 接口GET#/gaeaDictItem/pageList + if(authoritiesAllMap.containsKey(path)){ + String permissionCode = authoritiesAllMap.get(path); + boolean flag = userAuthorities.contains(permissionCode); + authFlag.set(flag); + return authFlag; + } + + // 接口GET#/accessUser/roleTree/** + Optional optionalMatchKey = authoritiesAllMap.keySet().stream() + .filter(key -> StringUtils.isNotBlank(key) && key.contains(URL_REPLACEMENT)) + .filter(key -> antPathMatcher.match(key, path)).findFirst(); + if(optionalMatchKey.isPresent() == false){ + authFlag.set(true); + return authFlag; + } + String authoritieKey = optionalMatchKey.get(); + String needPermission = authoritiesAllMap.get(authoritieKey); + boolean flag = userAuthorities.contains(needPermission); + authFlag.set(flag); + return authFlag; + } + private void error(HttpServletResponse response) throws IOException { - ResponseBean responseBean = ResponseBean.builder().code("50014").message("The Token has expired").build(); + ResponseBean responseBean = ResponseBean.builder().code("50008").message("The Token has expired").build(); response.setContentType(ContentType.APPLICATION_JSON.getMimeType()); response.getWriter().print(JSONObject.toJSONString(responseBean)); } private void authError(HttpServletResponse response) throws IOException { - ResponseBean responseBean = ResponseBean.builder().code("User.no.authority").message("没有权限").build(); + ResponseBean responseBean = ResponseBean.builder().code("User.no.authority").message("no auth").build(); response.setContentType(ContentType.APPLICATION_JSON.getMimeType()); response.getWriter().print(JSONObject.toJSONString(responseBean)); }