【问题标题】:Spring OAuth2 Requiring PlatformTransactionManagerSpring OAuth2 需要 PlatformTransactionManager
【发布时间】:2015-09-19 04:57:20
【问题描述】:

我正在将 Spring Security OAuth2 与 JWT 令牌集成到 Spring Boot 项目中。我的身份验证服务器的配置类似于 sample project 中的配置。

当 OAuth2 客户端在 /oauth/token 上执行 POST 时,它无法创建访问令牌。记录的具体错误是:

o.s.s.o.provider.endpoint.TokenEndpoint : Handling error: NoSuchBeanDefinitionException, No qualifying bean of type [org.springframework.transaction.PlatformTransactionManager] is defined

在调用tokenServices.createAccessToken 时,我已将其调试到AbstractTokenGranter 第70 行。我无法轻松地进行进一步调试,因为此调用实际上是通过代理进行的。配置中的某些东西似乎想让这个事务性。在 JWT 中创建访问令牌不应该是事务性的。我可以理解为什么检索访问代码是事务性的,但代码成功地通过了这一点。

为什么这需要PlatformTransactionManager,我该如何提供?

【问题讨论】:

    标签: spring spring-security oauth-2.0 spring-security-oauth2


    【解决方案1】:

    问题是您在应用程序中配置了使用new InMemoryTokenStore() 的内存数据库,但您的spring-boot 应用程序不包含内存数据库。

    解决方案:在你的 spring-boot pom 或 gradle 依赖中添加一个内存数据库。

    H2 和 Maven pom 示例:

    <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <version>1.4.187</version>
    </dependency>
    

    【讨论】:

    • 感谢您的建议,但我没有使用任何 SQL 数据库。
    • 问题:您的注册客户存放在哪里?
    • 再给你一个提示。默认 DefaultTokenService 的 spring 内部 spring 实现使用 @Transactional 注释(第 81 行)。比您需要任何类型的事务管理器。我为您看到了两个解决方案。实现一个你自己的没有事务注释的 TokenService 或者在内存数据库中添加一个作为依赖项。
    • 它与提供内存数据库无关。 Sprin Oauth InMemory 实现使用 Map 来存储键和值。
    • @FlorianE。我想将权限存储在一个单独的表中,但DefaultTokenService 中的getAccessToken 没有用@Transactional 注释。所以我得到一个惰性初始化异常,不知道有没有什么原因不代理get方法?
    【解决方案2】:

    我遇到了 PlatformTransactionManager 的类似问题,并通过以下步骤解决了它:

    1. 将 H2 数据库添加到 pom.xml(以便将客户端存储在内存中)
    2. 使用 Mongo DB 作为应用程序后端。 (确保应用程序使用 MongoRepository 而不是 CrudRepository)
    3. 删除了 @EnableAutoConfiguration 注释中的排除类(我之前在排除中添加了 DataSourceAutoConfiguration.class

    第 1 点和第 3 点是相互的。 H2 配置应该启用 DataSourceAutoConfiguration.class。

    谢谢。

    【讨论】:

      【解决方案3】:

      我遇到了同样的问题

      tokenServices.createAccessToken 使用 @Transactional 。 当我使用 mongo DB 时,我不需要事务。

      我通过添加 PseudoTransactionManager bean 解决了这个问题。

      @Bean
      public PlatformTransactionManager annotationDrivenTransactionManager() {
          return new PseudoTransactionManager();
      }
      

      【讨论】:

        【解决方案4】:

        问题在于 DefaultTokenServices 中的方法是用@Transactional 注释的。因此,即使您不使用数据库,您也需要在授权服务器配置中添加这样的事务管理器 bean:

            @Bean
            public PlatformTransactionManager annotationDrivenTransactionManager() {
                return new ResourceTransactionManager() {
                    @Override
                    public Object getResourceFactory() {
                        return null;
                    }
        
                    @Override
                    public TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
                        return null;
                    }
        
                    @Override
                    public void commit(TransactionStatus status) throws TransactionException {
        
                    }
        
                    @Override
                    public void rollback(TransactionStatus status) throws TransactionException {
        
                    }
                };
            }
        

        【讨论】:

          猜你喜欢
          • 2016-10-06
          • 2018-02-13
          • 1970-01-01
          • 2019-01-03
          • 2019-07-29
          • 1970-01-01
          • 2019-10-18
          • 1970-01-01
          • 2018-07-15
          相关资源
          最近更新 更多