package cc.smtweb.framework.core.mvc.filter;

import cc.smtweb.framework.core.common.R;
import cc.smtweb.framework.core.exception.ExceptionMessage;
import cc.smtweb.framework.core.util.JsonUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * @Author yaoq
 * @Date 2022年07月20日 9:28
 * @Description
 */
@Slf4j
@Component
public class HttpSecurityFilter extends OncePerRequestFilter {

    @Autowired
    private HttpSecurityConfig httpConfig;

    @Autowired
    private XssSecurityConfig xssConfig;

    @Override
    public void afterPropertiesSet() throws ServletException {

    }

    @Override
    public void initFilterBean() throws ServletException {
        log.info("HttpSecurityFilter init begin ");
        log.info("XssSecurityRegex:" + xssConfig.getRegexStr());
        log.info("HttpSecurityRegex:" + httpConfig.toString());
        log.info("HttpSecurityFilter init end ");
    }

    /**
     * 销毁操作
     */
    public void destroy() {
        System.out.println("HttpSecurityFilter destroy");
    }


    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        //httpResponse 响应头
        if (httpConfig.getConfigs() != null && httpConfig.getConfigs().size() > 0) {
            httpConfig.getConfigs().forEach(response::setHeader);
        }
        //Xss 校验
        XssHttpRequestWrapper xssRequest = new XssHttpRequestWrapper(request, xssConfig);
        // 对request信息进行封装并进行校验工作，若校验失败（含非法字符），根据配置信息进行日志记录和请求中断处理
        if (xssRequest.validateParameter(response)) {
            log.error("XSS校验：请求参数存在XSS攻击行为！");
            if (xssConfig.isLogIs()) {
                // 记录攻击访问日志
                // 可使用数据库、日志、文件等方式
            }
            if (xssConfig.isChain()) {
                R r = R.error("很抱歉，您提交的信息中含有非法信息，可能会对系统安全带来影响，您的请求被阻断！");
                if (request.getMethod().equals("GET")) {
                    r = R.error(ExceptionMessage.NOT_ALLOWED_ERROR.getCode(), ExceptionMessage.NOT_ALLOWED_ERROR.getMsg());
                }
                writeResponseJson(response, JsonUtil.encodeString(r));
                return;
            }
        }
        filterChain.doFilter(xssRequest, response);
    }

    public void writeResponseJson(HttpServletResponse response, String ret) {
        response.setHeader("Pragma", "No-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0L);
        response.setContentType("application/json;charset=UTF-8");
        PrintWriter writer = null;
        try {
            writer = response.getWriter();
            writer.write(ret);
            writer.flush();
        } catch (Exception e) {
            log.error("response error", e);
        } finally {
            if (writer != null) {
                writer.close();
            }
        }
    }


    class GetRequest extends HttpServletRequestWrapper {

        public GetRequest(HttpServletRequest request) {
            super(request);
        }

        @Override
        public String getMethod() {
            return "GET";
        }
    }
}
