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

Spring Security中BasicUserDetails构造函数无法解析的问题求助

问题背景

最初为基础登录用户实现了BasicUserDetails类:

@Data
@NoArgsConstructor
@AllArgsConstructor
public class BasicUserDetails implements UserDetails {
    @NotBlank(message = "Username is mandatory")
    @Email(message = "Username should be a valid email address")
    private String username;

    @NotBlank(message = "Password is mandatory")
    @Size(min = 8, message = "Password length should be at least 8 characters")
    private String password;
    private List<GrantedAuthority> authorities;
    private boolean enabled;

    // 重写UserDetails接口的方法(略)
}

新增OAuth用户后,由于OAuth用户无需密码,调整了类结构:

OAuth用户类

@Data
@NoArgsConstructor
@AllArgsConstructor
public class OAuthUserDetails implements UserDetails {
    @NotBlank(message = "Username is mandatory")
    @Email(message = "Username should be a valid email address")
    private String username;
    private List<GrantedAuthority> authorities;
    private boolean enabled;

    // 重写UserDetails接口的方法,getPassword返回占位符(略)
}

基础用户类

@Data
@NoArgsConstructor
@AllArgsConstructor
public class BasicUserDetails extends OAuthUserDetails {
    @NotBlank(message = "Password is mandatory")
    @Size(min = 8, message = "Password length should be at least 8 characters")
    private String password;

    @Override
    public String getPassword() {
        return password;
    }
}
问题描述

在CustomUserService的loadUserByUsername方法中实例化BasicUserDetails时报错:

@Component
@AllArgsConstructor
public class CustomUserService implements UserDetailsService {
    private UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByUsername(username);
        if (null == user || ! user.getUsername().equals(username)) {
            throw new UsernameNotFoundException("No user present with username: " + username);
        }
        else {
            // 此处报错
            return new BasicUserDetails(user.getUsername(), user.getPassword(), Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")), true);
        }
    }
}

报错信息:Cannot resolve constructor 'BasicUserDetails(String, String, List, boolean)',已知BasicUserDetails的全参构造仅接收password参数,请问如何传递其余参数?

解决方案

问题核心是:BasicUserDetails的@AllArgsConstructor只会生成包含自身新增属性(仅password)的构造方法,不会自动继承父类的属性构造逻辑。要传递父类的username、authorities、enabled参数,有两种可行方案:

方案一:手动编写子类构造方法

在BasicUserDetails中添加包含父类属性的构造方法,显式调用父类的全参构造:

@Data
@NoArgsConstructor
public class BasicUserDetails extends OAuthUserDetails {
    @NotBlank(message = "Password is mandatory")
    @Size(min = 8, message = "Password length should be at least 8 characters")
    private String password;

    // 手动编写包含父类属性的构造方法
    public BasicUserDetails(String username, List<GrantedAuthority> authorities, boolean enabled, String password) {
        super(username, authorities, enabled);
        this.password = password;
    }

    @Override
    public String getPassword() {
        return password;
    }
}

之后在CustomUserService中调整实例化参数顺序,匹配构造方法:

return new BasicUserDetails(user.getUsername(), Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")), true, user.getPassword());

方案二:使用@SuperBuilder注解简化构造逻辑

借助Lombok的@SuperBuilder注解实现父子类的构造参数传递,无需手动编写构造方法:

修改父类OAuthUserDetails

@Data
@NoArgsConstructor
@AllArgsConstructor
@SuperBuilder
public class OAuthUserDetails implements UserDetails {
    // 属性和原有方法保持不变
}

修改子类BasicUserDetails

@Data
@NoArgsConstructor
@AllArgsConstructor
@SuperBuilder
public class BasicUserDetails extends OAuthUserDetails {
    // 属性和原有方法保持不变
}

实例化时使用Builder模式

return BasicUserDetails.builder()
        .username(user.getUsername())
        .password(user.getPassword())
        .authorities(Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")))
        .enabled(true)
        .build();

方案对比

  • 方案一适合不需要Builder模式的场景,代码逻辑直白,无额外依赖成本;
  • 方案二用注解简化构造逻辑,后续新增属性时无需修改构造方法,扩展性更强。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 13:13:19