You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Spring Security注册时出现rawPassword cannot be null异常排查

问题排查:Spring Security注册时rawPassword cannot be null异常

问题场景

使用Spring Security的SecurityFilterChain配置安全规则,已定义BCryptPasswordEncoder Bean,但用户注册接口调用时抛出rawPassword cannot be null异常,相关代码如下:

SpringSecurity配置类

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SpringSecurity {

    private final RecipesUserDetailsService userDetailsService;

    @Autowired
    public SpringSecurity(RecipesUserDetailsService userDetailsService) {
        this.userDetailsService = userDetailsService;
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public DaoAuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
        authProvider.setUserDetailsService(userDetailsService);
        authProvider.setPasswordEncoder(passwordEncoder());
        return authProvider;
    }

    @Bean
    SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.httpBasic()
                .and()
                .authorizeRequests()
                .antMatchers("/api/register").anonymous()
                .antMatchers("/actuator/shutdown").anonymous()
                .antMatchers("/h2-console/**").anonymous()
                .anyRequest().authenticated()
                .and()
                .csrf().disable()
                .headers().frameOptions().disable();
        return http.build();
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(authenticationProvider());
    }

}

RecipesUserDetailsService

@Service
@AllArgsConstructor
public class RecipesUserDetailsService implements UserDetailsService {
    private final UserRepository userRepository;


    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findById(username)
                .orElseThrow(() -> new UsernameNotFoundException("User not found"));
        return new RecipeUserDetails(user);
    }
}

错误日志

2023-04-21 04:41:09.574 ERROR 404954 --- [nio-8822-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.IllegalArgumentException: rawPassword cannot be null] with root cause

java.lang.IllegalArgumentException: rawPassword cannot be null
    at org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder.encode(BCryptPasswordEncoder.java:107) ~[spring-security-crypto-5.5.3.jar:5.5.3]
    at recipes.service.UserService.add(UserService.java:26) ~[classes/:na]
    at recipes.controller.RegistrationController.register(RegistrationController.java:29) ~[classes/:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]

注册Controller

@ResponseStatus(HttpStatus.OK)
public void register(@JsonView(UserJsonView.RegistrationView.class)
                         @Valid @RequestBody User user){
    userService.add(user);
}

UserService

@Service
public class UserService {
    private final UserRepository userRepository;
    private final PasswordEncoder passwordEncoder;

    @Autowired
    public UserService(UserRepository userRepository, PasswordEncoder passwordEncoder) {
        this.userRepository = userRepository;
        this.passwordEncoder = passwordEncoder;
    }

    public void add(User user) {
        if (userRepository.existsById(user.getEmail())) {
            throw new KeyAlreadyExistsException();
        }
        String encodedPassword = passwordEncoder.encode(user.getPassword());
        user.setPassword(encodedPassword);
        userRepository.save(user);
    }
    public void addTest(User user) {
        userRepository.save(user);
    }
}

User实体类

@Entity
@Table(name = "USERS")
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class User {
    @Id
    @NotBlank
    @Email(regexp = "^(?=.{1,64}@)[A-Za-z0-9\\+_-]+(\\.[A-Za-z0-9\\+_-]+)*@"
            + "[^-][A-Za-z0-9\\+-]+(\\.[A-Za-z0-9\\+-]+)*(\\.[A-Za-z]{2,})$")
    @JsonView(UserJsonView.RegistrationView.class)
    private String email;


    @Size(min = 8)
    private String password;

     @OneToMany(mappedBy = "user",cascade = CascadeType.ALL)
     private Set<Recipe> recipe;
}

问题根源

注册接口使用了@JsonView(UserJsonView.RegistrationView.class)注解,但User实体类的password字段未添加该注解,导致请求JSON中的password字段无法被反序列化到User对象中,调用passwordEncoder.encode(user.getPassword())时传入null,触发BCryptPasswordEncoder的非空校验异常。

修复方案

修改User实体类的password字段,添加对应的@JsonView注解:

@Size(min = 8)
@JsonView(UserJsonView.RegistrationView.class) // 新增此注解,确保password字段被反序列化
private String password;

额外验证

  1. 确保注册请求的JSON包含password字段,且长度至少为8位
  2. 确认@Valid注解生效:若请求缺少password或不符合长度要求,应返回400 Bad Request,避免进入service层执行加密逻辑

内容的提问来源于stack exchange,提问作者lulzeR

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 14:27:14