2017-07-04 23 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幫助我以更清晰的方式處理這個問題。

我們可以使用靜態assertThatThrownBy(斷言類的)方法。該方法返回一個AbstractThrowableAssert對象,我們可以使用它來爲引發的異常編寫斷言。

捕獲由methodThatThrowsException()方法拋出的異常的代碼如下:

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

由於this優秀的博客,你可以找到更多的細節。

中,我處理了這個在我的測試情況下,將(通過採取測試用例代碼行)的方式:

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

這樣,你的測試用例就能夠斷言實際AccessDeniedException異常嵌套在NestedServletException 。

相關問題