Spring Security(maven项目) 3.0.3.1版本 - 动态JDBC认证
前言:
通过实践而发现真理,又通过实践而证实真理和发展真理。从感性认识而能动地发展到理性认识,又从理性认识而能动地指导革命实践,改造主观世界和客观世界。实践、认识、再实践、再认识,这种形式,循环往复以至无穷,而实践和认识之每一循环的内容,都比较地进到了高一级的程度。
目标:完成动态JDBC认证
正片:
静态JDBC认证是指:手动输入实参
动态JDBC认证理念:获取用户输入的账号名,自动完成查询功能,简单来说,修改了实参的来源
如何完成动态JDBC认证,就是如何修改实参的来源
没错,又回到了UserDetailsService这一篇,两次修改路线差不多都是因为它,为什么呢?,首先它的示例看不懂,其次描述十分奇怪
随着内存认证和JDBC认证的实践,达到窥一斑而知全豹的境界
首先看到示例代码和示例代码的描述
例如,假设 CustomUserDetailsService
实现了 UserDetailsService
,那么下面的列表将自定义认证
@Bean
CustomUserDetailsService customUserDetailsService() {
return new CustomUserDetailsService();
}
觉他的迷糊是因为,它将细节隐藏在这个CustomUserDetailsService
类里面,如何验证这一推断呢?
Bean class= "路径",并且这个类实现了UserDetailsService接口
我们模仿一下
1:新建类
2:实现UserDetailsService
3:重写方法
在Security Java配置类中,将其类注册为bean
根据理论:既然它实现了JDBC认证和内存认证,也就意味着,它具有核心功能,在之前的配置对比中,我们发现有内存认证的没有生成的安全密码
我们注册模板它写出一个类似的,并注册为bean,是否有生成密码
很显然,没有
即没有账号,也没有密码,这段简单的代码完成了自定义配置的功能,但我们该如何具体的自定义配置,需要进行代码的对比,利用在内存认证中它的作用是什么,既然要知道它在内存认证中起到什么作用,就要去看它的源码
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
UserDetails user = (UserDetails)this.users.get(username.toLowerCase(Locale.ROOT));
if (user == null) {
throw new UsernameNotFoundException(username);
} else {
return (UserDetails)(user instanceof CredentialsContainer ? user : new User(
user.getUsername(),
user.getPassword(),
user.isEnabled(),
user.isAccountNonExpired(),
user.isCredentialsNonExpired(),
user.isAccountNonLocked(),
user.getAuthorities()));
}
}
内存认证
形参:一个字符串 username
第一段代码:this.users.get(username.toLowerCase(Locale.ROOT))
内存认证的核心,从这句代码中读取了存放在内存中的账号信息,并强制转换成了UserDetails
最后封装成一个user,以便使用
第二段代码:if(user == null)判断user是否为空,如果为空抛出异常
第三段代码:user不为空,进行以下内容
首先判断 user 是否是CredentialsContainer的实现
很显然在这段代码中,大部分情况都是否
否的话就会New 一个user对线,并将账号等信息填入,最后强转换成UserDetail
将这段代码可视化
结构很简单
第一个问题:username的来源
第二个问题:能否直接new一个user完成自定义认证
根据实践,username的来源多半的登录页面的username输入框
我们选择打上一个端点,去验证
打上断点,点击测试
username的参数应为啊实打实大苏打
很显然,第一个问题的答案我们知道了,username哪里来的
第二个问题,能否直接new一个user,然强转换为userDetails
user两个有参构造函数,我们想不出这么参数怎么办?还记得基础配置吗?
@Bean
public UserDetailsService userDetailsService() {
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
manager.createUser(
User.
withDefaultPasswordEncoder().
username("user").
password("password").
roles("USER").build());
return manager;
}
我们不new一个对象,而是直接使用静态方法完成构建
测试
完美登录成功!!!!
基础配置,到JDBC配置多了一个什么?查询数据库的步骤
完美登录成功!
动态JDBC认证,完成
总结模板:
第一步:创建一个用于实现UserDetailsService的类
第二步:重写方法
第三步:调用查询数据库方法
第四步:返回User
第五步:在配置模板中将上述的类注册为bean