若依登录流程

1.第一步

// 用户验证
Authentication authentication = null;
try
{
    // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
    authentication = authenticationManager
            .authenticate(new UsernamePasswordAuthenticationToken(username, password));
}

2.第二步  UsernamePasswordAuthenticationToken.java

public UsernamePasswordAuthenticationToken(Object principal, Object credentials) {
    super((Collection)null);
    this.principal = principal;
    this.credentials = credentials;
    this.setAuthenticated(false);
}

3.第三步  WebSecurityConfigurerAdapter.java

public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    if (this.delegate != null) {
        return this.delegate.authenticate(authentication);
    } else {
        synchronized(this.delegateMonitor) {
            if (this.delegate == null) {
                this.delegate = (AuthenticationManager)this.delegateBuilder.getObject();
                this.delegateBuilder = null;
            }
        }

        return this.delegate.authenticate(authentication);
    }
}

4.第四步  ProviderManager.java

public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    Class<? extends Authentication> toTest = authentication.getClass();
    AuthenticationException lastException = null;
    AuthenticationException parentException = null;
    Authentication result = null;
    Authentication parentResult = null;
    boolean debug = logger.isDebugEnabled();
    Iterator var8 = this.getProviders().iterator();

    while(var8.hasNext()) {
        AuthenticationProvider provider = (AuthenticationProvider)var8.next();
        if (provider.supports(toTest)) {
            if (debug) {
                logger.debug("Authentication attempt using " + provider.getClass().getName());
            }

            try {
                result = provider.authenticate(authentication);
                if (result != null) {
                    this.copyDetails(authentication, result);
                    break;
                }
            } catch (InternalAuthenticationServiceException | AccountStatusException var13) {
                this.prepareException(var13, authentication);
                throw var13;
            } catch (AuthenticationException var14) {
                lastException = var14;
            }
        }
    }

    if (result == null && this.parent != null) {
        try {
            result = parentResult = this.parent.authenticate(authentication);
        } catch (ProviderNotFoundException var11) {
        } catch (AuthenticationException var12) {
            parentException = var12;
            lastException = var12;
        }
    }

    if (result != null) {
        if (this.eraseCredentialsAfterAuthentication && result instanceof CredentialsContainer) {
            ((CredentialsContainer)result).eraseCredentials();
        }

        if (parentResult == null) {
            this.eventPublisher.publishAuthenticationSuccess(result);
        }

        return result;
    } else {
        if (lastException == null) {
            lastException = new ProviderNotFoundException(this.messages.getMessage("ProviderManager.providerNotFound", new Object[]{toTest.getName()}, "No AuthenticationProvider found for {0}"));
        }

        if (parentException == null) {
            this.prepareException((AuthenticationException)lastException, authentication);
        }

        throw lastException;
    }
}

5.第五步   

AbstractUserDetailsAuthenticationProvider.java
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    Assert.isInstanceOf(UsernamePasswordAuthenticationToken.class, authentication, () -> {
        return this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.onlySupports", "Only UsernamePasswordAuthenticationToken is supported");
    });
    String username = authentication.getPrincipal() == null ? "NONE_PROVIDED" : authentication.getName();
    boolean cacheWasUsed = true;
    UserDetails user = this.userCache.getUserFromCache(username);
    if (user == null) {
        cacheWasUsed = false;

        try {
            user = this.retrieveUser(username, (UsernamePasswordAuthenticationToken)authentication);
        } catch (UsernameNotFoundException var6) {
            this.logger.debug("User '" + username + "' not found");
            if (this.hideUserNotFoundExceptions) {
                throw new BadCredentialsException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
            }

            throw var6;
        }

        Assert.notNull(user, "retrieveUser returned null - a violation of the interface contract");
    }

    try {
        this.preAuthenticationChecks.check(user);
        this.additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken)authentication);
    } catch (AuthenticationException var7) {
        if (!cacheWasUsed) {
            throw var7;
        }

        cacheWasUsed = false;
        user = this.retrieveUser(username, (UsernamePasswordAuthenticationToken)authentication);
        this.preAuthenticationChecks.check(user);
        this.additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken)authentication);
    }

    this.postAuthenticationChecks.check(user);
    if (!cacheWasUsed) {
        this.userCache.putUserInCache(user);
    }

    Object principalToReturn = user;
    if (this.forcePrincipalAsString) {
        principalToReturn = user.getUsername();
    }

    return this.createSuccessAuthentication(principalToReturn, authentication, user);
}

