package com.enterprise.manage.core.secure.process;

import cn.shuibo.config.SecretKeyConfig;
import cn.shuibo.util.Base64Util;
import cn.shuibo.util.RSAUtil;
import com.enterprise.manage.modules.system.domain.po.User;
import com.enterprise.manage.modules.system.mapper.UserMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;

import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;

/**
 * 自定义密码校验
 *
 * @author PeiZhi Guo
 * 2022-7-4 16:35
 */
public class AuthenticationProvider extends DaoAuthenticationProvider {

    @Resource
    private PasswordEncoder passwordEncoder;

    @Resource
    private SecretKeyConfig secretKeyConfig;

    @Resource
    private UserMapper userMapper;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        this.hideUserNotFoundExceptions = false;
        return super.authenticate(authentication);
    }

    @Override
    protected void additionalAuthenticationChecks(UserDetails userDetails,
            UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
        User user = (User) userDetails;
        if (authentication.getCredentials() == null) {
            this.logger.info(">>>>>>>>>>>> 登录失败，凭证错误：" + user.getUsername());
            throw new BadCredentialsException(this.messages
                    .getMessage("AuthenticationProvider.badCredentials", "登录失败，凭证错误"));
        }
        String presentedPassword = authentication.getCredentials().toString();
        //解密登陆密码
        presentedPassword = decrypt(presentedPassword);
        if (!this.passwordEncoder.matches(presentedPassword, userDetails.getPassword())) {
            this.logger.info(">>>>>>>>>>>> 登录失败，密码匹配错误，登录账号：" + user.getUsername());
            if (user.getLoginFailureNum() >= 4) {
                userMapper.lockUser(user.getUsername());
                throw new BadCredentialsException(this.messages
                        .getMessage("AuthenticationProvider.badCredentials",
                                "密码错误，账户已锁定（10分钟后解锁）。"));
            } else {
                userMapper.updateLoginInfo(user.getUsername(), user.getLoginFailureNum() + 1);
                throw new BadCredentialsException(this.messages
                        .getMessage("AuthenticationProvider.badCredentials",
                                "密码错误，请重新输入。密码错误超过5次系统将自动锁定（剩余"+ (4 - user.getLoginFailureNum()) + "次）。"));
            }
        }
        // 密码校对成功，清除次数，记录最后登录时间
        userMapper.updateLoginInfo(user.getUsername(), 0);
    }

    private String decrypt(String password) {
        StringBuilder json = new StringBuilder();
        try {
            if (!StringUtils.isEmpty(password)) {
                String[] contents = password.split("\\|");
                for (String value : contents) {
                    value = new String(RSAUtil.decrypt(Base64Util.decode(value),
                            secretKeyConfig.getPrivateKey()), StandardCharsets.UTF_8);
                    json.append(value);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return json.toString().replace("\"","");
    }
}
