package com.chinaweal.aiccs.config;


import com.chinaweal.aiccs.common.util.StringUtils;
import com.chinaweal.youfool.framework.springboot.util.SpringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.env.Environment;

import javax.servlet.FilterConfig;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;


@WebFilter(urlPatterns = "/*", filterName = "safetyFilter")
@Slf4j
public class SafetyFilter implements Filter {

    // 伪站点白名单
    private static final List<String> urlRefererList = new ArrayList<>();
    // 微信白名单
    private static final List<String> wxWhitelist = new ArrayList<>();

    private Environment environment = null;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

        wxWhitelist.add("/wx/");
        wxWhitelist.add("/attachment/");
        wxWhitelist.add("/writ/");
        wxWhitelist.add("/tbBatchGsList/queryRevocationByNamePage");
        wxWhitelist.add("/tbBatchGsDetail/queryRevocationGsDetails");
        wxWhitelist.add("/tbBatchGsDetail/queryRevocationGsDetails");
        wxWhitelist.add("/abnormalAndBatch/abnormalYcDetails");
        wxWhitelist.add("/abnormalAndBatch/abnormalLrDetails");
        wxWhitelist.add("/abnormalAndBatch/queryAbnormalByNamePage");
        wxWhitelist.add("/test/again/nstsWrit");
        wxWhitelist.add("/test/again/nscfWrit");
        wxWhitelist.add("/test/push/tf/penalty");
        wxWhitelist.add("/test/FtyTest");
        wxWhitelist.add("/test/hqlcusers");
        wxWhitelist.add("/test/revokeCancel");
        wxWhitelist.add("/user/captchadl");
        wxWhitelist.add("/user/checkSSOLogin");

        urlRefererList.add("http://localhost");
        urlRefererList.add("http://127.0.0.1");
        urlRefererList.add("http://192.168.100");
        urlRefererList.add("http://10.201.62");
        urlRefererList.add("http://10.194.188.237/");
        urlRefererList.add("https://10.194.188.237/");
        urlRefererList.add("http://172.22.80.35/");
        urlRefererList.add("https://172.22.80.35/");
        urlRefererList.add("http://172.22.80.129/");
        urlRefererList.add("http://172.22.80.129:6888/");
        urlRefererList.add("http://10.207.148");
        urlRefererList.add("https://10.207.148");
        urlRefererList.add("https://portal.scjgj.gz.gov.cn/");
        urlRefererList.add("http://10.21.5.138/");
        urlRefererList.add("http://chinaweal.com.cn:8090/");
        urlRefererList.add("http://www.chinaweal.com.cn:1777/");
        urlRefererList.add("https://www.chinaweal.com.cn:1777/");
        urlRefererList.add("https://sjzx.scjgj.gz.gov.cn/");
        urlRefererList.add("http://sjzx.scjgj.gz.gov.cn/");
        urlRefererList.add("https://10.21.5.138/");
        urlRefererList.add("http://10.21.5.138/");

        environment = SpringUtil.getBean(Environment.class);
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        //X-Content-Type-Options响应头缺失
        response.addHeader("X-Content-Type-Options", "nosniff");
        //Content-Security-Policy响应头缺失 临时注释，影响druid监控，需要时在开启 by ymc 2022.8.4
//        response.addHeader("Content-Security-Policy", "object-src 'self'; script-src 'self';");
        //X-Frame-Options未配置
        response.setHeader("x-frame-options", "SAMEORIGIN");
        //发现可高速缓存的 SSL 页面
        response.setHeader("Cache-Control", "no-store");
        //Strict-Transport-Security 头缺失或不安全
        response.setHeader("Strict-Transport-Security", "max-age=63072000; includeSubdomains; preload");

        String requestUri = request.getRequestURI();
        String contextPath = request.getContextPath();
        String url = requestUri.substring(contextPath.length());
        String referer = request.getHeader("Referer");
        if (environment != null && StringUtils.equals(environment.getProperty("spring.profiles.active"), "prod129")) {
            chain.doFilter(request, response);
            return;
        }
        //跨站点伪造防御
        if (referer != null && urlRefererList.stream().noneMatch((s) -> referer.trim().startsWith(s))) {
            response.sendError(HttpServletResponse.SC_FORBIDDEN);
        } else if (wxWhitelist.stream().anyMatch((s) -> url.trim().startsWith(s))) {
            chain.doFilter(request, response);
        } else {
            log.error("非法请求链接，url：{}", url);
            response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
        }

    }

    @Override
    public void destroy() {

    }

    private String getParamString(HttpServletRequest request) {
        String param = null;
        try (BufferedReader streamReader = new BufferedReader(new InputStreamReader(request.getInputStream(), StandardCharsets.UTF_8))){
            StringBuilder responseStrBuilder = new StringBuilder();

            String inputStr;
            while ((inputStr = streamReader.readLine()) != null) {
                responseStrBuilder.append(inputStr);
            }
            if (responseStrBuilder.length() > 0) {
                param = responseStrBuilder.toString();
            }
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return param;
    }

    private String getQueryString(Map<String, String[]> map) {
        if (map.isEmpty()) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<String, String[]> e : map.entrySet()) {
            sb.append(e.getKey()).append(":");
            String[] value = e.getValue();
            if (value != null && value.length == 1) {
                sb.append(value[0]).append(" ");
            } else {
                sb.append(Arrays.toString(value)).append("\t");
            }
        }
        return sb.toString();
    }
}
