package com.tykj.workflowcore.user.authencation.provider;

import com.tykj.workflowcore.user.authencation.checks.DefaultPreAuthenticationChecks;
import com.tykj.workflowcore.user.authencation.token.JwtAuthencationToken;
import com.tykj.workflowcore.user.pojo.User;
import com.tykj.workflowcore.user.service.CenterUserService;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsChecker;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

/**
 * 自定义SpringSecurity的用户处理类类
 * 当用户通过统一登录平台访问本系统时由该类进行用户验证
 *
 * @author HuangXiahao
 * @version V1.0
 * @class JWTAuthenticationProvider
 * @packageName com.example.personnelmanager.common.SpringSecurityProvider
 * @data 2020/6/13
 **/
@Component
public class JwtAuthenticationProvider implements AuthenticationProvider {

    private final CenterUserService userDetailsService;

    /**
     * 用户可用性检查类
     */
    private final UserDetailsChecker preAuthenticationChecks = new DefaultPreAuthenticationChecks();

    public JwtAuthenticationProvider(CenterUserService centerUserService) {
        this.userDetailsService = centerUserService;
    }

    /***
     * 验证用户
     *
     * @param authentication
     * @Return : org.springframework.security.core.Authentication
    */
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        Assert.isInstanceOf(JwtAuthencationToken.class, authentication,
                "错误的凭证");
        String username = (authentication.getPrincipal() == null) ? "NONE_PROVIDED"
                : ((User)authentication.getPrincipal()).getUsername();
        UserDetails user = retrieveUser(username);
        preAuthenticationChecks.check(user);
        return createSuccessAuthentication(user,authentication,user);
    }

    /***
     * 返回True则由该对象进行用户验证
     *
     * @param authentication
     * @Return : boolean
    */
    @Override
    public boolean supports(Class<?> authentication) {
        return (JwtAuthencationToken.class.isAssignableFrom(authentication));
    }

    /***
     * 通过用户名获取对应的用户
     *
     * @param username
     * @Return : org.springframework.security.core.userdetails.UserDetails
    */
    protected final UserDetails retrieveUser(String username) {
        UserDetails loadedUser = userDetailsService.selectByUserName(username);
        if (loadedUser == null) {
            throw new InternalAuthenticationServiceException(
                    "UserDetailsService returned null, which is an interface contract violation");
        }
        return loadedUser;
    }

    /***
     * 创建一个已经通过验证的用户实例
     * 该方法由SpringSecurity源码魔改得到
     * @param principal
     * @param authentication
     * @param user
     * @Return : org.springframework.security.core.Authentication
     */
    protected Authentication createSuccessAuthentication(Object principal,
                                                         Authentication authentication, UserDetails user) {
        JwtAuthencationToken result = new JwtAuthencationToken(principal,
                user.getAuthorities());
        result.setDetails(authentication.getDetails());
        return result;
    }

}
