SpringCloud 使用Zuul防止xss攻擊和sql注入

SpringCloud 使用Zuul防止xss攻擊和sql注入

解決方法:使用string的本地方法 將特殊符號使用replaceAll方法替換掉,以防止xss攻擊

導入zuul的jar包

		<!--zuul-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
            <version>2.0.8.RELEASE</version>
        </dependency>

編寫一個過濾器SqLinjectionFilter,繼承ZuulFilter



import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import com.netflix.zuul.http.ServletInputStreamWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;
import org.springframework.util.StreamUtils;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.*;

/**
 * 攔截防止xss注入
 * 帶sql注入攔截 (舊版本)
 * 測試成功
 *
 * @author alone
 * @date 2020/4/11
 * @desciption XssFilter
 */
@Component
@Slf4j
@RefreshScope
@Deprecated
public class XssFilter extends ZuulFilter {

    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        return 1;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();
        String contentType = request.getContentType();
        if (StringUtils.isBlank(contentType)) {
            return null;
        } else if (StringUtils.equals(contentType, "application/x-www-form-urlencoded")
                || StringUtils.equals(contentType, "application/x-www-form-urlencoded;charset=UTF-8")) {
            Map<String, String[]> parameterMap = request.getParameterMap();
            Iterator it_d = parameterMap.entrySet().iterator();
            while (it_d.hasNext()) {
                Map.Entry<String, String[]> entry_d = (Map.Entry) it_d.next();
                String key = entry_d.getKey();
                String[] value = entry_d.getValue();
                if (value != null) {
                    List<String> strings = Arrays.asList(value);
                    for (int i = 0; i < strings.size(); i++) {
                        strings.set(i, StringEscapeUtils.escapeHtml(strings.get(i)));
                        strings.set(i, StringEscapeUtils.escapeJavaScript(strings.get(i)));
                    }
                }
                parameterMap.put(key, value);
            }
            String newBody = JSON.toJSONString(parameterMap);
            //	如果存在sql注入,直接攔截請求
            if (newBody.contains("forbid")) {
                setUnauthorizedResponse(requestContext);
            }
            final byte[] reqBodyBytes = newBody.getBytes();
            requestContext.setRequest(new HttpServletRequestWrapper(request) {

                @Override
                public ServletInputStream getInputStream() {
                    return new ServletInputStreamWrapper(reqBodyBytes);
                }

                @Override
                public int getContentLength() {
                    return reqBodyBytes.length;
                }

                @Override
                public long getContentLengthLong() {
                    return reqBodyBytes.length;
                }
            });

        } else if (StringUtils.equals(contentType, "application/json")
                || StringUtils.equals(contentType, "application/json;charset=UTF-8")) {
            try {
                InputStream in = requestContext.getRequest().getInputStream();
                String body = StreamUtils.copyToString(in, Charset.forName("UTF-8"));
                Map<String, Object> parameterMap = cleanXSS(body);

                String newBody = JSON.toJSONString(parameterMap);
                //	如果存在sql注入,直接攔截請求
                if (newBody.contains("forAlone")) {
                    setUnauthorizedResponse(requestContext);
                }
                final byte[] reqBodyBytes = newBody.getBytes();
                requestContext.setRequest(new HttpServletRequestWrapper(request) {

                    @Override
                    public ServletInputStream getInputStream() {
                        return new ServletInputStreamWrapper(reqBodyBytes);
                    }

                    @Override
                    public int getContentLength() {
                        return reqBodyBytes.length;
                    }

                    @Override
                    public long getContentLengthLong() {
                        return reqBodyBytes.length;
                    }
                });
            } catch (IOException e) {
                log.error("xss過濾器讀取參數異常", e);
            }
        }
        try {
            String s = StreamUtils.copyToString(requestContext.getRequest().getInputStream(), Charset.forName("UTF-8"));
            System.out.println(s);
        } catch (IOException e) {
            log.error("xss過濾器讀取參數異常", e);
        }
        return null;
    }

    private Map<String, Object> cleanXSS(String value) {
        value = value.replaceAll("<", "& lt;").replaceAll(">", "& gt;");
        value = value.replaceAll("\\(", "& #40;").replaceAll("\\)", "& #41;");
        value = value.replaceAll("'", "& #39;");
        value = value.replaceAll("eval\\((.*)\\)", "");
        value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\"");
        value = value.replaceAll("script", "");
        value = value.replaceAll("[*]", "[" + "*]");
        value = value.replaceAll("[+]", "[" + "+]");
        value = value.replaceAll("[?]", "[" + "?]");

        String badStr = "'|and|exec|execute|insert|select|delete|update|count|drop|%|chr|mid|master|truncate|" +
                "char|declare|sitename|net user|xp_cmdshell|;|or|+|,|like'|and|exec|execute|insert|create|drop|" +
                "table|from|grant|use|group_concat|column_name|" +
                "information_schema.columns|table_schema|union|where|select|delete|update|order|by|count|" +
                "chr|mid|master|truncate|char|declare|or|;|--|,|like|//|/|%|#";

        JSONObject json = JSON.parseObject(value);
        String[] badStrs = badStr.split("\\|");
        Map<String, Object> map = json;
        Map<String, Object> mapJson = new HashMap<>();
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            String value1 = entry.getValue().toString();
            for (String bad : badStrs) {
                if (value1.equalsIgnoreCase(bad)) {
                    value1 = "forAlone";
                    mapJson.put(entry.getKey(), value1);
                    break;
                } else {
                    mapJson.put(entry.getKey(), entry.getValue());
                }
            }
        }
        return mapJson;
    }

    /**
     * 設置500攔截狀態
     */
    private void setUnauthorizedResponse(RequestContext requestContext) {
        requestContext.setResponseBody(JSON.toJSONString(ResultBean.errorResult(500, "您填寫的值存在sql注入問題")));
    }

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章