package com.ningdatech.pmapi.user.security.auth.password;

import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
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.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;

/**
 * @Author LiuXinXin
 * @Date 2020/8/3 8:55 下午
 * @Version 1.0
 **/
public class UsernamePasswordAuthProvider implements AuthenticationProvider {

    private UserDetailsService userDetailsService;

    private PasswordEncoder passwordEncoder;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        if (!(authentication instanceof UsernamePasswordAuthToken)) {
            throw new RuntimeException("CustomAuthProvider 只支持 CustomAuthToken");
        }
        UsernamePasswordAuthToken authenticationToken = (UsernamePasswordAuthToken) authentication;

        UserDetails user = userDetailsService.loadUserByUsername((String) authenticationToken.getPrincipal());
        if (user == null) {
            throw new InternalAuthenticationServiceException("can not get user info!");
        }
        additionalAuthenticationChecks(user, authenticationToken);
        // 校验用户是否有当前端的登陆权限
        // 将用户定义的user放入token中，这样可以在session中查询到所有自定义的用户信息
        return new UsernamePasswordAuthToken(user, user.getPassword(), user.getAuthorities());
    }

    protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthToken authentication)
            throws AuthenticationException {
        if (authentication.getCredentials() == null) {
            throw new BadCredentialsException("login fail! password is null");
        }
        String presentedPassword = authentication.getCredentials().toString();
        if (!passwordEncoder.matches(presentedPassword, userDetails.getPassword())) {
            throw new BadCredentialsException("login fail! password is error");
        }
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return UsernamePasswordAuthToken.class.isAssignableFrom(authentication);
    }

    public void setUserDetailsService(UserDetailsService userDetailsService) {
        this.userDetailsService = userDetailsService;
    }

    public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
        this.passwordEncoder = passwordEncoder;
    }

}