6.第六步

DaoAuthenticationProvider.java
protected final UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
    this.prepareTimingAttackProtection();

    try {
        UserDetails loadedUser = this.getUserDetailsService().loadUserByUsername(username);
        if (loadedUser == null) {
            throw new InternalAuthenticationServiceException("UserDetailsService returned null, which is an interface contract violation");
        } else {
            return loadedUser;
        }
    } catch (UsernameNotFoundException var4) {
        this.mitigateAgainstTimingAttack(authentication);
        throw var4;
    } catch (InternalAuthenticationServiceException var5) {
        throw var5;
    } catch (Exception var6) {
        throw new InternalAuthenticationServiceException(var6.getMessage(), var6);
    }
}

protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
    if (authentication.getCredentials() == null) {
        this.logger.debug("Authentication failed: no credentials provided");
        throw new BadCredentialsException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
    } else {
        String presentedPassword = authentication.getCredentials().toString();
        if (!this.passwordEncoder.matches(presentedPassword, userDetails.getPassword())) {
            this.logger.debug("Authentication failed: password does not match stored value");
            throw new BadCredentialsException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
        }
    }
}

7.第七步  

BCryptPasswordEncoder.java
public boolean matches(CharSequence rawPassword, String encodedPassword) {
    if (rawPassword == null) {
        throw new IllegalArgumentException("rawPassword cannot be null");
    } else if (encodedPassword != null && encodedPassword.length() != 0) {
        if (!this.BCRYPT_PATTERN.matcher(encodedPassword).matches()) {
            this.logger.warn("Encoded password does not look like BCrypt");
            return false;
        } else {
            return BCrypt.checkpw(rawPassword.toString(), encodedPassword);
        }
    } else {
        this.logger.warn("Empty encoded password");
        return false;
    }
}

8.第八步   

BCrypt.java
public static boolean checkpw(String plaintext, String hashed) {
    return equalsNoEarlyReturn(hashed, hashpw(plaintext, hashed));
}

public static String hashpw(String password, String salt) {
    byte[] passwordb = password.getBytes(StandardCharsets.UTF_8);
    return hashpw(passwordb, salt);
}

public static String hashpw(byte[] passwordb, String salt) {
    char minor = 0;
    StringBuilder rs = new StringBuilder();
    if (salt == null) {
        throw new IllegalArgumentException("salt cannot be null");
    } else {
        int saltLength = salt.length();
        if (saltLength < 28) {
            throw new IllegalArgumentException("Invalid salt");
        } else if (salt.charAt(0) == '$' && salt.charAt(1) == '2') {
            byte off;
            if (salt.charAt(2) == '$') {
                off = 3;
            } else {
                minor = salt.charAt(2);
                if (minor != 'a' && minor != 'x' && minor != 'y' && minor != 'b' || salt.charAt(3) != '$') {
                    throw new IllegalArgumentException("Invalid salt revision");
                }

                off = 4;
            }

            if (salt.charAt(off + 2) > '$') {
                throw new IllegalArgumentException("Missing salt rounds");
            } else if (off == 4 && saltLength < 29) {
                throw new IllegalArgumentException("Invalid salt");
            } else {
                int rounds = Integer.parseInt(salt.substring(off, off + 2));
                String real_salt = salt.substring(off + 3, off + 25);
                byte[] saltb = decode_base64(real_salt, 16);
                if (minor >= 'a') {
                    passwordb = Arrays.copyOf(passwordb, passwordb.length + 1);
                }

                BCrypt B = new BCrypt();
                byte[] hashed = B.crypt_raw(passwordb, saltb, rounds, minor == 'x', minor == 'a' ? 65536 : 0);
                rs.append("$2");
                if (minor >= 'a') {
                    rs.append(minor);
                }

                rs.append("$");
                if (rounds < 10) {
                    rs.append("0");
                }

                rs.append(rounds);
                rs.append("$");
                encode_base64(saltb, saltb.length, rs);
                encode_base64(hashed, bf_crypt_ciphertext.length * 4 - 1, rs);
                return rs.toString();
            }
        } else {
            throw new IllegalArgumentException("Invalid salt version");
        }
    }
}

static boolean equalsNoEarlyReturn(String a, String b) {
    return MessageDigest.isEqual(a.getBytes(StandardCharsets.UTF_8), b.getBytes(StandardCharsets.UTF_8));
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值