oAuth2 리소스 서버 애플리케이션 내에서 @WithMock 사용자(@SpringBootTest 포함) 사용
환경:여러 인프라 서비스와 리소스 서비스(비즈니스 로직 포함)로 구성된 스프링 부트 기반 마이크로서비스 아키텍처 애플리케이션을 보유하고 있습니다.권한 부여 및 인증은 사용자 엔티티를 관리하고 클라이언트에 대한 JWT 토큰을 생성하는 oAuth2-Service에 의해 처리됩니다.
단일 마이크로서비스 애플리케이션 전체를 테스트하기 위해 testNG, spring.boot.test, org.springframework로 테스트를 구축하려고 했습니다.보안.테스트...
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK, properties = {"spring.cloud.discovery.enabled=false", "spring.cloud.config.enabled=false", "spring.profiles.active=test"})
@AutoConfigureMockMvc
@Test
public class ArtistControllerTest extends AbstractTestNGSpringContextTests {
@Autowired
private MockMvc mvc;
@BeforeClass
@Transactional
public void setUp() {
// nothing to do
}
@AfterClass
@Transactional
public void tearDown() {
// nothing to do here
}
@Test
@WithMockUser(authorities = {"READ", "WRITE"})
public void getAllTest() throws Exception {
// EXPECT HTTP STATUS 200
// BUT GET 401
this.mvc.perform(get("/")
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
}
}
여기서 보안(리소스 서버) 구성은 다음과 같습니다.
@Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
// get the configured token store
@Autowired
TokenStore tokenStore;
// get the configured token converter
@Autowired
JwtAccessTokenConverter tokenConverter;
/**
* !!! configuration of springs http security !!!
*/
@Override
public void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/**").authenticated();
}
/**
* configuration of springs resource server security
*/
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
// set the configured tokenStore to this resourceServer
resources.resourceId("artist").tokenStore(tokenStore);
}
}
컨트롤러 클래스 내부에 주석이 달린 다음 방법 기반 보안 검사
@PreAuthorize("hasAuthority('READ')")
@RequestMapping(value = "/", method = RequestMethod.GET)
public List<Foo> getAll(Principal user) {
List<Foo> foos = fooRepository.findAll();
return foos;
}
그게 될 줄 알았는데 테스트를 실행할 때 어설션 오류만 발생합니다.
java.lang.AssertionError: Status
Expected :200
Actual :401
질문:제가 잘못하고 있다는 것이 완전히 명백한 것이 있습니까?또는 @WithMock 사용자가 @SpringBoot과 함께 작동하지 않을 것입니다.oAuth2 환경에서 테스트 및 @AutoConfigureMockMvc?이런 경우라면...이와 같은 (통합) 테스트의 일부로 경로 및 방법 기반 보안 구성을 테스트하기 위한 가장 좋은 접근 방식은 무엇입니까?
부록: 저는 다음과 같은 다양한 접근법을 시도했습니다.하지만 그것은 같은 결과로 이어졌습니다 :(
this.mvc.perform(get("/")
.with(user("admin").roles("READ","WRITE").authorities(() -> "READ", () -> "WRITE"))
.accept(MediaType.APPLICATION_JSON))
@WithMockUserSecurityContext에 인증을 만듭니다.에도 동일하게 적용됩니다.with(user("username")).
기본적으로 OAuth2Auth2AuthenticationProcessingFilter는 SecurityContext를 사용하지 않지만 항상 토큰("상태 비저장")에서 인증을 작성합니다.
리소스 서버 보안 구성에서 상태 비저장 플래그를 false로 설정하면 이 동작을 쉽게 변경할 수 있습니다.
@Configuration
@EnableResourceServer
public class ResourceServerConfiguration implements ResourceServerConfigurer {
@Override
public void configure(ResourceServerSecurityConfigurer security) throws Exception {
security.stateless(false);
}
@Override
public void configure(HttpSecurity http) {}
}
다른 옵션은 ResourceServerConfigurerAdapter를 확장하는 것이지만 문제는 모든 요청을 인증하도록 강제하는 구성이 제공된다는 것입니다.인터페이스를 구현하면 상태 비저장과 별도로 기본 보안 구성이 변경되지 않습니다.
물론 테스트 컨텍스트에서만 플래그를 false로 설정합니다.
저는 동일한 문제가 있었고, 토큰을 만들어 모의 MVC 수행에 사용하는 방법밖에 없었습니다.
mockMvc.perform(get("/resource")
.with(oAuthHelper.bearerToken("test"))
그리고 OA의 조력자:
@Component
@EnableAuthorizationServer
public class OAuthHelper extends AuthorizationServerConfigurerAdapter {
@Autowired
AuthorizationServerTokenServices tokenservice;
@Autowired
ClientDetailsService clientDetailsService;
public RequestPostProcessor bearerToken(final String clientid) {
return mockRequest -> {
OAuth2AccessToken token = createAccessToken(clientid);
mockRequest.addHeader("Authorization", "Bearer " + token.getValue());
return mockRequest;
};
}
OAuth2AccessToken createAccessToken(final String clientId) {
ClientDetails client = clientDetailsService.loadClientByClientId(clientId);
Collection<GrantedAuthority> authorities = client.getAuthorities();
Set<String> resourceIds = client.getResourceIds();
Set<String> scopes = client.getScope();
Map<String, String> requestParameters = Collections.emptyMap();
boolean approved = true;
String redirectUrl = null;
Set<String> responseTypes = Collections.emptySet();
Map<String, Serializable> extensionProperties = Collections.emptyMap();
OAuth2Request oAuth2Request = new OAuth2Request(requestParameters, clientId, authorities,
approved, scopes, resourceIds, redirectUrl, responseTypes, extensionProperties);
User userPrincipal = new User("user", "", true, true, true, true, authorities);
UsernamePasswordAuthenticationToken authenticationToken =
new UsernamePasswordAuthenticationToken(userPrincipal, null, authorities);
OAuth2Authentication auth = new OAuth2Authentication(oAuth2Request, authenticationToken);
return tokenservice.createAccessToken(auth);
}
@Override
public void configure(final ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("test")
.authorities("READ");
}
}
특히 ResourceServerConfiguration에 대한 테스트를 작성하려고 할 때 security.stateless를 false로 설정하는 테스트 래퍼를 만들어 문제를 해결했습니다.
@Configuration
@EnableResourceServer
public class ResourceServerTestConfiguration extends ResourceServerConfigurerAdapter {
private ResourceServerConfiguration configuration;
public ResourceServerTestConfiguration(ResourceServerConfiguration configuration) {
this.configuration = configuration;
}
@Override
public void configure(ResourceServerSecurityConfigurer security) throws Exception {
configuration.configure(security);
security.stateless(false);
}
@Override
public void configure(HttpSecurity http) throws Exception {
configuration.configure(http);
}
}
언급URL : https://stackoverflow.com/questions/41824885/use-withmockuser-with-springboottest-inside-an-oauth2-resource-server-applic
'source' 카테고리의 다른 글
| Excel의 다른 워크북을 상대적으로 참조하려면 어떻게 해야 합니까? (0) | 2023.07.16 |
|---|---|
| 데코레이터실행순서 (0) | 2023.07.16 |
| Null이 아닐 경우 입력 매개 변수를 확인하고 SQL Server의 위치에서 사용 (0) | 2023.07.16 |
| R의 숫자에 대한 쉼표 구분 기호? (0) | 2023.07.16 |
| x-Application-Context 헤더란 무엇입니까? (0) | 2023.07.16 |