【问题标题】:Extends Spring security user class扩展 Spring 安全用户类
【发布时间】:2021-03-25 23:30:53
【问题描述】:

我正在开发一个 Spring 安全项目。我尝试扩展 security.core.userdetails.User 类以在注册用户时添加更多详细信息。

用户扩展类

public class UserDetails extends User {

    private int id;
    private String Country;


public UserDetails(String username, String password, Collection<? extends GrantedAuthority> authorities, int id,
        String country) {
    super(username, password, authorities);
    this.id = id;
    Country = country;
}

public UserDetails(String username, String password, boolean enabled, boolean accountNonExpired,
        boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities,
        int id, String country) {
    super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
    this.id = id;
    Country = country;
}




public int getId() {
    return id;
}


public void setId(int id) {
    this.id = id;
}


public String getCountry() {
    return Country;
}


public void setCountry(String country) {
    Country = country;
}

我还在实体类(模型类)中添加了 ID 和国家/地区。

但是当我尝试注册用户时。 它给出一个错误。org.springframework.dao.DataIntegrityViolationException: PreparedStatementCallback; SQL [插入用户(用户名,密码,启用)值(?,?,?)];字段“id”没有默认值;嵌套异常是 java.sql.SQLException: Field 'id' doesn't have a default value

(id和国家的值是硬编码的)

控制器类

try {
        List<GrantedAuthority> authority = new ArrayList<>();
        authority.add(new SimpleGrantedAuthority(form.getRole()));
        String encodedPassword = passwordEncoder.encode(form.getPassword());
        
        UserDetails details = new UserDetails(form.getUsername(), encodedPassword, authority, 10 ,"India");
        System.out.println(details.getId()+" "+details.getCountry() +" "+details.getUsername());
        System.out.println(details);
        detailsManager.createUser(details);
  }

输出

10 印度 alpha@gmail.com

com.example.demo.model.UserDetails [Username=alpha@gmail.com, Password=[PROTECTED], Enabled=true, AccountNonExpired=true, credentialsNonExpired=true, AccountNonLocked=true, Granted Authorities=[ROLE_ADMIN]]

我不知道它为什么调用父类构造函数。

【问题讨论】:

  • 可以添加用户类定义吗?
  • 用户是spring security用户类(org.springframework.security.core.userdetails.User)

标签: spring spring-boot spring-security spring-data-jpa


【解决方案1】:

SQL 不正确。 Spring Security 的INSERT 默认填充usernamepasswordenabled 列。但是,您创建的users 表也需要id 列。由于查询没有指定值,所以它失败了。

您可以尝试扩展JdbcUserDetailsManager 的各种方法以了解您的id 字段。您至少需要扩展 createUser 以便将 id 添加到 INSERT 语句和 findUserByUsername 以便构造您的自定义对象。

不过,更好的方法是发送至use Spring Data。这允许您的域对象独立于 Spring Security。此外,Spring Data 具有更广泛的 SQL 支持。

将您的类称为不同于 Spring Security 接口的名称可能会有所帮助。因此,让我们假设您的自定义类(带有id 的类)被称为YourUser(而不是UserDetails)。现在,您可以将基于 Spring Data 的 UserDetailsService 连接到 Spring Security,如下所示:

@Service
public class YourUserRepositoryUserDetailsService implements UserDetailsService {
    private final YourUserRepository users; // your Spring Data repository

    // ... constructor

    @Override
    public UserDetails findUserByUsername(String username) {
        YourUser user = this.users.findByUsername(username)
            .orElseThrow(() -> new UserNotFoundException("not found"));
        return new UserDetailsAdapter(user);
    }

    private static class UserDetailsAdapter extends YourUser implements UserDetails {
        UserDetailsAdapter(YourUser user) {
            super(user); // copy constructor
        }

        // ... implement UserDetails methods
    }
}

UserDetailsService 替换您正在发布的 JdbcUserDetailsManager

【讨论】:

  • 您好,感谢您的回复,但我没有得到那部分,即创建用户详细信息的服务类。基本上用户详细信息类是用户类(org.springframework.security.core.userdetails.User)的扩展。
  • 我更改了类名并添加了更多解释。这有帮助吗?
猜你喜欢
  • 2017-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多