优化-----TokenFilter update

raodeming 3 years ago
parent 7e7f9a89b4
commit ec77e4aba5

@ -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";
/**
*

@ -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(',')}")
/**
* tokenurl
*/
@Value("#{'${customer.skip-authenticate-urls:}'.split(',')}")
private List<String> 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<String> authorities = gaeaUserDto.getAuthorities();
Map<String, String> 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<String> 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<String> userAuthorities = gaeaUserDto.getAuthorities();
Map<String, String> 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<String> 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));
}

Loading…
Cancel
Save