简体   繁体   中英

In Springboot Unit test, MockMvc returns 403 Forbidden

In Springboot unit Test always return 403 error,I've tried a variety of different configurations using AutoConfigureMockMvc with secure false and excluding security auto configuration getting 403 errror. Can anyone help me on this.

Here is my Security Implementation

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Resource(name = "userService")
    private UserDetailsService userDetailsService;

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Autowired
    public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationEventPublisher(authenticationEventPublisher())
                .userDetailsService(userDetailsService)
                .passwordEncoder(encoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf()
                .disable()
                .anonymous()
                .disable()
                .authorizeRequests()
                .antMatchers("/api-docs/**")
                .permitAll();
    }

    @Bean
    public DefaultAuthenticationEventPublisher authenticationEventPublisher() {
        return new DefaultAuthenticationEventPublisher();
    }

    @Bean
    public TokenStore tokenStore() {
        return new InMemoryTokenStore();
    }

    @Bean
    public BCryptPasswordEncoder encoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public FilterRegistrationBean corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");
        source.registerCorsConfiguration("/**", config);
        FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
        bean.setOrder(0);
        return bean;
    }
   }

Sharing Api Implementation Class, added PreAuthorize -Admin, to view all users

@RestController
@RequestMapping("/api/userInfo")
public class UserController {

    private final Logger LOG = Logger.getLogger(getClass());

    private String serviceMsg = "serviceMsg";

    @Autowired
    private UserService userService;

    @Autowired
    private UserServiceUtil util;

    
    @PreAuthorize("hasAnyRole('ADMIN')")
    @RequestMapping(method = RequestMethod.GET, produces = "application/json" )
    @ApiOperation(value = "Get details of all RA2 users in a paginated JSON format")
    public Page<User> listUser(Pageable pageable) {
        return userService.getUserSummary(pageable);
    }

And Here is my JUnit Test,am Sending get request and return 403 error.

@RunWith(SpringRunner.class)
@SpringBootTest
@ActiveProfiles("test")
@ContextConfiguration
@AutoConfigureMockMvc(addFilters = false)

public class UserControllerTest {
    
    @Configuration
    
    @EnableGlobalMethodSecurity(prePostEnabled = true)
    protected static class TestConfiguration {
         @Bean
         @Primary
         public UserService getUserService(){
               return Mockito.mock(UserService.class);
         }
         
         @Bean
         @Primary
         public UserServiceUtil getUserServiceUtil(){
               return Mockito.mock(UserServiceUtil.class);
         }
    }
    @Autowired
    private MockMvc mockMvc;
    
    @Autowired
    private WebApplicationContext webApplicationContext ;

    
    
    private String serviceMsg = "serviceMsg";

    @Autowired
    private UserService userService;

    @Autowired
    private UserServiceUtil util;
    
    private User admin;
    private User user;
    
    @Before
    public void setup() {

        mockMvc = MockMvcBuilders.webAppContextSetup(this.webApplicationContext ).apply(springSecurity()).build();
        }

    @WithMockUser(username = "test",authorities ="ADMIN")
    @Test
    public void getuserList() throws Exception {
        List<User> list = new ArrayList<User>();
        list.add(new User());
        Page<User> page = new PageImpl<User>(list, null, list.size());
        Mockito.when(userService.getUserSummary(any(Pageable.class))).thenReturn(page);
        this.mockMvc.perform(get("/api/userInfo?page=1&size=10").with(csrf()).contentType(MediaType.APPLICATION_JSON)).
        andExpect(status().isOk()).andDo(MockMvcResultHandlers.print());
      }
    ```

There is a difference between authorities and roles when you use @WithMockUser :

/**
 * <p>
 * The roles to use. The default is "USER". A {@link GrantedAuthority} will be created
 * for each value within roles. Each value in roles will automatically be prefixed
 * with "ROLE_". For example, the default will result in "ROLE_USER" being used.
 * </p>
 * <p>
 * If {@link #authorities()} is specified this property cannot be changed from the
 * default.
 * </p>
 * @return
 */
String[] roles() default { "USER" };

/**
 * <p>
 * The authorities to use. A {@link GrantedAuthority} will be created for each value.
 * </p>
 *
 * <p>
 * If this property is specified then {@link #roles()} is not used. This differs from
 * {@link #roles()} in that it does not prefix the values passed in automatically.
 * </p>
 * @return
 */
String[] authorities() default {};

Whatever you set with authorities does not get any prefix.

As your controller expects ROLE_ADMIN , try using roles instead.

In addition to this, I would also try to use a sliced Spring Context using @WebMvcTest for this test. Starting the whole Spring Context using @SpringBootTest is not required for such tests.

Removed @SpringBootTest and added @WebMvcTest and roles, but getting 403.


@RunWith(SpringRunner.class)
@WebMvcTest(controllers = UserController.class)
@ActiveProfiles("test")
@ContextConfiguration
@AutoConfigureMockMvc(addFilters = false)

public class UserControllerTest {
    
    @Configuration
    
    @EnableGlobalMethodSecurity(prePostEnabled = true)
    protected static class TestConfiguration {
         @Bean
         @Primary
         public UserService getUserService(){
               return Mockito.mock(UserService.class);
         }
         
         @Bean
         @Primary
         public UserServiceUtil getUserServiceUtil(){
               return Mockito.mock(UserServiceUtil.class);
         }
    }
    @Autowired
    private MockMvc mockMvc;
    
    @Autowired
    private WebApplicationContext wac;

    @Autowired
    private UserService userService;

    @Autowired
    private UserServiceUtil util;

    
    @Before
    public void setup() {

        mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).apply(springSecurity()).build();
           }
    @WithMockUser(username = "Ram",roles ="ADMIN")
    @Test
    public void getuserList() throws Exception {
        List<User> list = new ArrayList<User>();
        Page<User> page = new PageImpl<User>(list, null, list.size());
        Mockito.when(userService.getUserSummary(any(Pageable.class))).thenReturn(page);
        this.mockMvc.perform(get("/api/userInfo?page=1&size=10").with(csrf()).contentType(MediaType.APPLICATION_JSON)).
        andExpect(status().isOk()).andDo(MockMvcResultHandlers.print());
      }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM