【问题标题】:WSO2 API Manager authentication Violation of UNIQUE KEY constraint errorWSO2 API Manager 身份验证违反 UNIQUE KEY 约束错误
【发布时间】:2016-10-06 00:21:28
【问题描述】:

我们已经在分布式架构中实现了 WSO2 API Manager (v1.10.0),如在线文档 here 中所述。

这包括以下内容(在 5 个单独的服务器上):

  • 网关 (x2)
  • 发布者和商店(在单个服务器上)
  • 密钥管理器 (x2)

这些连接到 3 个普通的 API 管理器数据库(注册表、用户管理器和 API 管理器),它们位于 SQL Server 2014 实例上。

我们使用密钥管理器对网站用户进行身份验证(登录、忘记密码等),以及对 API 调用进行身份验证。

但是,当我尝试登录该站点时,我在密钥管理器上看到以下(违反 UNIQUE KEY 约束)错误:

TID:[-1] [] [2016-10-06 00:36:47,842] 错误 {org.wso2.carbon.identity.oauth2.dao.TokenPersistenceTask} - 错误 持久访问令牌时发生 :c5a0a11e63388dCHANGEDea34b0533445 {org.wso2.carbon.identity.oauth2.dao.TokenPersistenceTask} org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception:错误时 存储消费者密钥的访问令牌: fpA6AhOfbVCHANGEDgH0WzBDOga 在 org.wso2.carbon.identity.oauth2.dao.TokenMgtDAO.storeAccessToken(TokenMgtDAO.java:246) 在 org.wso2.carbon.identity.oauth2.dao.TokenMgtDAO.persistAccessToken(TokenMgtDAO.java:284) 在 org.wso2.carbon.identity.oauth2.dao.TokenPersistenceTask.run(TokenPersistenceTask.java:52) 在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) 在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) 在 java.lang.Thread.run(Thread.java:745) 引起: com.microsoft.sqlserver.jdbc.SQLServerException:违反 UNIQUE KEY 约束“CON_APP_KEY”。无法在对象中插入重复键 'dbo.IDN_OAUTH2_ACCESS_TOKEN'。重复键值为 (15, williams.j2@CHANGED.org.uk, -1234, , APPLICATION_USER,369db21a386ae4CHANGED0ff34d35708d,活动,无)。在 com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:216) 在 com.microsoft.sqlserver.jdbc.SQLServerStatement.getNextResult(SQLServerStatement.java:1515) 在 com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.doExecutePreparedStatement(SQLServerPreparedStatement.java:404) 在 com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement$PrepStmtExecCmd.doExecute(SQLServerPreparedStatement.java:350) 在 com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:5696) 在 com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:1715) 在 com.microsoft.sqlserver.jdbc.SQLServerStatement.executeCommand(SQLServerStatement.java:180) 在 com.microsoft.sqlserver.jdbc.SQLServerStatement.executeStatement(SQLServerStatement.java:155) 在 com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.execute(SQLServerPreparedStatement.java:332) 在 org.wso2.carbon.identity.oauth2.dao.TokenMgtDAO.storeAccessToken(TokenMgtDAO.java:224) ... 5 更多

这会导致网站上出现以下 .NET 错误:

我试过用谷歌搜索,但找不到最新的答案。

我没有将密钥管理器配置为拥有主节点和工作节点(如 here 所述),因为文档似乎表明不需要这样做。

任何帮助将不胜感激!

