带有额外字段的Spring Boot UserDetailsservice多用户

发布于 2025-01-31 03:15:44 字数 1219 浏览 0 评论 0原文

我有一个Spring Boot项目,该项目有3种类型的用户(管理员,专家,客户),并且该应用程序适用于在现场注册的专家,以提供诸如将计算机修复的服务诸如向网站询问帮助的客户固定计算机之类的服务。

我具有不同类型的用户类型的继承。

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "USER_TYPE", discriminatorType = DiscriminatorType.INTEGER)
public abstract class User {

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    private String username;
    private String password;
    private Set<String> roles = new HashSet<>();

    // getter & setter...
}


@Entity
@DiscriminatorValue("1")
public class Admin extends User {
}


@Entity
@DiscriminatorValue("2")
public class Expert extends User {

    private Byte[] expertPhoto;
    private String password;

    // some other fields & getter & setter...
}


@Entity
@DiscriminatorValue("3")
public class Customer extends User {

    private Long credit;
    private Set<CustomerOrder> orders = new HashSet<>();

    // some other fields & getter & setter...
}

我想使用Spring Boot Security并实现UserDetailsservice,我的问题是当我有不同的用户类型(专家,客户等)时如何设计?

我希望用户能够使用一个用户名担任不同的角色(管理员,专家,客户)。

我应该如何设计我的系统来解决这些要求?

I have a spring boot project that has 3 types of users (Admin, Expert, Customer) and the application is for Experts that register on site for giving services like fixing computers to Customers that are asking help in site.

I have an inheritance of different kind of User types as following.

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "USER_TYPE", discriminatorType = DiscriminatorType.INTEGER)
public abstract class User {

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    private String username;
    private String password;
    private Set<String> roles = new HashSet<>();

    // getter & setter...
}


@Entity
@DiscriminatorValue("1")
public class Admin extends User {
}


@Entity
@DiscriminatorValue("2")
public class Expert extends User {

    private Byte[] expertPhoto;
    private String password;

    // some other fields & getter & setter...
}


@Entity
@DiscriminatorValue("3")
public class Customer extends User {

    private Long credit;
    private Set<CustomerOrder> orders = new HashSet<>();

    // some other fields & getter & setter...
}

I want to use spring boot security and implement UserDetailsService, my problem is that how to design when I have different User types (Expert, Customer, etc.)?

I want users to be able to have different roles (admin, expert, customer) with one username.

How should I design my system to solve these requirements?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

那些过往 2025-02-07 03:15:44

您的角色模式似乎有些偏离。最好拥有一种用户的单一类型,然后用新的角色实体填充它。新的用户实体将看起来如下:

@Table(name = "user")
@Entity
public class User {

    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "username", unique = true, nullable = false)
    private String username;

    @Column(name = "password", nullable = false)
    private String password;

    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(
            name = "user_role",
            joinColumns = {@JoinColumn(name = "user_id")},
            inverseJoinColumns = {@JoinColumn(name = "role_id")},
    )
    private Set<Role> roles;

// getters and setters & other fields user can have

}

角色实体看起来像这样:

@Entity
@Table(name = "role")
public class Role {

    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "role_name", unique = true, nullable = false)
    private String roleName;

    @ManyToMany(mappedBy = "roles")
    private Set<User> users;
}

然后,您需要实现org.springframework.security.core.core。 UserDetails.user接口用作userDetailsS​​ervice的Spring Security Class user 的具体实现。请注意,此类也称为用户,并且与系统上的用户类不同。

public class MyUserDetail extends User {

    private String otherFieldsLikePhoto; // you can add different fields like this to keep extra information

    public MyUserDetail(String username, String password, Collection<? extends GrantedAuthority> authorities, String otherFieldsLikePhoto) {
        super(username, password, authorities);
        this.otherFieldsLikePhoto = otherFieldsLikePhoto;
    }
}

然后,您可以通过实现org.springframework.security.core.core.userdetails.userdetailsservice,可以创建userDetailsS​​ervice

