如何在登录中使用多个UserDetails实现:Spring Security和Spring Boot

huangapple go评论75阅读模式
英文:

How to use multiple UserDetails implementations for login: Spring Security and Spring Boot

问题

我正在开发一个Spring Boot应用程序,并且有以下情景-

  1. 我有三种类型的用户帐户- a. 普通用户, b. 管理员用户 c. 公司
  2. 管理员用户可以创建一个公司实体。
  3. 管理员用户和公司需要具有登录功能,普通用户可以在没有登录的情况下访问端点(公共页面)。
  4. 现在,问题是我有两个独立的表格用于用户(具有管理员和普通角色)和公司。它们都实现了UserDetails,并且我希望为这些不同的实体使用登录功能。
  5. 用户将能够使用用户名和密码登录。公司可以使用公司名称(而不是电子邮件)和密码登录。
  6. 我无法合并用户和公司表格,因为它们具有不同的属性,而且管理员用户可以创建公司。
    那么,我如何配置Spring Security以用于不同的UserDetails实现,以及如何在运行时选择尝试登录的实体,无论是用户还是公司?请帮忙!
英文:

I am working on a spring boot application and has the following scenario-

  1. I have three types of user accounts- a. Normal Users, b. Admin users c. Company
  2. Admin users can create a company entity.
  3. Admin users and company need to have login functionality and normal users can access endpoints without login (public pages).
  4. Now, the problem is that I have two separate tables for User (with admin and normal role) and Company. Both implement UserDetails and I want to use login functionality for these different entities.
  5. A user will be able to login with username and password. A company can login with company name (not email) and password.
  6. I cannot merge the user and company table because they have different attributes and also, an admin user can create a company.
    So, how can I configure Spring Security for different implementations of UserDetails and how to choose at runtime which entity is trying to login whether it is a user or a company? Please help!

答案1

得分: 1

我会使用一个由其他服务组成的详细信息服务(用于公司和用户)。

对于公司:

public class CompanyDetailsService implements UserDetailsService {

  private final CompanyRepo companyRepo;

  @Override
  public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    Optional<Company> company = this.companyRepo.findByName(username);
    // 处理结果
  }
}

对于用户:

public class UserDetailsService implements org.springframework.security.core.userdetails.UserDetailsService {

  private final UserRepo userRepo;

  @Override
  public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    Optional<User> user = this.userRepo.findByUserName(username);
    // 处理结果
  }
}

用于实际登录的组合服务:

public class CompositeDetailsService implements UserDetailsService {

  private final List<UserDetailsService> services;

  public CompositeDetailsService(List<UserDetailsService> services) {
    this.services = services;
  }

  @Override
  public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    for (UserDetailsService delegate : this.services) {
      try {
        return delegate.loadUserByUsername(username);
      } catch (UsernameNotFoundException ignore) {
      }
    }
    throw new UsernameNotFoundException("");
  }
}

然后根据需要自动装配组合服务。

英文:

I would use a details service composed from other services (for company and user).

For company:

public class CompanyDetailsService implements UserDetailsService {

  private final CompanyRepo companyRepo;

  @Override
  public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    Optional&lt;Company&gt; company = this.companyRepo.findByName(username);
    //handle result
  }
}

For user:

public class UserDetailsService implements org.springframework.security.core.userdetails.UserDetailsService {

  private final UserRepo userRepo;

  @Override
  public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    Optional&lt;User&gt; user = this.userRepo.findByUserName(username);
    //handle result
  }
}

Composed service to use for the actual login:

public class CompositeDetailsService implements UserDetailsService {

  private final List&lt;UserDetailsService&gt; services;

  public CompositeDetailsService(List&lt;UserDetailsService&gt; services) {
    this.services = services;
  }

  @Override
  public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    for (UserDetailsService delegate : this.services) {
      try {
        return delegate.loadUserByUsername(username);
      } catch (UsernameNotFoundException ignore) {
      }
    }
    throw new UsernameNotFoundException(&quot;&quot;);
  }
}

Then autowire the composite service where needed.

huangapple
  • 本文由 发表于 2023年6月15日 14:27:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/76479689.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定