package cn.service.token;

import cn.constant.CommonConst;
import cn.orm.abs.ICommonAPI;
import cn.pojo.vo.LoginUser;
import cn.util.core.IsKit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
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.HttpServletResponse;
import java.io.IOException;

/**
 * 认证拦截器 用于拦截请求提取jwt认证，验证token有效性
 * 在Spring中，Filter默认继承OncePerRequestFilter
 * OncePerRequestFilter过滤器保证一次请求只调用一次doFilterInternal方法;
 * 如内部的forward不会再多执行一次
 * 见：spring-security
 * */
@Component
public class JwtAuthTokenFilter extends OncePerRequestFilter
{
	@Autowired
	private JwtTokenService tokenService;
	@Autowired
	private ICommonAPI sysBaseService;
	
	@Override
	protected void doFilterInternal(HttpServletRequest request, 
			HttpServletResponse response,
			FilterChain chain) throws ServletException, IOException
	{
		String tokenHeader = request.getHeader(CommonConst.TOKEN_HEADER);
		//如果请求头中没有Authorization则直接放行
		if (IsKit.isNullOrEmpty(tokenHeader)) {
			//放行 转入：AuthenticationEntryPointImpl
			chain.doFilter(request, response);
			return;
		}

		// 若是已经经过认证
		if (SecurityContextHolder.getContext().getAuthentication() != null) {
			chain.doFilter(request, response);
			return;
		}

		/**如果请求头中有token，则进行解析，并且设置认证信息*/ 
		//获取登录用户所携带的
		LoginUser loginUser = tokenService.getLoginUser(request);
		if (IsKit.isNotNull(loginUser) && IsKit.isNull(sysBaseService.getAuthentication()))
		{
			//刷新缓存中用户信息
			tokenService.verifyToken(loginUser);
			//三个参数依次为：userDetails, userDetails.getPassword(), userDetails.getAuthorities()
			UsernamePasswordAuthenticationToken authenticationToken = 
					new UsernamePasswordAuthenticationToken(loginUser, null,loginUser.getAuthorities());
			authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
			SecurityContextHolder.getContext().setAuthentication(authenticationToken);
		}
		/**chain.doFilter将请求转发给过滤器链下一个filter , 
		 * 如果没有filter那就是用户请求的资源 
		 */
		chain.doFilter(request, response);
	}
}
