UserDetailService接口:自定义逻辑控制认证
如果需自定义逻辑控制认证
创建类继承UsernamePasswordAuthenticationFilter,并重写
attemptAuthentication ,successfulAuthentication,unsuccessfulAuthentication方法
创建类实现UserDetailsService,编写查询数据过程,返回UserDetails对象,这个UserDetails对象时安全框架提供的对象
PasswordEncoder
用于返回的User对象里面密码的加密,sercuity中只认此加密方式。
!!以上是看了教学视频中大致仅仅粗略讲解的内容,但是为什么实现UserDetailService接口?为什么要继承UsernamePasswordAuthenticationFilter重写attemptAuthentication ,successfulAuthentication,unsuccessfulAuthentication方法呢?看看源码
上一篇说到在UsernamePasswordAuthenticationFilter的父类中AbstractAuthenticationProcessingFilter的dofilter方法中有这样的一段方法
在attemptAuthentication方法中如果抛出异常,那么会执行unsuccessfulAuthentication方法,成功则执行successfulAuthentication方法。因此需要重写attemptAuthentication去进行验证,并重新successfulAuthentication与unsuccessfulAuthentication方法自定义成功与失败的操作。
那么为什么需要继承UserDetailService接口?
attemptAuthentication方法中有这样一段代码
首先会封装用户名与密码到token对象中,
而this.getAuthenticationManager().authenticate(authRequest);是认证的核心方法
cirlt shift +h查看方法的实现
ProviderManager的authenticate方法中
getProviders()获取各种认证的方式并遍历,并通过
result = provider.authenticate(authentication);
去进行认证。
cirlt shift +h
AbstractUserDetailsAuthenticationProvider的authenticate方法中
会获取到UserDetail对象,由于类中的userCache为NullUserCache对象
因此getUserFromCache方法返回值null,user需从
retrieveUser(username,
(UsernamePasswordAuthenticationToken) authentication);
方法获取。
retrieveUser由AbstractUserDetailsAuthenticationProvider的子类DaoAuthenticationProvider进行重写。
这里我们可以看到userdetail是通过调用UserDetailsService去进获取的。
因此我们如果需要自定义认证过程,那么就需要实现该接口。