Spring Security未授权登录触发NullPointerException问题排查
解决Spring Security登录时输入错误凭证抛出NullPointerException的问题
问题根源
你遇到的空指针异常(NPE)完全是因为在ApiClient_Service.loadUserByUsername方法里,当查询不到用户时_apiClient为null,却调用了_apiClient.equals(null)——null对象不能调用任何方法,这直接触发了NPE。
看你这段出问题的代码:
if(!_apiClient.equals(null)) { // ... }
当apiClient_repository.findByName($username)返回null时,_apiClient就是null,此时执行_apiClient.equals(null)必然抛出NullPointerException。
修复方案
把对象是否为null的判断改成正确的写法,这里有两种常用方式:
方式1:使用!= null直接判断(最基础可靠的写法)
修改loadUserByUsername方法的判断逻辑:
@Override public UserDetails loadUserByUsername(String $username) throws UsernameNotFoundException { ApiClient _apiClient = apiClient_repository.findByName($username); // 正确判断对象不为null if(_apiClient != null) { log.info("authorized api-client logged-in: "+_apiClient); return new ApiClient_Details(_apiClient); } else { throw new UsernameNotFoundException("unauthorized api-client..."); } }
方式2:使用Java 8+的Objects.nonNull()工具方法(更优雅)
如果你的项目使用Java 8及以上,可以借助java.util.Objects类的静态方法提升代码可读性:
import java.util.Objects; // ... @Override public UserDetails loadUserByUsername(String $username) throws UsernameNotFoundException { ApiClient _apiClient = apiClient_repository.findByName($username); if(Objects.nonNull(_apiClient)) { log.info("authorized api-client logged-in: "+_apiClient); return new ApiClient_Details(_apiClient); } else { throw new UsernameNotFoundException("unauthorized api-client..."); } }
额外健壮性优化
另外,你的ApiClient_Details实现类所有方法都直接依赖apiClient对象,虽然当前逻辑里只有_apiClient不为null时才会创建这个实例,但为了避免后续代码变更带来的潜在问题,可以在构造方法里添加非空校验:
import lombok.AllArgsConstructor; import java.util.Objects; @AllArgsConstructor public class ApiClient_Details implements UserDetails { private ApiClient apiClient; // 手动添加构造方法的非空校验(覆盖lombok生成的无校验构造) public ApiClient_Details(ApiClient apiClient) { this.apiClient = Objects.requireNonNull(apiClient, "ApiClient实例不能为null"); } // 其他原有方法保持不变... }
修改完成后,当输入错误的用户名或密码时,系统会正常抛出UsernameNotFoundException,Spring Security会自动处理这个异常并返回登录失败的响应,不会再出现NullPointerException了。
内容的提问来源于stack exchange,提问作者Nasir Siraj
相关产品推荐
相关产品推荐