【问题讨论】:

    标签: sql-server wso2 wso2-am


    【解决方案1】:

    经过一番调试发现问题!在我们放置这个配置之前,

    <JDBCPersistenceManager>
        <SessionDataPersist>
            <PoolSize>0</PoolSize>
        </SessionDataPersist>
    </JDBCPersistenceManager>
    

    APIM 可以将多个 ACTIVE OAUTH 令牌保存到 IDN_OAUTH2_ACCESS_TOKEN 表中,用于单个令牌获取调用。

    当令牌验证端点查询令牌时,仅返回最后一个(使用基于时间的排序和限制)。当那个令牌验证过期时,将其标记为不活动。但前一个保持原样。

    当刷新令牌发生时,它会检查最新的令牌是否处于非活动状态。由于它处于非活动状态,它会发布一个新令牌。但是当令牌端点尝试持久化令牌时,会出现另一个 ACTIVE 令牌。这导致了这个异常。

    为了解决这个问题,我们可以对 IDN_OAUTH2_ACCESS_TOKEN 表运行更新查询,以将所有 ACTIVE 令牌标记为 INACTIVE。

    update IDN_OAUTH2_ACCESS_TOKEN set TOKEN_STATE="INACTIVE" where TOKEN_STATE="ACTIVE"
    

    然后旧的故障令牌将被删除,服务器将开始正常工作!

    【讨论】:

    • 嗨和unslg。感谢您的回答。什么时候运行update SQL 命令?这只是一次性的任务吗?如果是这样,您如何防止此问题再次发生?
    • 这个问题的原因是初始运行没有添加0。为0时,不会发生这种情况。
    • 不幸的是,我仍然看到 CON_APP_KEY 唯一键问题 - 即使在设置 &lt;PoolSize&gt;0&lt;/PoolSize&gt; 之后。这只发生在我离开一段时间后刷新我的应用程序网页时。
    • 我的 identity.xml 中有以下内容:&lt;SessionDataPersist&gt; &lt;PoolSize&gt;0&lt;/PoolSize&gt; &lt;Enable&gt;true&lt;/Enable&gt; &lt;Temporary&gt;false&lt;/Temporary&gt; &lt;SessionDataCleanUp&gt; &lt;Enable&gt;true&lt;/Enable&gt; &lt;CleanUpTimeout&gt;120&lt;/CleanUpTimeout&gt; &lt;CleanUpPeriod&gt;10&lt;/CleanUpPeriod&gt; &lt;/SessionDataCleanUp&gt; &lt;OperationDataCleanUp&gt; &lt;Enable&gt;true&lt;/Enable&gt; &lt;CleanUpPeriod&gt;10&lt;/CleanUpPeriod&gt; &lt;/OperationDataCleanUp&gt; &lt;/SessionDataPersist&gt;
    • 找到导致此 SQL 异常的条目并删除其下的所有活动标记。
    【解决方案2】:

    我使用 mysql 并面临同样的问题。更改池大小也不是一个完整的解决方案。然后我注意到 idn_oauth2_access_token 表有些奇怪。有一列time_created,但内容不是创建时间。这是最后一次更新时间戳。我在某个地方读到了 time_created 列中几列的系统命令。我检查了我的 sql 脚本,发现数据库在触发更新时更新了此列。我删除了这条规则,我没有更多的错误。

    【讨论】:

      【解决方案3】:

      你能改变&lt;APIM_HOME&gt;/repository/conf/identity.xml下面的配置(&lt;PoolSize&gt;0&lt;/PoolSize&gt;),看看?默认情况下,PoolSize 设置为 100。

      <JDBCPersistenceManager>
          <SessionDataPersist>
              <PoolSize>0</PoolSize>
          </SessionDataPersist>
      </JDBCPersistenceManager>
      

      希望这能解决您的问题。

      参考:http://sanjeewamalalgoda.blogspot.com/2015/08/how-to-avoid-getting-incorrect-access.html

      【讨论】:

      • 嗨@Bhathiya。感谢您的回答。我确实看到了您链接到的页面。但是,我对此不以为然,因为我正在使用的版本(v1.10.0 - 而不是 v1.9.0)没有&lt;APIM_HOME&gt;/repository/conf/identity.xml 文件,并且它确实拥有的&lt;APIM_HOME&gt;/repository/conf/indentity/identity.xml 文件没有@987654327 @ 里面的元素。然而,它确实有一个 &lt;SessionDataPersist&gt;&lt;Enable&gt;true&lt;/Enable&gt;...&lt;/SessionDataPersist&gt; 元素(目前已被注释掉)。我应该取消注释吗?如果是这样,它的值应该是true 还是false
      • 我刚刚取消了&lt;SessionDataPersist&gt; 元素的注释,并尝试设置&lt;Enable&gt;true&lt;/Enable&gt;,然后设置&lt;Enable&gt;false&lt;/Enable&gt;。但是,我在这两种情况下仍然遇到同样的问题。我将首先尝试运行清理(通过将其值设置为 1),然后再次尝试使用 &lt;Enable&gt;true&lt;/Enable&gt;
      • 是的,请尝试启用它并设置&lt;PoolSize&gt;0&lt;/PoolSize&gt;
      • 我已经实现了这个,但我仍然看到同样的问题。我试图确定新行首次添加到 API Manager 数据库中的 IDN_OAUTH2_ACCESS_TOKEN 表的确切时间以及在什么条件下。
      • 在我们的设置中,这个版本也出现了同样的错误!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-01-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多