修复xssbug
This commit is contained in:
parent
47993beebd
commit
219f28c3c1
1
pom.xml
1
pom.xml
|
@ -112,7 +112,6 @@
|
|||
<artifactId>sa-token-dao-redis-jackson</artifactId>
|
||||
<version>1.26.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- thymeleaf模版 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
package com.fc.v2.common.conf.xss;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
|
@ -10,35 +11,61 @@ import javax.servlet.ServletRequest;
|
|||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import com.fc.v2.util.StringUtils;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class SimpleCORSFilter implements Filter {
|
||||
|
||||
/**
|
||||
* 排除链接
|
||||
*/
|
||||
public List<String> excludes = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest req, ServletResponse res,
|
||||
FilterChain chain) throws IOException, ServletException {
|
||||
// 在这里,使用我们实现的XSS过滤器
|
||||
XssHttpServletRequestWrapper request =
|
||||
new XssHttpServletRequestWrapper((HttpServletRequest) req);
|
||||
|
||||
HttpServletResponse response = (HttpServletResponse) res;
|
||||
response.setHeader("Access-Control-Allow-Origin", "*");
|
||||
response.setHeader("Access-Control-Allow-Methods",
|
||||
"POST, GET, PUT, OPTIONS, DELETE");
|
||||
response.setHeader("Access-Control-Max-Age", "3600");
|
||||
response.setHeader("Access-Control-Allow-Headers",
|
||||
"Origin, X-Requested-With, Content-Type, Accept, token");
|
||||
|
||||
chain.doFilter(request, response);
|
||||
public void doFilter(ServletRequest req, ServletResponse res,FilterChain chain) throws IOException, ServletException {
|
||||
|
||||
// 在这里,使用我们实现的XSS过滤器
|
||||
XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) req);
|
||||
HttpServletResponse response = (HttpServletResponse) res;
|
||||
HttpServletRequest request = (HttpServletRequest) req;
|
||||
if (handleExcludeURL(request, response))
|
||||
{
|
||||
chain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
response.setHeader("Access-Control-Allow-Origin", "*");
|
||||
response.setHeader("Access-Control-Allow-Methods","POST, GET, PUT, OPTIONS, DELETE");
|
||||
response.setHeader("Access-Control-Max-Age", "3600");
|
||||
response.setHeader("Access-Control-Allow-Headers","Origin, X-Requested-With, Content-Type, Accept, token");
|
||||
chain.doFilter(xssRequest, response);
|
||||
|
||||
}
|
||||
|
||||
public void init(FilterConfig filterConfig) {
|
||||
String tempExcludes = filterConfig.getInitParameter("exclusions");
|
||||
if (StringUtils.isNotEmpty(tempExcludes))
|
||||
{
|
||||
String[] url = tempExcludes.split(",");
|
||||
for (int i = 0; url != null && i < url.length; i++)
|
||||
{
|
||||
excludes.add(url[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean handleExcludeURL(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
String url = request.getServletPath();
|
||||
String method = request.getMethod();
|
||||
// GET DELETE 不过滤
|
||||
if (method == null || method.matches("GET") || method.matches("DELETE"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return StringUtils.matches(url, excludes);
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -3,12 +3,7 @@ package com.fc.v2.common.conf.xss;
|
|||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
import com.fc.v2.common.conf.V2Config;
|
||||
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
@ -29,8 +24,8 @@ public class XssFilterAtuoConfig {
|
|||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public FilterRegistrationBean xssFiltrRegister() {
|
||||
FilterRegistrationBean registration = new FilterRegistrationBean();
|
||||
public FilterRegistrationBean<SimpleCORSFilter> xssFiltrRegister() {
|
||||
FilterRegistrationBean<SimpleCORSFilter> registration = new FilterRegistrationBean<SimpleCORSFilter>();
|
||||
//设置系统过滤器 (setFilter就是你所定义的过滤器filter类)
|
||||
registration.setFilter(new SimpleCORSFilter());
|
||||
|
||||
|
@ -45,12 +40,11 @@ public class XssFilterAtuoConfig {
|
|||
if(xssnoturlList!=null&&xssnoturlList.size()>0) {
|
||||
xssnot=String.join(",", xssnoturlList);
|
||||
}
|
||||
|
||||
|
||||
//添加忽略的格式以及链接请求
|
||||
registration.addInitParameter("exclusions","*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid2/*,"+xssnot);
|
||||
//优先级
|
||||
registration.setOrder(1);
|
||||
|
||||
return registration;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,19 +1,24 @@
|
|||
package com.fc.v2.common.exception;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.validation.BindException;
|
||||
import org.springframework.web.HttpRequestMethodNotSupportedException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.fc.v2.common.conf.V2Config;
|
||||
import com.fc.v2.common.domain.AjaxResult;
|
||||
import com.fc.v2.common.exception.demo.DemoModeException;
|
||||
import com.fc.v2.util.ServletUtils;
|
||||
|
||||
import cn.dev33.satoken.exception.NotLoginException;
|
||||
import cn.dev33.satoken.exception.NotPermissionException;
|
||||
import cn.dev33.satoken.exception.NotRoleException;
|
||||
|
@ -29,6 +34,9 @@ import cn.dev33.satoken.exception.SaTokenException;
|
|||
public class GlobalExceptionResolver{
|
||||
private static Logger logger = LoggerFactory.getLogger(GlobalExceptionResolver.class);
|
||||
|
||||
@Autowired
|
||||
private V2Config v2Config;
|
||||
|
||||
/**
|
||||
* 权限校验失败 如果请求为ajax返回json,普通请求跳转页面
|
||||
*/
|
||||
|
@ -45,10 +53,24 @@ public class GlobalExceptionResolver{
|
|||
{
|
||||
// 登录认证异常
|
||||
if(e instanceof NotLoginException){
|
||||
List<String> satoken_not_urls=v2Config.getSaTokenNotFilterUrl();
|
||||
for (String nourl : satoken_not_urls) {
|
||||
AntPathMatcher matcher = new AntPathMatcher();
|
||||
if(matcher.match(nourl,request.getRequestURI())) {
|
||||
return JSON.toJSONString(AjaxResult.error(886,e.getMessage()));
|
||||
}
|
||||
}
|
||||
return new ModelAndView("/login");
|
||||
}
|
||||
// 权限认证异常
|
||||
else if (e instanceof NotPermissionException || e instanceof NotRoleException || e instanceof NotSafeException){
|
||||
List<String> satoken_not_urls=v2Config.getSaTokenNotFilterUrl();
|
||||
for (String nourl : satoken_not_urls) {
|
||||
AntPathMatcher matcher = new AntPathMatcher();
|
||||
if(matcher.match(nourl,request.getRequestURI())) {
|
||||
return JSON.toJSONString(AjaxResult.error(403,e.getMessage()));
|
||||
}
|
||||
}
|
||||
return new ModelAndView("/error/403");
|
||||
}
|
||||
// 其它异常
|
||||
|
|
|
@ -6,7 +6,6 @@ import com.fc.v2.common.domain.ResultTable;
|
|||
import com.fc.v2.model.auto.GoviewProject;
|
||||
import com.fc.v2.model.auto.GoviewProjectData;
|
||||
import com.fc.v2.model.auto.GoviewProjectDataExample;
|
||||
import com.fc.v2.model.auto.GoviewProjectExample;
|
||||
import com.fc.v2.model.custom.Tablepar;
|
||||
import com.fc.v2.service.GoviewProjectDataService;
|
||||
import com.fc.v2.service.GoviewProjectService;
|
||||
|
@ -14,9 +13,7 @@ import com.github.pagehelper.PageInfo;
|
|||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
|
@ -171,7 +168,7 @@ public class GoviewProjectAPi extends BaseController{
|
|||
@ApiOperation(value = "保存项目数据", notes = "保存项目数据")
|
||||
@PostMapping("/save/data")
|
||||
@ResponseBody
|
||||
public AjaxResult saveData(@RequestBody GoviewProjectData data) {
|
||||
public AjaxResult saveData(GoviewProjectData data) {
|
||||
|
||||
GoviewProject goviewProject= goviewProjectService.selectByPrimaryKey(data.getProjectId());
|
||||
if(goviewProject==null) {
|
||||
|
|
|
@ -86,6 +86,11 @@ public class SaTokenConfigure implements WebMvcConfigurer {
|
|||
.setError(e -> {
|
||||
// e.printStackTrace();
|
||||
if(e instanceof NotLoginException) {
|
||||
for (String nourl : satoken_not_urls) {
|
||||
if(nourl.contains(SaHolder.getRequest().getUrl())) {
|
||||
return JSON.toJSONString(AjaxResult.error(886,e.getMessage()));
|
||||
}
|
||||
}
|
||||
SaHolder.getResponse().redirect("/admin/login");
|
||||
}
|
||||
return JSON.toJSONString(AjaxResult.error(e.getMessage()));
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
package com.fc.v2.util;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.apache.commons.lang.WordUtils;
|
||||
import org.apache.commons.lang.text.StrBuilder;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
|
||||
|
||||
|
||||
|
@ -441,4 +443,42 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
|
|||
}
|
||||
return columnToJava(tableName);
|
||||
}
|
||||
/**
|
||||
* 查找指定字符串是否匹配指定字符串列表中的任意一个字符串
|
||||
*
|
||||
* @param str 指定字符串
|
||||
* @param strs 需要检查的字符串数组
|
||||
* @return 是否匹配
|
||||
*/
|
||||
public static boolean matches(String str, List<String> strs)
|
||||
{
|
||||
if (isEmpty(str) || isEmpty(strs))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (String pattern : strs)
|
||||
{
|
||||
if (isMatch(pattern, str))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* 判断url是否与规则配置:
|
||||
* ? 表示单个字符;
|
||||
* * 表示一层路径内的任意字符串,不可跨层级;
|
||||
* ** 表示任意层路径;
|
||||
*
|
||||
* @param pattern 匹配规则
|
||||
* @param url 需要匹配的url
|
||||
* @return
|
||||
*/
|
||||
public static boolean isMatch(String pattern, String url)
|
||||
{
|
||||
AntPathMatcher matcher = new AntPathMatcher();
|
||||
return matcher.match(pattern, url);
|
||||
}
|
||||
|
||||
}
|
|
@ -20,7 +20,7 @@ fuce:
|
|||
#漂亮得拖动验证码 默认false普通验证码、true滚动验证码
|
||||
roll-verification: false
|
||||
#xss不拦截url
|
||||
xss-not-filter-url: [/api/v1/token/api_token,/api/v1/yibaotong/save]
|
||||
xss-not-filter-url: [/api/v1/token/api_token,/api/goview/project/save/data]
|
||||
#satoken不拦截url
|
||||
sa-token-not-filter-url: [/api/goview/sys/*,/api/goview/project/**]
|
||||
#tomcat config
|
||||
|
|
Loading…
Reference in New Issue