摘要:本文主要通过研究 JHipster 默认的登陆授权机制,学习 Spring-Security 基础知识。通过注解配置基于 DAO 的验证方法。
参考链接
由于 Spring 支持配置的方法非常灵活,所有同一个功能会有各种各样的配置方法,所以在网上搜索资料的时候,需要灵活的理解不同配置方法。
首先列出相关的参考文档和知识点:
Spring Security 官网文档:
6.9 Authentication:UserDetailsService : 这是其中的一种授权方法,比较灵活,只需要提供一个 UserDetailsService 接口的实现,然后进行相应的配置,该节只是简单的介绍,并没有详细其实现和配置方法。
8.2 UserDetailsService Implementation :这一小节详细的介绍了其实现和配置方法,从原理上分析,推荐阅读
Spring Security: Authentication with a Database-backed UserDetailsService :比较精准扼要的介绍使用方法,实用,并且提供了另种配置方法。但是注解配置和 JHipster 不太一样。
验证概述

上图是一张高度概括的 Spring Security Authentication 的架构,我们这里根据 JHipster 的实现具体的介绍一下。
以下简要介绍一下配置和实际验证的调用流程
- 授权 API 入口
UserJWTController的authorize方法,该方法关于授权只用了两行代码 - 根据用户输入的
credential创建UsernamePasswordAuthenticationToken - 使用
AuthenticationManager的抽象方法authenticate(authenticationToken)授权。 - 抽象方法
authenticate的实际调用是ProviderManager的实现方法,这个方法中,我们可以看到里面维护了一个AuthenticationProvider列表,然后依次使用每个provider进行验证操作。 AuthenticationProvider有一个抽象类实现AbstractUserDetailsAuthenticationProvider,进而有一个DaoAuthenticationProvider非抽象实现类DaoAuthenticationProvider中有一个成员变量就是UserDetailService- 具体这个成员变量如何在
authenticate方法中使用,需要追溯到抽象类的authenticate的重载,UserDetails user = retrieveUser(username,(UsernamePasswordAuthenticationToken) authentication);,实现类通过重载这个方法,来定义不同的获取UserDetails的方法,获取了这个 user,就可以进行验证了,additionalAuthenticationChecks(user,(UsernamePasswordAuthenticationToken) authentication);,这里还有 pre 和 post 验证的触发。 - 我们再回到
DaoAuthenticationProvider类中,对retrieveUser的重载,关键就是调用了UserDetailsService的loadUserByUsername方法获取的UserDetails。UserDetails loadedUser = this.getUserDetailsService().loadUserByUsername(username);所以我们自己写的代码就是实现接口UserDetailsService然后实现loadUserByUsername方法 - 所以 JHipster 中有一个使用
@Component注入的实现:DomainUserDetailsService,来完成这个任务。 - 另外,我们在配置类
SecurityConfiguration中,通过Intellij可以智能的看到其构造方法的注入,就可以定位到这个实现。
