springboot 項目先後端接口,防止xss攻擊以及跨域問題解決javascript
@ServletComponentScancss
package com.longfor.hrssc.api.config; import com.longfor.hrssc.common.util.ResultUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.PropertySource; import org.springframework.stereotype.Component; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Arrays; import java.util.HashSet; import java.util.Set; @Component @PropertySource("classpath:application-dev.yml") @WebFilter(urlPatterns = "/*", filterName = "CorsFilter") public class CorsFilter implements Filter { @Value("${bpm.fiter.domain}") private String allowDomains; @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletResponse response = (HttpServletResponse) res; HttpServletRequest reqs = (HttpServletRequest) req; // 設置容許多個域名請求 //String[] allowDomains = {"http://www.xxxx.xin","http://xxxx:8080","http://localhost:8080"}; String[] allowDomain = allowDomains.split(","); Set allowOrigins = new HashSet(Arrays.asList(allowDomain)); String curOrigin = reqs.getHeader("Origin"); /*if("null".equalsIgnoreCase(curOrigin)){ curOrigin = "http://xxxxxx:8888"; }*/ if(allowOrigins.contains(curOrigin) || null == curOrigin){ //設置容許跨域的配置 // 這裏填寫你容許進行跨域的主機ip(正式上線時能夠動態配置具體容許的域名和IP) response.setHeader("Access-Control-Allow-Origin", curOrigin); response.setHeader("Access-Control-Allow-Credentials", "true"); //response.setHeader("Access-Control-Allow-Methods", "POST, GET, PATCH, DELETE, PUT"); response.setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, DELETE, OPTIONS, PATCH"); response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, token"); chain.doFilter(reqs, response); }else{ throw new IOException(ResultUtils.doFilter().toString()); } } @Override public void init(FilterConfig filterConfig) {} @Override public void destroy() {} }
XssFilter
package com.longfor.hrssc.api.config; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import java.io.IOException; /** * XSS過濾器 * @author Jozz */ @WebFilter(filterName="xssFilter",urlPatterns="/*") public class XssFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest)servletRequest; String path = request.getServletPath(); //因爲個人@WebFilter註解配置的是urlPatterns="/*"(過濾全部請求),因此這裏對不須要過濾的靜態資源url,做忽略處理(你們能夠依照具體需求配置) String[] exclusionsUrls = {".js",".gif",".jpg",".png",".css",".ico"}; for (String str : exclusionsUrls) { if (path.contains(str)) { filterChain.doFilter(servletRequest,servletResponse); return; } } filterChain.doFilter(new XssHttpServletRequestWrapper(request),servletResponse); } @Override public void destroy() { } }
XssHttpServletRequestWrapper
package com.longfor.hrssc.api.config; /** * Created by 裴帥楠 on 2019/7/10. */ import com.alibaba.fastjson.JSON; import org.apache.commons.lang3.StringEscapeUtils; import org.apache.commons.lang3.StringUtils; //import org.apache.commons.text.StringEscapeUtils; import javax.servlet.ReadListener; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import java.io.*; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * ServletRequest包裝類,對request作XSS過濾處理 * @author Jozz * * */ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper { public XssHttpServletRequestWrapper(HttpServletRequest request) { super(request); } @Override public String getHeader(String name) { return StringEscapeUtils.escapeHtml4(super.getHeader(name)); } @Override public String getQueryString() { return StringEscapeUtils.escapeHtml4(super.getQueryString()); } @Override public String getParameter(String name) { return StringEscapeUtils.escapeHtml4(super.getParameter(name)); } @Override public String[] getParameterValues(String name) { String[] values = super.getParameterValues(name); if(values != null) { int length = values.length; String[] escapseValues = new String[length]; for(int i = 0; i < length; i++){ escapseValues[i] = StringEscapeUtils.escapeHtml4(values[i]); } return escapseValues; } return values; } @Override public ServletInputStream getInputStream() throws IOException { String str=getRequestBody(super.getInputStream()); Map<String,Object> map= JSON.parseObject(str,Map.class); Map<String,Object> resultMap=new HashMap<>(map.size()); for(String key:map.keySet()){ Object val=map.get(key); if(null != val){ stripXss(val.toString()); } if(map.get(key) instanceof String){ resultMap.put(key,StringEscapeUtils.escapeHtml4(val.toString())); }else{ resultMap.put(key,val); } } str=JSON.toJSONString(resultMap); final ByteArrayInputStream bais = new ByteArrayInputStream(str.getBytes()); return new ServletInputStream() { @Override public int read() throws IOException { return bais.read(); } @Override public boolean isFinished() { return false; } @Override public boolean isReady() { return false; } @Override public void setReadListener(ReadListener listener) { } }; } private String getRequestBody(InputStream stream) { String line = ""; StringBuilder body = new StringBuilder(); int counter = 0; // 讀取POST提交的數據內容 BufferedReader reader = new BufferedReader(new InputStreamReader(stream, Charset.forName("UTF-8"))); try { while ((line = reader.readLine()) != null) { body.append(line); counter++; } } catch (IOException e) { e.printStackTrace(); } return body.toString(); } private static List<Pattern> patterns = null; public static String stripXss(String value) { if(StringUtils.isNotBlank(value)) { Matcher matcher = null; for(Pattern pattern : getPatterns()) { matcher = pattern.matcher(value); // 匹配 if(matcher.find()) { // 刪除相關字符串 value = matcher.replaceAll(""); } } value = value.replaceAll("<", "<").replaceAll(">", ">"); } /* if (LOG.isDebugEnabled()) { LOG.debug("strip value: " + value); return value; }*/ return value; } private static List<Object[]> getXssPatternList() { List<Object[]> ret = new ArrayList<Object[]>(); ret.add(new Object[]{"<(no)?script[^>]*>.*?</(no)?script>", Pattern.CASE_INSENSITIVE}); ret.add(new Object[]{"eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL}); ret.add(new Object[]{"expression\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL}); ret.add(new Object[]{"(javascript:|vbscript:|view-source:)*", Pattern.CASE_INSENSITIVE}); ret.add(new Object[]{"<(\"[^\"]*\"|\'[^\']*\'|[^\'\">])*>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL}); ret.add(new Object[]{"(window\\.location|window\\.|\\.location|document\\.cookie|document\\.|alert\\(.*?\\)|window\\.open\\()*", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL}); ret.add(new Object[]{"<+\\s*\\w*\\s*(oncontrolselect|oncopy|oncut|ondataavailable|ondatasetchanged|ondatasetcomplete|ondblclick|ondeactivate|ondrag|ondragend|ondragenter|ondragleave|ondragover|ondragstart|ondrop|onerror=|onerroupdate|onfilterchange|onfinish|onfocus|onfocusin|onfocusout|onhelp|onkeydown|onkeypress|onkeyup|onlayoutcomplete|onload|onlosecapture|onmousedown|onmouseenter|onmouseleave|onmousemove|onmousout|onmouseover|onmouseup|onmousewheel|onmove|onmoveend|onmovestart|onabort|onactivate|onafterprint|onafterupdate|onbefore|onbeforeactivate|onbeforecopy|onbeforecut|onbeforedeactivate|onbeforeeditocus|onbeforepaste|onbeforeprint|onbeforeunload|onbeforeupdate|onblur|onbounce|oncellchange|onchange|onclick|oncontextmenu|onpaste|onpropertychange|onreadystatechange|onreset|onresize|onresizend|onresizestart|onrowenter|onrowexit|onrowsdelete|onrowsinserted|onscroll|onselect|onselectionchange|onselectstart|onstart|onstop|onsubmit|onunload)+\\s*=+", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL}); return ret; } private static List<Pattern> getPatterns() { if (patterns == null) { List<Pattern> list = new ArrayList<Pattern>(); String regex = null; Integer flag = null; int arrLength = 0; for(Object[] arr : getXssPatternList()) { arrLength = arr.length; for(int i = 0; i < arrLength; i++) { regex = (String)arr[0]; flag = (Integer)arr[1]; list.add(Pattern.compile(regex, flag)); } } patterns = list; } return patterns; } }
#bpm域名過濾 bpm: fiter: domain: http://xxx.sit,https://xxxxx.net:8089,http://xxxxx.sit:8088,http://xxxxx:8888,https://xxxxx:8443
/** * 跨域白名單 * @return */ public static ResultUtils doFilter() { return new ResultUtils(Constants.doFilterCode, Constants.doFilterException, null); }
public static final int doFilterCode = 403; public static final String doFilterException = "請申請IP白名單";