您将获得userDetailsservice是在我们刚创建的myuserdetail格式中加载用户。这样就是这样:

public class MyUserDetailsService implements UserDetailsService {

    private final UserReadService userReadService; // put your service to get user from db

    public MyUserDetailsService(UserReadService UserReadService) {
        this.userReadService = UserReadService;
    }

    @Override
    public UserDetails loadUserByUsername(String username) {
        User user = userReadService.getByUsername(username); // get user from db
        String otherFieldsLikePhoto = getUserPhotoOrAnythingElse(user); // get your extra fields however you want

        return new MyUserDetail(
                user.getUsername(),
                user.getPassword(),
                getAuthoritySetOfUser(user), // notice how we embed roles to UserDetail
                otherFieldsLikePhoto
        );
    }

    // this function is not necessary but useful to calculate authority set calculation on helper
    private Set<SimpleGrantedAuthority> getAuthoritySetOfUser(User user) {
        Set<Role> userRoles = user.getRoles();  // get roles of user like ADMIN, EXPERT etc.
        Set<SimpleGrantedAuthority> authorities = roles.stream()
            .map(rolex -> new SimpleGrantedAuthority(rolex.getRoleName()))
            .collect(Collectors.toSet());
       

        return authorities;
    }

}

Your role modal seems a bit off. It is better to have a single type of User and fill it with list of a new Role entity. The new User entity will look like the following:

@Table(name = "user")
@Entity
public class User {

    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "username", unique = true, nullable = false)
    private String username;

    @Column(name = "password", nullable = false)
    private String password;

    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(
            name = "user_role",
            joinColumns = {@JoinColumn(name = "user_id")},
            inverseJoinColumns = {@JoinColumn(name = "role_id")},
    )
    private Set<Role> roles;

// getters and setters & other fields user can have

}

And the Role entity will look like this:

@Entity
@Table(name = "role")
public class Role {

    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "role_name", unique = true, nullable = false)
    private String roleName;

    @ManyToMany(mappedBy = "roles")
    private Set<User> users;
}

Then, you need to implement org.springframework.security.core.userdetails.User interface to use as a concrete implementation of spring security class Useron your UserDetailsService. Notice that this class is also called User and is different than the User class on your system.

public class MyUserDetail extends User {

    private String otherFieldsLikePhoto; // you can add different fields like this to keep extra information

    public MyUserDetail(String username, String password, Collection<? extends GrantedAuthority> authorities, String otherFieldsLikePhoto) {
        super(username, password, authorities);
        this.otherFieldsLikePhoto = otherFieldsLikePhoto;
    }
}

Then, you can create your UserDetailsService by implementing org.springframework.security.core.userdetails.UserDetailsService of spring security.

What you will achieve UserDetailsService is to load the user in the MyUserDetail format we just created. It will be something like this:

public class MyUserDetailsService implements UserDetailsService {

    private final UserReadService userReadService; // put your service to get user from db

    public MyUserDetailsService(UserReadService UserReadService) {
        this.userReadService = UserReadService;
    }

    @Override
    public UserDetails loadUserByUsername(String username) {
        User user = userReadService.getByUsername(username); // get user from db
        String otherFieldsLikePhoto = getUserPhotoOrAnythingElse(user); // get your extra fields however you want

        return new MyUserDetail(
                user.getUsername(),
                user.getPassword(),
                getAuthoritySetOfUser(user), // notice how we embed roles to UserDetail
                otherFieldsLikePhoto
        );
    }

    // this function is not necessary but useful to calculate authority set calculation on helper
    private Set<SimpleGrantedAuthority> getAuthoritySetOfUser(User user) {
        Set<Role> userRoles = user.getRoles();  // get roles of user like ADMIN, EXPERT etc.
        Set<SimpleGrantedAuthority> authorities = roles.stream()
            .map(rolex -> new SimpleGrantedAuthority(rolex.getRoleName()))
            .collect(Collectors.toSet());
       

        return authorities;
    }

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文