package com.dcit.authority.shiro.filter;

import java.util.Map;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.AccessControlFilter;
import org.apache.shiro.web.util.WebUtils;

import com.alibaba.fastjson.JSON;
import com.dcit.authority.dto.form.LoginForm;
import com.dcit.authority.shiro.token.PasswordToken;
import com.dcit.authority.utils.RequestResponseUtil;
import com.dcit.common.enums.ResultEnum;
import com.dcit.common.utils.ResultVOUtil;
import com.dcit.logging.util.IpUtil;

import lombok.extern.slf4j.Slf4j;

/**
 * Title: PasswordFilter
 * Description: 基于 用户名密码 的认证过滤器
 * Company: SJZ DC-IT co. LTD
 * 
 * @author ZZZ
 * @date 2018年9月6日 下午8:41:45
 */
@Slf4j
public class PasswordFilter extends AccessControlFilter {

    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {

        Subject subject = getSubject(request,response);
        // 如果其已经登录，再此发送登录请求
        //  拒绝，统一交给 onAccessDenied 处理
        return null != subject && subject.isAuthenticated();
    }

    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) {

    	// 判断是否是登录请求
		if (isPasswordLoginPost(request)) {

			AuthenticationToken authenticationToken = null;
			
			try {
				authenticationToken = createPasswordToken(request);

				Subject subject = getSubject(request, response);
				
				subject.login(authenticationToken);
				// 登录认证成功,进入请求派发json web token url资源内
				
				return true;
				
			} catch (AuthenticationException e) {
				log.error("{}::{}", authenticationToken.getPrincipal(), e.getMessage());
				// 返回response告诉客户端认证失败
				RequestResponseUtil.responseWrite(JSON.toJSONString(ResultVOUtil.error(ResultEnum.ACCOUNT_PWD_ERROR)),
						response);
				return false;
			} catch (Exception e) {
				log.error("{}::认证异常::{}", authenticationToken.getPrincipal(), e.getMessage());
				// 返回response告诉客户端认证失败
				RequestResponseUtil.responseWrite(JSON.toJSONString(ResultVOUtil.error(ResultEnum.ACCOUNT_PWD_ERROR)),
						response);
				return false;
			}
		}

		log.error("===无效的登录请求====");
		// response 告知无效请求
		RequestResponseUtil.responseWrite(JSON.toJSONString(ResultVOUtil.error(ResultEnum.ACCOUNT_PWD_EMPTY)), response);

		return false;
        
    }

    private boolean isPasswordLoginPost(ServletRequest request) {

        Map<String ,String> map = RequestResponseUtil.getRequestBodyMap(request);
        String password = map.get("password");
        String account = map.get("account");
        
        return (request instanceof HttpServletRequest)
                && "POST".equals(((HttpServletRequest)request).getMethod().toUpperCase())
                && null != password
                && null != account;
    }


    private AuthenticationToken createPasswordToken(ServletRequest request) throws Exception {

    	LoginForm loginForm = JSON.parseObject(JSON.toJSONString(RequestResponseUtil.getRequestBodyMap(request)),LoginForm.class);
        String host = IpUtil.getIpFromRequest(WebUtils.toHttp(request));
        if(null == loginForm){
        	return null;
        }
        return new PasswordToken(loginForm.getAccount(),loginForm.getPassword(),loginForm.getTimestamp(),host);
    }

}
