我正在嘗試為應用程式端點實施授權。我正在使用@PreAuthorize注釋中的自定義方法。
@RestController
@RequestMapping("test")
@RequiredArgsConstructor
public class TestController {
private final TestService testService;
@GetMapping("/{userId}")
@ResponseStatus(HttpStatus.OK)
@PreAuthorize("@SecurityService.hasAccessToUser(#userId)")
List<TestDTO> getUserData(@PathVariable String userId) {
return testService.fetchUserData(userId);
}
}
旁注 - 下面介紹hasAccessToUser的方法可以通過簡單地使用來替換,@PreAuthorize("authorization.principal == #userId")但它只是 SecurityService 的精簡版本
@Service
@RequiredArgsConstructor
public class SecurityService {
private Authentication getAuthentication() {
return SecurityContextHolder.getContext().getAuthentication();
}
private String getUserId() {
return (String) getAuthentication().getPrincipal();
}
public boolean hasAccessToUser(String userId) {
return getUserId().equals(userId);
}
}
此授權實作在啟動的應用程式上運行良好,但在測驗時會中斷:
@WebMvcTest(TestController.class)
public class TestControllerTest {
private static final String BASE_URL = "/test";
@Autowired
private MockMvc mockMvc;
@MockBean
private TestService testService;
@MockBean
private SecurityService securityService;
@MockBean
private TestRepository testRepository;
@SneakyThrows
@Test
void shouldGetUserDataGivenUserId() {
mockMvc.perform(asUser(get(BASE_URL "/" TEST_USER_ID)))
.andExpect(status().is(Response.SC_OK));
verify(testService).fetchUserData(TEST_USER_ID);
}
}
當我查看對失敗請求的回應正文時,它有很長的日志以結尾:
Internal Server Error: Failed to evaluate expression '@SecurityService.hasAccessToUser(#userId)'"}]
at org.springframework.test.util.AssertionErrors.fail(AssertionErrors.java:59)
at org.springframework.test.util.AssertionErrors.assertEquals(AssertionErrors.java:122)
at org.springframework.test.web.servlet.result.ContentResultMatchers.lambda$string$4(ContentResultMatchers.java:148)
at org.springframework.test.web.servlet.MockMvc$1.andExpect(MockMvc.java:212)
at com.test.controller.TestControllerTest.shouldGetUserDataGivenUserId(TestControllerTest.java:87)
at java.base/java.util.ArrayList.forEach(Unknown Source)
@SecurityService因此,Spring在運行測驗時無法識別。在測驗期間有什么方法@SecurityService可以在里面作業嗎?@PreAuthorize
uj5u.com熱心網友回復:
該運算式@SecurityService.hasAccessToUser(#userId)將查找名稱為 的 bean SecurityService。但是您現在使用@MockBean來定義這個 bean,默認情況下它的 bean 名稱將自動生成。沒有名稱是豆類,SecurityService因此會引發此錯誤。
您可以通過以下方式顯式配置其 bean 名稱:
@MockBean(name="SecurityService")
private SecurityService securityService;
這應該可以解決您的問題。
但更好的是,不要模擬SecurityService,因為它是您的應用程式安全設定的一部分,而不是被測控制器的一種協作者或依賴項。使用真實實體可以使測驗用例更接近實際生產代碼。
@WebMvcTest(TestController.class)
@Import({TestController.Config.class})
public class TestControllerTest {
@Configuration
public static class Config {
@Bean(name="SecurityService")
public SecurityService securityService() {
return new SecurityService();
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/511709.html
標籤:爪哇春天弹簧安全弹簧测试
