2017-07-04 9 views
1

私は@PreAuthorize(#oauth2.hasScope('scope')で保護されているいくつかのエンドポイントのセキュリティ設定をテストしようとしています。必要な範囲を持っていないアクセストークンとポストマンを経て、このようなエンドポイントにアクセスすると、次のHTTPステータスコード403(禁じられた)で返されます。SpringエンドポイントをテストするときにNestedServletExceptionを防止する方法は?

{ 
    "error": "insufficient_scope", 
    "error_description": "Insufficient scope for this resource", 
    "scope": "scope" 
} 

私が欲しい予期された動作です。

この設定をテストしようとすると、スプリングNestedServletExceptionが私のテストケースを妨害して、予期した結果が得られません。

これは私がテストしたいコントローラの簡易版である:

@RestController 
@RequestMapping(value = "/api") 
public class OauthTestingResource { 

    @PreAuthorize(#oauth2.hasScope('scope')) 
    @RequestMapping(value = "/scope", method = RequestMethod.GET) 
    public void endpoint() { 
     // ... 
    } 
} 

そして、これは、対応するテストケースである:スローされ

@RunWith(SpringJUnit4ClassRunner.class) 
@SpringBootTest(classes = MyApplication.class) 
@WebAppConfiguration 
public class AuthorizationTest { 

    @Autowired 
    protected WebApplicationContext webApplicationContext; 

    protected SecurityContext securityContext = Mockito.mock(SecurityContext.class); 

    @Before 
    public void setup() throws Exception { 

     this.mvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build(); 
     SecurityContextHolder.setContext(securityContext); 
    } 

    protected Authentication createMockAuth(Client client) { 

     final List<GrantedAuthority> authorities = new ArrayList<>(); 
     authorities.add(new SimpleGrantedAuthority("ROLE_USER")); 

     final Authentication pwAuth = new UsernamePasswordAuthenticationToken("testuser", "testpw", authorities); 

     final TokenRequest request = new TokenRequest(new HashMap<>(), client.getClientId(), client.getScopes(), "password"); 

     final OAuthClient oauthClient = new OAuthClient(client, GrantType.PASSWORD); 

     return new OAuth2Authentication(request.createOAuth2Request(oauthClient), pwAuth); 
    } 
    @Test 
    public void testAppScope() throws Exception { 

     final Client client = new Client("id1", "secret1"); 

     client.setScope("scope"); 
     Mockito.when(securityContext.getAuthentication()).thenReturn(createMockAuth(client)); 
     // this test passes 
     mvc.perform(get("/api/scope")).andExpect(status().isOk()); 

     client.setScope("other_scope"); 
     Mockito.when(securityContext.getAuthentication()).thenReturn(createMockAuth(client)); 
     // NestedServletException thrown here 
     mvc.perform(get("/api/scope")).andExpect(status().isForbidden()); 
    } 
} 

例外はある(以下れます期待通り):

org.springframework.web.util.NestedServletException:リクエスト プロセス失敗しました。私の質問は、私は私のテストケースとの干渉からこの例外を防ぐことができる方法あるこのリソースの 不十分な範囲

:ネストされた例外は org.springframework.security.access.AccessDeniedExceptionのですか?

答えて

2

これは、linkに準拠して春のセキュリティテストケースを行いました。 NestedServletExceptionの元の例外を入れ子にするというこの問題を除いて、問題なく動作しました。 これを理解するための直接的な方法は見つかりませんでしたが、AspectJはこれをよりきれいな方法で処理するのを助けました。

Assertionsクラスのstatic assertThatThrownBy()メソッドを使用できます。このメソッドは、スローされた例外のアサーションを書き込むために使用できるAbstractThrowableAssertオブジェクトを返します。あなたは追加の詳細を見つけることができますthis優れたブログに

assertThatThrownBy(() -> methodThatThrowsException()) 
.isExactlyInstanceOf(DuplicateEmailException.class); 

感謝を次のように

methodThatThrowsException()メソッドによってスローされた例外をキャプチャコードが見えます。

私は(あなたのテストケースのコードラインを取ることによって)になります私のテストケースでこれを扱っする方法:

org.assertj.core.api.Assertions.assertThatThrownBy(() -> mvc.perform(get("/api/scope")).andExpect(status().isOk())).hasCause(new AccessDeniedException("Access is denied")); 

NestedServletExceptionにネストされたテストケースは、実際のAccessDeniedExceptionを主張することができるだろうその方法。

関連する問題