Tho*_*mas 5 spring-security spring-boot
我正在使用 Spring Boot 2.2.0.RELEASE,我的基于 Spring 的后端充当 OAuth2 资源服务器,在生产中运行良好。
我的所有 REST 端点都受到保护:
public class BookingController {
@PreAuthorize("hasAuthority('booking:WRITE')")
@PostMapping(value = "/book")
public ResponseEntity<Void> createBooking(@RequestBody BookModel bookModel, JwtAuthenticationToken jwt) {..}
Run Code Online (Sandbox Code Playgroud)
我想针对 REST API 编写一个单元测试,并且想模拟 JWT 令牌。
我尝试了以下操作,但总是收到“访问被拒绝的消息”
我的单元测试如下所示:
@WebMvcTest(controllers = BookingController.class)
public class BookingControllerTests {
@Autowired
private ObjectMapper objectMapper;
@Autowired
MockMvc mockMvc;
@MockBean
JwtDecoder jwtDecoder;
@Test
public void when_valid_booking_then_return_200() {
BookModel bookModel = new BookModel();
mockMvc
.perform(post("/book")
.with(jwt(jwt ->jwt().authorities(new SimpleGrantedAuthority("booking:WRITE"))))
.contentType("application/json")
.content(objectMapper.writeValueAsBytes(bookModel)))
.andExpect(status().isCreated());
}
Run Code Online (Sandbox Code Playgroud)
不知何故,mockMvc 中定义的声明被忽略。查看调试输出:
PrePostAnnotationSecurityMetadataSource : @org.springframework.security.access.prepost.PreAuthorize(value=hasAuthority('booking:WRITE')) found on specific method: public org.springframework.http.ResponseEntity BookingController.createBooking(BookModel ,org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken)
o.s.s.w.a.i.FilterSecurityInterceptor : Secure object: FilterInvocation: URL: /book; Attributes: [permitAll]
o.s.s.w.a.i.FilterSecurityInterceptor : Previously Authenticated: org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken@eca97305: Principal: org.springframework.security.oauth2.jwt.Jwt@bbd01fb9; Credentials: [PROTECTED]; Authenticated: true; Details: null; Granted Authorities: SCOPE_read
o.s.s.a.v.AffirmativeBased : Voter: org.springframework.security.web.access.expression.WebExpressionVoter@18907af2, returned: 1
o.s.s.w.a.i.FilterSecurityInterceptor : Authorization successful
o.s.s.w.a.i.FilterSecurityInterceptor : RunAsManager did not change Authentication object
o.s.s.w.FilterChainProxy : /book reached end of additional filter chain; proceeding with original chain
o.s.s.a.i.a.MethodSecurityInterceptor : Secure object: ReflectiveMethodInvocation: public org.springframework.http.ResponseEntity BookingController.createBooking(BookModel,org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken); target is of class [BookModel]; Attributes: [[authorize: 'hasAuthority('booking:WRITE')', filter: 'null', filterTarget: 'null']]
o.s.s.a.i.a.MethodSecurityInterceptor : Previously Authenticated: org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken@eca97305: Principal: org.springframework.security.oauth2.jwt.Jwt@bbd01fb9; Credentials: [PROTECTED]; Authenticated: true; Details: null; Granted Authorities: SCOPE_read
o.s.s.a.v.AffirmativeBased : Voter: org.springframework.security.access.prepost.PreInvocationAuthorizationAdviceVoter@67afe909, returned: -1
o.s.s.a.v.AffirmativeBased : Voter: org.springframework.security.access.vote.RoleVoter@79f1e22e, returned: 0
o.s.s.a.v.AffirmativeBased : Voter: org.springframework.security.access.vote.AuthenticatedVoter@6903ed0e, returned: 0
c.s.d.r.e.GlobalExceptionHandler : mapped AccessDeniedException to FORBIDDEN
org.springframework.security.access.AccessDeniedException: Access is denied
at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:84) ~[spring-security-core-5.2.0.RELEASE.jar:5.2.0.RELEASE]
Run Code Online (Sandbox Code Playgroud)
在用于模拟 JWT 的 lambda 中,您通过使用括号两次来调用后处理器两次.with(jwt(jwt ->jwt()...))
相反,尝试
mockMvc
.perform(post("/book")
.with(jwt().authorities(new SimpleGrantedAuthority("booking:WRITE"))))
Run Code Online (Sandbox Code Playgroud)
小智 0
如果您需要安全上下文,那么您就不是在编写单元测试。
无论如何,为什么不使用@WithMockUser?
在这里您可以看到如何在模拟业务层的集成测试中使用它的快照。
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ActiveProfiles("api")
public class GetAllProfilesControllerITest {
@MockBean
private GetAllProfilesDAO getAllProfilesDAO;
@MockBean
private ProfileControllerMapper profileControllerMapper;
@Inject
private WebApplicationContext context;
private MockMvc mockMvc;
private static final String ENDPOINT = "/profiles";
@Before
public void setUp() {
mockMvc = MockMvcBuilders.webAppContextSetup(context)
.apply(springSecurity())
.build();
}
@WithMockUser(authorities = "MINION")
@Test
public void should_returnUnauthorized_when_cantView() throws Exception {
//when
mockMvc.perform(get(ENDPOINT))
//then
.andExpect(status().isUnauthorized());
}
@WithMockUser(authorities = {"VIEW", "CREATE"})
@Test
public void should_returnOk_when_canView() throws Exception {
//when
mockMvc.perform(get(ENDPOINT))
//then
.andExpect(status().isOk());
}
@WithMockUser(authorities = "PUPPY")
@Test
public void should_returnOk_when_puppy() throws Exception {
//when
mockMvc.perform(get(ENDPOINT))
//then
.andExpect(status().isOk());
}
Run Code Online (Sandbox Code Playgroud)
}
| 归档时间: |
|
| 查看次数: |
11409 次 |
| 最近记录: |