Spring Acegi框架鉴权的实现 (2)

本文深入解析了一个典型的应用程序用户认证流程,包括从用户输入验证、账户状态检查到最终的认证成功处理全过程。此外,还详细介绍了如何从数据库加载用户信息的具体实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

代码
  1. public Authentication authenticate(Authentication authentication)   
  2.     throws AuthenticationException {   
  3.      Assert.isInstanceOf(UsernamePasswordAuthenticationToken.class, authentication,   
  4.          messages.getMessage("AbstractUserDetailsAuthenticationProvider.onlySupports",   
  5.             "Only UsernamePasswordAuthenticationToken is supported"));   
  6.   
  7.     // 这里取得用户输入的用户名   
  8.      String username = (authentication.getPrincipal() == null) ? "NONE_PROVIDED" : authentication.getName();   
  9.     // 如果配置了缓存,从缓存中去取以前存入的用户验证信息 - 这里是UserDetail,是服务器端存在数据库里的用户信息,这样就不用每次都去数据库中取了   
  10.     boolean cacheWasUsed = true;   
  11.      UserDetails user = this.userCache.getUserFromCache(username);   
  12.     //没有取到,设置标志位,下面会把这次取到的服务器端用户信息存入缓存中去   
  13.     if (user == null) {   
  14.          cacheWasUsed = false;   
  15.   
  16.         try {//这里是调用UserDetailService去取用户数据库里信息的地方   
  17.              user = retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication);   
  18.          } catch (UsernameNotFoundException notFound) {   
  19.             if (hideUserNotFoundExceptions) {   
  20.                 throw new BadCredentialsException(messages.getMessage(   
  21.                         "AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));   
  22.              } else {   
  23.                 throw notFound;   
  24.              }   
  25.          }   
  26.   
  27.          Assert.notNull(user, "retrieveUser returned null - a violation of the interface contract");   
  28.      }   
  29.   
  30.     if (!user.isAccountNonLocked()) {   
  31.         throw new LockedException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.locked",   
  32.                 "User account is locked"));   
  33.      }   
  34.   
  35.     if (!user.isEnabled()) {   
  36.         throw new DisabledException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.disabled",   
  37.                 "User is disabled"));   
  38.      }   
  39.   
  40.     if (!user.isAccountNonExpired()) {   
  41.         throw new AccountExpiredException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.expired",   
  42.                 "User account has expired"));   
  43.      }   
  44.   
  45.     // This check must come here, as we don't want to tell users   
  46.     // about account status unless they presented the correct credentials   
  47.     try {//这里是验证过程,在retrieveUser中从数据库中得到用户的信息,在additionalAuthenticationChecks中进行对比用户输入和服务器端的用户信息   
  48.           //如果验证通过,那么构造一个Authentication对象来让以后的授权使用,如果验证不通过,直接抛出异常结束鉴权过程   
  49.          additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken) authentication);   
  50.      } catch (AuthenticationException exception) {   
  51.         if (cacheWasUsed) {   
  52.             // There was a problem, so try again after checking   
  53.             // we're using latest data (ie not from the cache)   
  54.              cacheWasUsed = false;   
  55.              user = retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication);   
  56.              additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken) authentication);   
  57.          } else {   
  58.             throw exception;   
  59.          }   
  60.      }   
  61.   
  62.     if (!user.isCredentialsNonExpired()) {   
  63.         throw new CredentialsExpiredException(messages.getMessage(   
  64.                 "AbstractUserDetailsAuthenticationProvider.credentialsExpired", "User credentials have expired"));   
  65.      }   
  66.     //根据前面的缓存结果决定是不是要把当前的用户信息存入缓存以供下次验证使用   
  67.     if (!cacheWasUsed) {   
  68.         this.userCache.putUserInCache(user);   
  69.      }   
  70.   
  71.      Object principalToReturn = user;   
  72.   
  73.     if (forcePrincipalAsString) {   
  74.          principalToReturn = user.getUsername();   
  75.      }   
  76.     //最后返回Authentication记录了验证结果供以后的授权使用   
  77.     return createSuccessAuthentication(principalToReturn, authentication, user);   
  78. }   
  79. //这是是调用UserDetailService去加载服务器端用户信息的地方,从什么地方加载要看设置,这里我们假设由JdbcDaoImp来从数据中进行加载   
  80. protected final UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication)   
  81.     throws AuthenticationException {   
  82.      UserDetails loadedUser;   
  83.     //这里调用UserDetailService去从数据库中加载用户验证信息,同时返回从数据库中返回的信息,这些信息放到了UserDetails对象中去了   
  84.     try {   
  85.          loadedUser = this.getUserDetailsService().loadUserByUsername(username);   
  86.      } catch (DataAccessException repositoryProblem) {   
  87.         throw new AuthenticationServiceException(repositoryProblem.getMessage(), repositoryProblem);   
  88.      }   
  89.   
  90.     if (loadedUser == null) {   
  91.         throw new AuthenticationServiceException(   
  92.             "UserDetailsService returned null, which is an interface contract violation");   
  93.      }   
  94.     return loadedUser;   
  95. }   

下面我们重点分析一下JdbcDaoImp这个类来看看具体是怎样从数据库中得到用户信息的:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值