【问题标题】:Initialize repositories protected by Spring authentication初始化受 Spring 身份验证保护的存储库
【发布时间】:2019-10-12 20:31:55
【问题描述】:

我使用 Spring Boot Data REST 将实体的 Hibernate 存储库映射到 REST 路由。我还使用 Spring Security 的 @PreAuthorize 注释来保护这些存储库的某些方法。这在生产过程中工作正常,但是当我想用数据以编程方式初始化存储库时(例如,添加第一个用户以开始使用和一些其他示例数据),它抱怨“在 SecurityContext 中找不到身份验证对象”。我意识到这是因为在我配置数据库时安全上下文中没有经过身份验证的用户(使用自动装配的组件将对象保存到存储库)。不过我想在配置的时候暂时绕过这个授权,这样我就可以初始化数据库了。

有什么方法可以实现吗?如果没有,如何在初始化方法中手动登录?我已经看到了对第二种方法的一些尝试,但它们都需要访问AuthenticationManager,我不知道如何获得。

【问题讨论】:

  • 至少应该有一个超级用户。它应该具有所有访问权限。我们可以在启动服务器时使用资源位置中的一些 SQL 脚本输入条目。
  • 您是如何添加初始数据的?通过 REST?如果是这样,为什么要使用 REST 而不是 liquebase 之类的东西?
  • 我通过@Component 添加初始数据,使用repository.save(以编程方式)
  • @Prasath 我确实在这个设置组件中添加了一个超级用户。但是,如果可能的话,我宁愿不要在 SQL 中执行此操作,而是在 Java 代码中执行此操作
  • 我们可以做一些解决方法。硬编码一个用户记录并在服务器启动时保存。使用@postconstruct 的某种方法从服务类执行此硬编码。

标签: java spring spring-boot spring-security


【解决方案1】:

一个简单的解决方案:忽略安全性并专注于一个空的存储库

@Component
class InitializeDataIfNoDataPresent {
  private final UserRepo repository;

  public InitializeDataIfNoDataPresent(UserRepo repo) {
      this.repository = repo;
  }

  @EventListener(ApplicationReadyEvent.class)
  public void init() {
    if(0 == repository.count()) {
      setupData();
    } 
  }

  @PreAuthorize("hasRole('ADMIN')")
  public void setupData() {
    // your existing setup
  }

}

当应用程序启动并且您的存储库为空时,即使没有用户在场,setupData() 也会被调用。

参考:stackoverflow-initialization-secured

【讨论】:

    【解决方案2】:

    您可以使用以下代码创建一个具有足够权限的假用户,并在运行该受保护方法之前将其设置为SecurityContext

    List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
    
    //Setup the permission that the user should have in order to run that method.
    //It is the customized value based on your security configuration
    grantedAuthorities.add(new SimpleGrantedAuthority("ROLE_SUPER_ADMIN")); 
    
    //Ensure this user is enabled , active and has above permission
    User user = new User("admin", "password", true, true, true, true, grantedAuthorities);
    
    Authentication auth = new UsernamePasswordAuthenticationToken(user, user.getPassword(), user.getAuthorities());
    SecurityContextHolder.getContext().setAuthentication(auth);
    

    执行该受保护方法后,重置SecurityContext(相当于注销):

    SecurityContextHolder.clearContext();
    

    【讨论】:

      猜你喜欢
      • 2014-11-20
      • 1970-01-01
      • 1970-01-01
      • 2017-01-30
      • 2013-12-11
      • 1970-01-01
      • 2016-06-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多