package com.cftech.sys.filter;

import com.cftech.core.util.JWTUtils;
import com.cftech.core.util.StringUtils;
import org.apache.cxf.transport.http.Cookies;
import org.springframework.security.access.method.P;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.servlet.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.HashSet;
import java.util.Set;

/**
 * 针对JWT CSRF侵入，进行拦截过滤
 * Created by Jasper Huang on 2018/6/1.
 */
public class JwtSecurityFilter implements Filter {
    private static final String FILTER_APPLIED = JwtSecurityFilter.class.getName() + ".FILTERED";

    private static Set<String> excludePathRegex = new HashSet<String>();
    //不需要被拦截的地址，通过XML进行配置
    public void setExcludePathRegex( Set<String> excludePathRegex ) {
        this.excludePathRegex = excludePathRegex;
    }
    @Override
    public void init( FilterConfig filterConfig ) throws ServletException {}

    /**
     * 移动端拦截器
     * 如果是登录页面则不进行拦截 /mobile/wxjs/oauth 为登录页面
     * 校验两个COOKIE， 一个为authsignature 存JWT信息的COOKIE， 判断memberUid,openId,Time,requestId,以及域名，是否是跨域进行访问了
     * 一个为tokensign, tokensign从前端的参数signature传递过来,signature需要进行BASE64后，查看是否与COOKIE中的内容一致
     * 如果为401 无权限则，刷新前端页面重新获得最新的COOKIE及TOKEN
     * @param request
     * @param response
     * @param chain
     * @throws IOException
     * @throws ServletException
     */
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain ) throws IOException, ServletException {
        HttpServletRequest httpRequest = ( HttpServletRequest )request;
        HttpServletResponse httpResponse = ( HttpServletResponse )response;

        if (httpRequest.getRequestURI().contains("/mobile/auth")) {
            chain.doFilter( request, response );
            return;
        }

        if(httpRequest.getRequestURI().endsWith("/mobile/wxjs/oauth"))
        {
            chain.doFilter( request, response );
            return;
        }

        String uri = httpRequest.getRequestURI();
        for( String regex : excludePathRegex ) {
            if( uri.matches( regex ) ) {
                chain.doFilter( request, response );
                return;
            }
        }

//        String signature = request.getParameter("signature");
        //修改SIGNATURE从COOKIE中获取
        Cookie[] cookies = ((HttpServletRequest) request).getCookies();
        if(cookies==null||cookies.length==0)
        {
            httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
            return;
        }
        boolean jwtSignatureExists = false;
        for (int i = 0; i < cookies.length; i++) {
            Cookie cookie = cookies[i];
            if (cookie.getName().equals("authsignature")) {
                String signature = cookie.getValue();
                if(StringUtils.isNotBlank(signature))
                {
                    jwtSignatureExists = true;
                    signature = URLDecoder.decode( signature,"UTF-8" );
                    int status =  JWTUtils.verifyJWT(signature,httpRequest);
                    if(status==0)
                    {
//                        chain.doFilter( request, response );
//                        return;
                    }else if(status==-1)
                    {
                        httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
                        return;
                    }else
                    {
                        httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN);
                        return;
                    }
                }else
                {
                    httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN);
                    return;
                }
            }
        }
        if(!jwtSignatureExists)
        {
            httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
            return;
        }
        String signatureInfo = request.getParameter("signature");
        if(StringUtils.isBlank(signatureInfo))
        {
            httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
            return;
        }
        String str =   URLEncoder.encode(new BASE64Encoder().encodeBuffer(signatureInfo.getBytes()),"UTF-8" ) ;
        for (int i = 0; i < cookies.length; i++) {
            Cookie cookie = cookies[i];
            if (cookie.getName().equals("tokensign")) {
                String signature = cookie.getValue();
                if(StringUtils.isNotBlank(signature))
                {
                    if(signature.equals(str)){
                        chain.doFilter( request, response );
                        return;
                    }else
                    {
                        httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
                        return;
                    }
                }else
                {
                    httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN);
                    return;
                }
            }
        }
        //前后台校验判断- TOKEN校验
        httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
        return;
//        String uri = httpRequest.getRequestURI();
//        for( String regex : excludePathRegex ) {
//            if( uri.matches( regex ) ) {
//                chain.doFilter( request, response );
//                return;
//            }
//        }
        // Apply Filter
//        if( null != httpRequest.getAttribute( FILTER_APPLIED ) ) {
//            chain.doFilter( request, response );
//            return;
//        }
//        try {
//            request.setAttribute( FILTER_APPLIED, Boolean.TRUE );
//            SecurityRequestWrapper requestWrapper = new SecurityRequestWrapper( httpRequest );
//            chain.doFilter( requestWrapper, response );
//        } finally {
//            httpRequest.removeAttribute( FILTER_APPLIED );
//        }
    }

    @Override
    public void destroy() {}
}
