一、问题描述
无法登陆,登录报错
二、问题排查
这个报错,我们可以从spring security的源码中看到
很明显,就是在创建security的User对象的时候,username参数为null或为空字符串/password为空
那哪里会创建security的User对象呢?
在Security的UserDetailsService类的实现类中创建了security的对象
public class MyUserDetailsService implements UserDetailsService {
// 部分代码略
public UserDetails loadUserByUsername(String username) {
// 部分代码略
return new org.springframework.security.core.userdetails.User(
username,
password, // 【注意】这个password是在数据库根据username查的
true,
true,
true,
true,
RoleConfig.getAuthorities(xxx)
);
}
}
在这里我们可以看到要么username的问题,要么password的问题。
三、解决思路
在你项目中找到哪里创建了org.springframework.security.core.userdetails.User对象,然后排查username和password为空的情况,数据库限制、代码限制等方式,限制这两个字段不为空。
四、补充
简单解释Security是如何做密码校验的,帮助排查密码是否为null和其它关于密码检验失败的问题。
public class JWTLoginFilter extends AbstractAuthenticationProcessingFilter {
@Override
public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res) throws AuthenticationException, IOException {
// 部分代码省略
return getAuthenticationManager().authenticate(
new UsernamePasswordAuthenticationToken(
username,
password // 【注意】这个password是登陆时传过来的
)
);
}
@Override
protected void successfulAuthentication(HttpServletRequest req,
HttpServletResponse res,
FilterChain chain,
Authentication auth) throws IOException {
// 部分代码省略
}
@Override
protected void unsuccessfulAuthentication(HttpServletRequest req,
HttpServletResponse res,
AuthenticationException failed) throws IOException {
// 部分代码省略
}
// 部分代码省略
}
在attemptAuthentication方法中,最后return的这一步,会做2个操作
(1)携带username这参数,调用问题排查中讲到的loadUserByUsername方法,加载数据库信息到security的User对象中。
(2)拿参数password【登陆时前端传来的】按照配置的或者默认的加密方式加密后与上一步User中的passward【数据库查的】进行比较,相同则调用successfulAuthentication方法,失败调unsuccessfulAuthentication方法,我们可以自定义这两个方法,来处理成功和失败要做的操作。
最后修改时间:2021-11-12 22:23:50
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。