我有:
@Service
public class MyAppUserDetailsService implements UserDetailsService {
@Autowired
private IUserInfoDAO userInfoDAO;
@Override
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
User activeUserInfo = userInfoDAO.getActiveUser(userName);
GrantedAuthority authority = new SimpleGrantedAuthority(activeUserInfo.getRole());
String userNameVal = activeUserInfo.getUserName();
String userSurnameVal = activeUserInfo.getPassword();
UserDetails userDetails = new org.springframework.security.core.userdetails.User(userNameVal, userSurnameVal, Arrays.asList(authority));
return userDetails;
}
}
和
在我配置的安全链中:
.and().formLogin() //login configuration
.loginPage("/app/login")
.loginProcessingUrl("/app-login")
.usernameParameter("app_username")
.passwordParameter("app_password")
.defaultSuccessUrl("/app/secure/projects-details")
如何将表单中的用户密码填写与loadUserByUsername方法中设置的UserDetails进行比较?
答案 0 :(得分:1)
一旦告诉Spring安全配置您将使用特定的UserDetailsService
或只有一个@Service
bean是该接口的实现,那么Spring开始使用它从您的用户名中获取用户持久存储。让我们简化流程:
用户提交一个表单,其中存在名称为app_username
和app_password
的字段(在Web安全配置中配置)到loginPage(String)
路径
表单提交被Spring Security的过滤链拦截,Spring意识到用户名位于字段app_username
中,密码在app_password
现在已激活已配置的UserDetailsService
bean,调用其loadUserByUsername(String)
方法并传递app_username
字段的值(例如john_smith
)
由于loadUserByUsername(String)
方法是按合同设计的,用于返回UserDetails
的实现,因此它始终返回包含getUsername()
和getPassword()
方法的对象
Spring然后使用合同中的getPassword()
方法并将密码与app_password
字段进行比较(例如super_s3cr3t_password
)
如果在Spring Security Config中配置了passwordEncoder()
或者PasswordEncoder
接口的实现被注册为bean,则spring使用isPasswordValid(String, String, Object)
方法来验证{的内容{1}}字段和app_password
方法
如果UserDetails.getPassword()
没有抛出UserDetailsService
且被抓取的UsernameNotFoundException
UserDetails
与getPassword()
匹配,则过滤器链继续执行另一个过滤器,否则会阻止用户登录应用程序
如果代码示例更好地简化了它,那么想象下面的伪java代码:
app_password
请记住,这不是幕后的Spring Security Code,而只是解释的简化代码说明。