skip to Main Content

I just want to add a @PreAuthorize("hasAuthority('ROLE_ADMIN')") and @PreAuthorize("hasAuthority('ROLE_USER')") in the methods of order controller and I also revise the controller test method after I define a login method in auth service in terms of User and Admin role.

After I add @PreAuthorize("hasAuthority('ROLE_USER')") of placeOrder method of controller, I revise its test method.

Here is the method of order controller

 @PreAuthorize("hasAuthority('ROLE_USER')")
 @PostMapping("/placeorder")
    public ResponseEntity<Long> placeOrder(@RequestBody OrderRequest orderRequest) {

        log.info("OrderController | placeOrder is called");

        log.info("OrderController | placeOrder | orderRequest: {}", orderRequest.toString());

        long orderId = orderService.placeOrder(orderRequest);
        log.info("Order Id: {}", orderId);
        return new ResponseEntity<>(orderId, HttpStatus.OK);
    }

Here is the example test method in ordercontrollertest in order service.

@Test
    @DisplayName("Place Order -- Success Scenario")
    void test_When_placeOrder_DoPayment_Success() throws Exception {

        OrderRequest orderRequest = getMockOrderRequest();
        String jwt = getJWTTokenForRoleUser();

        MvcResult mvcResult
                = mockMvc.perform(MockMvcRequestBuilders.post("/order/placeorder")
                        .contentType(MediaType.APPLICATION_JSON_VALUE)
                        .header("Authorization", "Bearer " + jwt)
                        .content(objectMapper.writeValueAsString(orderRequest)))
                .andExpect(MockMvcResultMatchers.status().isOk())
                .andReturn();

        String orderId = mvcResult.getResponse().getContentAsString();

        Optional<Order> order = orderRepository.findById(Long.valueOf(orderId));
        assertTrue(order.isPresent());

        Order o = order.get();
        assertEquals(Long.parseLong(orderId), o.getId());
        assertEquals("PLACED", o.getOrderStatus());
        assertEquals(orderRequest.getTotalAmount(), o.getAmount());
        assertEquals(orderRequest.getQuantity(), o.getQuantity());
    }

Here are the dependenices of order service regarding it.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-test</artifactId>
    <scope>test</scope>
</dependency>

How can I define the ROLE in this test method. I tried to use @WithMockUser(roles="USER") and @WithMockUser(roles="ADMIN") but it didn’t help me. (I got 403 Forbidden error.)

Edited ( I also tried to WebSecurityConfig in the service but it didn’t help me fix the issue. That’s why I removed it from the service.)

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig {

    @Bean
    public SecurityFilterChain securityWebFilterChain(HttpSecurity http) throws Exception {
        http
                .authorizeRequests(
                        authorizeRequest -> authorizeRequest
                                .anyRequest()
                                .authenticated());

        return http.build();
    }
}

Here is the example link : Link

Here is the test controller : Link

To run the app,
1 ) Run Service Registery (Eureka Server)

2 ) Run config server

3 ) Run zipkin and redis through these commands shown below on docker
docker run -d -p 9411:9411 openzipkin/zipkin
docker run -d –name redis -p 6379:6379 redis

4 ) Run api gateway

5 ) Run other services

2

Answers


  1. Add this configuration to test class :

    @EnableGlobalMethodSecurity(prePostEnabled = true)

    Login or Signup to reply.
  2. I might seem rude, but I’m tired to give you the solution to your problem (it’s the 3rd time already, and we would have both saved a lot of time if you had tried it the first time)

    FOLLOW THOSE TUTORIALS: https://github.com/ch4mpy/spring-addons/tree/master/samples/tutorials

    It will teach you how to (you obviously don’t know how to correctly do it):

    • configure your OAuth2 resource-servers
    • secure Spring @Components (@Controllers but also @Service and @Repository)
    • write unit tests for those components with mocked identities
    • write integration test for each micro-service with mocked identities

    @WithMockUser populates test security context with UsernamePasswordAuthenticationToken which is not adapted to OAuth2 resource-servers.

    Just follow the first 3 tutoriuals (for real: write the code and run the tests) and then refer to the sample best matching your particular use-case. It should take you less than an hour.

    Stop trying to build JWTs to set it as request header when working with MockMvc. Use either org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.jwt from spring-security-test or @WithMockJwtAuth from spring-addons-oauth2-test.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search