自学内容网 自学内容网

SpringSecurity源码分析3--UserDetail部分

前言:本章提及的类都是与用户名、密码相关的类

UserDetailsService.class
用于加载用户信息
在这里插入图片描述

DaoAuthenticationProvider.class
将数据库的信息拿出来进行认证

在这里插入图片描述

AbstractUserDetailsAuthenticationProvider.class
DaoAuthenticationProvider的父类,通过模板模式,真正进行认证的模块,

一个允许子类重写和处理UserDetails对象的基AuthenticationProvider。该类旨在响应UsernamePasswordAuthenticationToken身份验证请求。
在这里插入图片描述

AuthenticationProvider.class

在这里插入图片描述

@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
Assert.isInstanceOf(UsernamePasswordAuthenticationToken.class, authentication,
() -> this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.onlySupports",
"Only UsernamePasswordAuthenticationToken is supported"));
String username = determineUsername(authentication);
boolean cacheWasUsed = true;
UserDetails user = this.userCache.getUserFromCache(username);
if (user == null) {
cacheWasUsed = false;
try {
user = retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication);
}
catch (UsernameNotFoundException ex) {
this.logger.debug("Failed to find user '" + username + "'");
// 抛出一个含糊的异常,提供安全保护机制
if (!this.hideUserNotFoundExceptions) {
throw ex;
}
throw new BadCredentialsException(this.messages
.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
}
Assert.notNull(user, "retrieveUser returned null - a violation of the interface contract");
}
try {
this.preAuthenticationChecks.check(user);
additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken) authentication);
}
catch (AuthenticationException ex) {
if (!cacheWasUsed) {
throw ex;
}
// 可能存在用户数据变更的问题,需要再次尝试获取
// There was a problem, so try again after checking
// we're using latest data (i.e. not from the cache)
cacheWasUsed = false;
user = retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication);
this.preAuthenticationChecks.check(user);
additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken) authentication);
}
this.postAuthenticationChecks.check(user);
if (!cacheWasUsed) {
this.userCache.putUserInCache(user);
}
Object principalToReturn = user;
if (this.forcePrincipalAsString) {
principalToReturn = user.getUsername();
}
return createSuccessAuthentication(principalToReturn, authentication, user);
}

获取用户名
在这里插入图片描述

从缓存中获取UserDetail对象

在这里插入图片描述

private UserCache userCache = new NullUserCache();

在这里插入图片描述
默认都是null,可以通过setUserCache设置Cache

this.preAuthenticationChecks.check(user);

在这里插入图片描述

additionalAuthenticationChecks

在这里插入图片描述

密码校验
在这里插入图片描述

public interface PasswordEncoder {
    String encode(CharSequence rawPassword);

    boolean matches(CharSequence rawPassword, String encodedPassword);

    default boolean upgradeEncoding(String encodedPassword) {
        return false;
    }
}

this.postAuthenticationChecks.check(user);

在这里插入图片描述

createSuccessAuthentication

在这里插入图片描述
权限管理

private GrantedAuthoritiesMapper authoritiesMapper = new NullAuthoritiesMapper();

在这里插入图片描述retrieveUser

  1. 建议直接抛出UsernameNotFoundException
  2. 时间攻击防护

在这里插入图片描述
通过预先编码这个密码,可以确保在后续的时间攻击防护方法中,不会因为实时编码操作而导致时间差异,这些时间差异可能会被攻击者用来推断密码或其他敏感信息。
在这里插入图片描述
在这里插入图片描述
加密方法升级后,重新更新密码
在这里插入图片描述
在这里插入图片描述

UsernamePasswordAuthenticationFilter.class
根据请求中的username

在这里插入图片描述
在这里插入图片描述

AbstractAuthenticationProcessingFilter.class

在这里插入图片描述

private void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws IOException, ServletException {
if (!requiresAuthentication(request, response)) {
chain.doFilter(request, response);
return;
}
try {
Authentication authenticationResult = attemptAuthentication(request, response);
if (authenticationResult == null) {
// return immediately as subclass has indicated that it hasn't completed
return;
}
// 给session策略提供钩子
this.sessionStrategy.onAuthentication(authenticationResult, request, response);
// Authentication success
if (this.continueChainBeforeSuccessfulAuthentication) {
chain.doFilter(request, response);
}
successfulAuthentication(request, response, chain, authenticationResult);
}
catch (InternalAuthenticationServiceException failed) {
this.logger.error("An internal error occurred while trying to authenticate the user.", failed);
unsuccessfulAuthentication(request, response, failed);
}
catch (AuthenticationException ex) {
// Authentication failed
unsuccessfulAuthentication(request, response, ex);
}
}

在这里插入图片描述
在这里插入图片描述

FormLoginConfigurer.class

在这里插入图片描述
在这里插入图片描述
默认页面,生产不会使用
在这里插入图片描述
默认密码来源
在这里插入图片描述
默认加载的类
在这里插入图片描述

SecurityConfigurerAdapter.class

链式调用
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

AbstractAuthenticationFilterConfigurer.class

在这里插入图片描述

@Override
public void configure(B http) throws Exception {
PortMapper portMapper = http.getSharedObject(PortMapper.class);
if (portMapper != null) {
this.authenticationEntryPoint.setPortMapper(portMapper);
}
// 设置请求缓存器
RequestCache requestCache = http.getSharedObject(RequestCache.class);
if (requestCache != null) {
this.defaultSuccessHandler.setRequestCache(requestCache);
}
// 设置处理器
this.authFilter.setAuthenticationManager(http.getSharedObject(AuthenticationManager.class));
this.authFilter.setAuthenticationSuccessHandler(this.successHandler);
this.authFilter.setAuthenticationFailureHandler(this.failureHandler);
if (this.authenticationDetailsSource != null) {
this.authFilter.setAuthenticationDetailsSource(this.authenticationDetailsSource);
}
// 设置Session策略
SessionAuthenticationStrategy sessionAuthenticationStrategy = http
.getSharedObject(SessionAuthenticationStrategy.class);
if (sessionAuthenticationStrategy != null) {
this.authFilter.setSessionAuthenticationStrategy(sessionAuthenticationStrategy);
}
// 记住我
RememberMeServices rememberMeServices = http.getSharedObject(RememberMeServices.class);
if (rememberMeServices != null) {
this.authFilter.setRememberMeServices(rememberMeServices);
}
// 安全上下文
SecurityContextConfigurer securityContextConfigurer = http.getConfigurer(SecurityContextConfigurer.class);
if (securityContextConfigurer != null && securityContextConfigurer.isRequireExplicitSave()) {
// 安全上下文仓库
SecurityContextRepository securityContextRepository = securityContextConfigurer
.getSecurityContextRepository();
this.authFilter.setSecurityContextRepository(securityContextRepository);
}
// 添加过滤器
F filter = postProcess(this.authFilter);
http.addFilter(filter);
}

在这里插入图片描述


原文地址:https://blog.csdn.net/moernagedian/article/details/137767321

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!