SpringSecurity身份认证流程

SpringSecurity的身份认证的入口是AuthenticationManger顾名思义,这是Authentication的管理者, Authentication是包含身份信息的超接口, AuthenticationManger负责验证Authentication身份信息,当然,AuthenticationManager也是一个接口,只是对身份验证做了一个规范,具体的验证并不是在这个接口中,而是交给了其实现类,ProviderManager,在ProviderManager类中维护了一个List<AuthenticationProvider> providers, 那么为什么会去维护这个集合呢,因为SpringSecurity的身份认证不仅仅只有一种方式,也就是Authentication的子类不会只有一种,当然最常用的是:UsernamePasswordAuthenticationToken,他是Authentication一个具体实现,这是使用用户名密码的形式认证的。 那么当请求进来的时候, 过滤器会获取到用户名和密码,并封装成UsernamePasswordAuthenticationToken,然后把UsernamePasswordAuthenticationToken交给AuthenticationManager去验证,那么也就是到其子类ProviderManager中认证,ProviderManager会调用其authenticate方法认证,那么在这个方法中, 会去遍历List<AuthenticationProvider>这是集合,找到和Authentication相匹配的AuthenticationProvider,当找到时会调用AuthenticationProvider的authenticate方法认证,AuthenticationProvider也有很多实现,最常用的一个实现就是DaoAuthenticationProvider,顾名思义,就是从数据库中获取用户信息封装的AuthenticationProvider, 然后到了这一步, 数据库中的用户信息拿到了, 前端提交的用户信息也拿到了,就可以做身份比对了。

SpringSecurity 获取用户身份信息从哪获取呢?
SpringSecurity提供了一个获取用户信息的接口,UserDetailsService, 用户可以自己实现这个接口, public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException 具体要是实现的为这个方法, 返回的UserDetails 中,就是用户的信息。 前文说到了验证用户信息是在AuthenticationProvider中, 在AuthenticationProvider的 实现中, 会调用authenticate(Authentication var1) 这个方法认证, 在这个方法中, 会调用 retrieveUser(username, (UsernamePasswordAuthenticationToken)authentication)方法去获取UserDetails, 在这个方法中就是调用UserDetailsService的UserDetails loadUserByUsername(String username)方法获取到了UserDetails , 好了,到这为止, 就从你自己的UserDetailsService实现中获取到了UserDetails,这个UserDetails 就是数据库中或内存中的真实用户数据了, 那么AuthenticationProvider 在authenticate方法中拿到UserDetails后,又会调用` this.additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken)authentication);方法,验证从数据库中获取的用户信息和用户输入的用户信息做对比,如果验证通过, 不会有返回值,验证失败,抛异常。到此, 整个验证流程结束。

流程图: 身份认证流程图