/**
 * Copyright 2018 北航天华 www.ibuaa.com
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package com.changfa.xss;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.changfa.constants.ApiResult;
import com.changfa.utils.MimeUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * SQL过滤
 * @author wwz
 * @date 2017-04-01 16:16
 */
@Component
public class SQLFilter implements Filter {

    private final static   String[] keywords = {"master", "truncate", "insert", "select", "delete", "update", "declare", "alter", "drop","alert","javascript","jscript","vbscript"};


    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        String contentType = request.getContentType();
        if(MimeUtils.validateIsMultiFile(contentType)){
            chain.doFilter(request, response);
            return;
        }
        SqlHttpServletRequestWrapper requestWrapper = new SqlHttpServletRequestWrapper(request);
        Map<String, Object> parameterMap = new HashMap<>();
        parameterMap =getParameterMap(parameterMap, request, requestWrapper);
        // 正则校验是否有SQL关键字
        for (Object obj : parameterMap.entrySet()) {
            Map.Entry entry = (Map.Entry) obj;
            Object value = entry.getValue();
            if (value != null) {
                boolean isValid = sqlInject(value.toString(), response);
                if (isValid) {
                    return;
                }
            }
        }
        chain.doFilter(requestWrapper, response);
    }

    /**
     * SQL注入过滤
     * @param str  待验证的字符串
     */
    public  boolean sqlInject(String str,ServletResponse servletResponse) throws IOException {
        if(StringUtils.isBlank(str)){
            return false;
        }
        HttpServletResponse response = (HttpServletResponse)servletResponse;

        //去掉'|"|;|\字符
        str = StringUtils.replace(str, "'", "");
        str = StringUtils.replace(str, "\"", "");
        str = StringUtils.replace(str, ";", "");
        str = StringUtils.replace(str, "\\", "");

        //转换成小写
        str = str.toLowerCase();

        //非法字符
        //判断是否包含非法字符
        for(String keyword : keywords){
            if(str.indexOf(keyword) != -1){
                // 匹配到非法字符,立即返回
                ApiResult apiResult = ApiResult.error("包含非法的字符！");
                response.setContentType("application/json;charset=UTF-8");
                response.setHeader("Access-Control-Allow-Origin","*");
                response.setHeader("Access-Control-Allow-Credentials","true");
                response.getWriter().write(JSON.toJSONString(apiResult));
                response.getWriter().flush();
                response.getWriter().close();
                return true;
            }
        }
        return false;
    }

    private Map<String, Object> getParameterMap(Map<String, Object> paramMap, HttpServletRequest request, SqlHttpServletRequestWrapper requestWrapper) {
        // 1.POST请求获取参数
        String contentType = request.getContentType();
        if (StringUtils.isNotEmpty(contentType) && contentType.contains(MediaType.APPLICATION_JSON_VALUE)) {
            String body = requestWrapper.getBody();
            paramMap = JSONObject.parseObject(body, HashMap.class);
        } else {
            Map<String, String[]> parameterMap = requestWrapper.getParameterMap();
            //普通的GET请求
            if (parameterMap != null && parameterMap.size() > 0) {
                Set<Map.Entry<String, String[]>> entries = parameterMap.entrySet();
                for (Map.Entry<String, String[]> next : entries) {
                    paramMap.put(next.getKey(), next.getValue()[0]);
                }
            } else {
                //GET请求,参数在URL路径型式,比如server/{var1}/{var2}
                /*String afterDecodeUrl = null;
                try {
                    //编码过URL需解码解码还原字符
                    afterDecodeUrl = URLDecoder.decode(request.getRequestURI(), "UTF-8");
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                paramMap.put("pathVar", afterDecodeUrl);*/
            }
        }
        return paramMap;
    }


}
