[SPRING] Spring OAuth2 토큰 엔드 포인트에 대한 요청 당 액세스 토큰 생성
SPRINGSpring OAuth2 토큰 엔드 포인트에 대한 요청 당 액세스 토큰 생성
요청 당 client_credentials 또는 password 부여 유형을 사용하여 여러 유효한 액세스 토큰을 생성 할 수 있습니까?
위의 부여 유형을 사용하여 토큰을 생성하면 현재 요청이 요청마다 만료되면 새 토큰 만 제공됩니다.
비밀번호 부여 유형을 사용하여 새로 고침 토큰을 생성 한 다음 여러 액세스 토큰을 생성 할 수 있지만이를 수행하면 이전 액세스 토큰이 무효화됩니다.
어떻게하면 액세스 토큰이 / oauth / 토큰 끝점에 대한 요청마다 생성되고 이전 토큰이 무효화되지 않도록 할 수 있도록 변경 될 수 있습니까?
아래는 oauth 서버의 XML 설정입니다.
<!-- oauth2 config start-->
<sec:http pattern="/test/oauth/token" create-session="never"
authentication-manager-ref="authenticationManager" >
<sec:intercept-url pattern="/test/oauth/token" access="IS_AUTHENTICATED_FULLY" />
<sec:anonymous enabled="false" />
<sec:http-basic entry-point-ref="clientAuthenticationEntryPoint"/>
<sec:custom-filter ref="clientCredentialsTokenEndpointFilter" before="BASIC_AUTH_FILTER" />
<sec:access-denied-handler ref="oauthAccessDeniedHandler" />
</sec:http>
<bean id="clientCredentialsTokenEndpointFilter"
class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
<property name="authenticationManager" ref="authenticationManager" />
</bean>
<sec:authentication-manager alias="authenticationManager">
<sec:authentication-provider user-service-ref="clientDetailsUserService" />
</sec:authentication-manager>
<bean id="clientDetailsUserService"
class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<constructor-arg ref="clientDetails" />
</bean>
<bean id="clientDetails" class="org.security.oauth2.ClientDetailsServiceImpl"></bean>
<bean id="clientAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="springsec/client" />
<property name="typeName" value="Basic" />
</bean>
<bean id="oauthAccessDeniedHandler"
class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler"/>
<oauth:authorization-server
client-details-service-ref="clientDetails" token-services-ref="tokenServices">
<oauth:authorization-code />
<oauth:implicit/>
<oauth:refresh-token/>
<oauth:client-credentials />
<oauth:password authentication-manager-ref="userAuthenticationManager"/>
</oauth:authorization-server>
<sec:authentication-manager id="userAuthenticationManager">
<sec:authentication-provider ref="customUserAuthenticationProvider">
</sec:authentication-provider>
</sec:authentication-manager>
<bean id="customUserAuthenticationProvider"
class="org.security.oauth2.CustomUserAuthenticationProvider">
</bean>
<bean id="tokenServices"
class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
<property name="tokenStore" ref="tokenStore" />
<property name="supportRefreshToken" value="true" />
<property name="accessTokenValiditySeconds" value="300"></property>
<property name="clientDetailsService" ref="clientDetails" />
</bean>
<bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.store.JdbcTokenStore">
<constructor-arg ref="jdbcTemplate" />
</bean>
<bean id="jdbcTemplate"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/oauthdb"/>
<property name="username" value="root"/>
<property name="password" value="password"/>
</bean>
<bean id="oauthAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
</bean>
해결법
-
==============================
1.다시 확인해 보면 InMemoryTokenStore가 OAuth2Authentication의 해시 문자열을 serveral Map의 키로 사용함을 발견했습니다. 그리고 같은 username, client_id, scope를 사용할 때 같은 키를 얻었습니다. 그래서 이것은 어떤 문제를 야기 할 수 있습니다. 그래서 저는 옛날 방식이 더 이상 사용되지 않을 것이라고 생각합니다. 다음은 내가이 문제를 피하기 위해 한 일이다.
다시 확인해 보면 InMemoryTokenStore가 OAuth2Authentication의 해시 문자열을 serveral Map의 키로 사용함을 발견했습니다. 그리고 같은 username, client_id, scope를 사용할 때 같은 키를 얻었습니다. 그래서 이것은 어떤 문제를 야기 할 수 있습니다. 그래서 저는 옛날 방식이 더 이상 사용되지 않을 것이라고 생각합니다. 다음은 내가이 문제를 피하기 위해 한 일이다.
UniqueAuthenticationKeyGenerator라는 고유 키를 계산할 수있는 다른 AuthenticationKeyGenerator를 만듭니다.
/* * Copyright 2006-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ /** * Basic key generator taking into account the client id, scope, resource ids and username (principal name) if they * exist. * * @author Dave Syer * @author thanh */ public class UniqueAuthenticationKeyGenerator implements AuthenticationKeyGenerator { private static final String CLIENT_ID = "client_id"; private static final String SCOPE = "scope"; private static final String USERNAME = "username"; private static final String UUID_KEY = "uuid"; public String extractKey(OAuth2Authentication authentication) { Map<String, String> values = new LinkedHashMap<String, String>(); OAuth2Request authorizationRequest = authentication.getOAuth2Request(); if (!authentication.isClientOnly()) { values.put(USERNAME, authentication.getName()); } values.put(CLIENT_ID, authorizationRequest.getClientId()); if (authorizationRequest.getScope() != null) { values.put(SCOPE, OAuth2Utils.formatParameterList(authorizationRequest.getScope())); } Map<String, Serializable> extentions = authorizationRequest.getExtensions(); String uuid = null; if (extentions == null) { extentions = new HashMap<String, Serializable>(1); uuid = UUID.randomUUID().toString(); extentions.put(UUID_KEY, uuid); } else { uuid = (String) extentions.get(UUID_KEY); if (uuid == null) { uuid = UUID.randomUUID().toString(); extentions.put(UUID_KEY, uuid); } } values.put(UUID_KEY, uuid); MessageDigest digest; try { digest = MessageDigest.getInstance("MD5"); } catch (NoSuchAlgorithmException e) { throw new IllegalStateException("MD5 algorithm not available. Fatal (should be in the JDK)."); } try { byte[] bytes = digest.digest(values.toString().getBytes("UTF-8")); return String.format("%032x", new BigInteger(1, bytes)); } catch (UnsupportedEncodingException e) { throw new IllegalStateException("UTF-8 encoding not available. Fatal (should be in the JDK)."); } } }
마지막으로,
<bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.store.JdbcTokenStore"> <constructor-arg ref="jdbcTemplate" /> <property name="authenticationKeyGenerator"> <bean class="your.package.UniqueAuthenticationKeyGenerator" /> </property> </bean>
from https://stackoverflow.com/questions/27020702/spring-oauth2-generate-access-token-per-request-to-the-token-endpoint by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] 스프링 자바 설정을 사용하여 싱글 톤 빈으로 프로토 타입 객체 생성하기 (0) | 2019.01.02 |
---|---|
[SPRING] JsonMappingException : 프록시를 초기화 할 수 없습니다 - 세션 없음 (0) | 2019.01.02 |
[SPRING] JSR-303 의존성 주입 및 절전 (0) | 2019.01.02 |
[SPRING] 복합 ID가있는 엔티티에 대한 HATEOAS 링크 생성 사용자 정의 (0) | 2019.01.02 |
[SPRING] 스프링 데이터 (JPA) 저장소를 계측 / 조언하는 방법은 무엇입니까? (0) | 2019.01.02 |