Duplicate Oauth2 AccessTokens Created
11901 ワード
Background
ソリューションのOAuth 2機能では、次の間欠的なエラーが発生したことを示す通知が表示されます.
省略...
Incorrect result size: expected 1, actual 2
...
...JdbcTemplate.queryForObject(JdbcTemplate.java:797)
...JdbcTokenStore.getAccessToken(JdbcTokenStore.java:105)
...JadeTokenService.createAccessToken(JadeTokenService.java:112)
省略...
CheckPoint
OAuth 2はSpringのOAuth 2機能を利用しているので,以下に示すように,まず検索を行い,関連する問題があるかどうかを決定した.
https://github.com/spring-projects/spring-security-oauth/issues/276
https://github.com/jhipster/generator-jhipster/issues/1759
https://github.com/jhipster/generator-jhipster/pull/1782
前述したように、1番目のSpring Outh 2 Oldバージョンにはトランザクションがない場合があり、2番目の同じclient idが複数のtokenを同時に要求すると、2つ以上の同じtokenがDBに格納される場合があります.
ただし、Tokenをアプリケーション側から取り出す場合は、1つの値を待機して取り出すだけなので、2つ以上のクエリーがある場合は、すぐにエラーが発生する可能性があります.
Replayed
エラーまたはエラー操作で最も重要なのは、プロジェクトチームで発生した同じ現象を再プレゼンテーションすることです.
PostManとFilderは、同じリクエストをコピーし、複数のリクエストを同時に呼び出すことで、同じ状況を再現します.
PostManを使用したトークン要求の発行
Fiddlerを利用した複数のリクエスト.500エラーを確認します.
500 Error詳細
14:23:35.760 [http-bio-8080-exec-8] ERROR s.e.SpringWebExceptionHandler [EID:] [SS-ID:] [USER-ID:] - Incorrect result size: expected 1, actual 3[END]
org.springframework.dao.IncorrectResultSizeDataAccessException: Incorrect result size: expected 1, actual 3
at org.springframework.dao.support.DataAccessUtils.requiredSingleResult(DataAccessUtils.java:74)
at org.springframework.jdbc.core.JdbcTemplate.queryForObject(JdbcTemplate.java:737)
at org.springframework.security.oauth2.provider.token.JdbcTokenStore.getAccessToken(JdbcTokenStore.java:113)
at
...
Task
前述したように、問題の原因が確認され、特定された場合は、次の操作を続行します.
取引
まず、JNDIを使用しているときのWASのautoCommit属性がfalseの場合、トランザクションが行われていない場合はコミットできない場合があります.これらの状況を考慮して、トランザクション終了後にコミットするためにトランザクションノイズ(@Transactional)を追加することもできます.
public class JadeTokenService ... {
...
@Transacrional
public OAuth2AccessToken createAccessToken(...) throws AuthenticationException { ... }
@Transacrional
public OAuth2AccessToken refreshAccessToken(...) { ... }
...
}
PrimaryKeyの追加とレプリケーションExceptionの処理
UTHENTICATION IDはPKとして定義される.
/* 발급된 접근 토큰 */
CREATE TABLE OAUTH_ACCESS_TOKEN (
TOKEN_ID VARCHAR2(256), /* 토큰 아이디 */
TOKEN BLOB, /* 토큰 */
AUTHENTICATION_ID VARCHAR2(256) NOT NULL, /* 인증 아이디 */
USER_NAME VARCHAR2(256), /* 사용자 명 */
CLIENT_ID VARCHAR2(256), /* 클라이언트 아이디 */
AUTHENTICATION BLOB, /* 인증 정보 */
REFRESH_TOKEN VARCHAR2(256) /* 리프레시 토큰 */
);
CREATE UNIQUE INDEX PK_OAUTH_ACCESS_TOKEN
ON OAUTH_ACCESS_TOKEN (
AUTHENTICATION_ID ASC
);
ALTER TABLE OAUTH_ACCESS_TOKEN
ADD
CONSTRAINT PK_OAUTH_ACCESS_TOKEN
PRIMARY KEY (
AUTHENTICATION_ID
);
DuplicateExceptionが発生した場合、Tokenクエリが処理されます.
// https://github.com/spring-projects/spring-security-oauth/issues/502
public class EnsureTokenService extends JadeTokenService {
private static final Log LOG = LogFactory.getLog(EnsureTokenService.class);
@Override
@Transactional
public OAuth2AccessToken createAccessToken(OAuth2Authentication authentication) throws AuthenticationException {
try {
return super.createAccessToken(authentication);
}catch (DuplicateKeyException dke) {
LOG.info(String.format("Duplicate Primary Key(Authenticate ID) found for %s",authentication.getUserAuthentication().getPrincipal()));
return super.getAccessToken(authentication);
}catch (Exception ex) {
LOG.info(String.format("Exception while creating access token %s",ex));
}
return null;
}
}
Reference
この問題について(Duplicate Oauth2 AccessTokens Created), 我々は、より多くの情報をここで見つけました https://velog.io/@winn85/Duplicate-Oauth2-AccessTokens-Createdテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol