Spring @WithMockUser and request.IsUserInRole()



我正在使用:

request.IsUserInRole("ADMIN")

在我的一个控制器中确定对请求的响应。我试着在测试中模仿这个请求,比如:

@Mock
private HttpServletRequest httpRequest;

并使用Springs注释@WithMockUser:

@Test
@WithMockUser(roles={"USER, ADMIN"})
public void getAccountsTest() throws Exception {...}

两者都不起作用。

问题1:如何在JUnit测试中模拟request.IsUserInRole("ADMIN")

问题2:@WithMockUser对请求和request.IsUserInRole("ADMIN")有什么影响?

感谢

----编辑----

"不起作用"意味着我有一个测试方法:

@Test
@WithMockUser(username = "user", roles={"USER"})
public void getAccountsReturnForbiddenTest() throws Exception {
    mockMvc.perform(get("/accounts/"))
        .andExpect(status().isForbidden());
}

应该返回403,由于控制器的原因不允许:

@RequestMapping(method=RequestMethod.GET)
@PreAuthorize("hasRole('ADMIN')")
public ResponseEntity<PagedResources<AccountResource>> getAccounts(...){...}

但是请求返回200,好的。

我使用的是Spring Boot 1.4.1。

----编辑2-

我的JUnit测试类:

@Transactional
@ContextConfiguration
public class AccountControllerTestDoc extends AbstractControllerTest {
    @InjectMocks
    private AccountController accountController;
    @Mock
    private AccountService accountService;
    private String uriBase = ""; 
    @Before
    public void setup() {
        // Initialize Mockito annotated components
        MockitoAnnotations.initMocks(this);
        // Prepare the Spring MVC Mock components for standalone testing
        setup(accountController);
    }
    @Test
    @WithMockUser(username = "user", roles={"USER"})
    public void getAccountsReturnForbiddenTest() throws Exception {
        String uri = uriBase + "/accounts";
        mockMvc.perform(get(uri))
            .andExpect(status().isForbidden());
    }
}

使用AbstractControllerTest:

@WebAppConfiguration
public abstract class AbstractControllerTest extends AbstractTest  {
    protected MockMvc mockMvc;
    @Autowired
    protected WebApplicationContext wac;
    protected void setup() {
        mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
    }
    protected void setup(BaseController controller) {
        mockMvc = MockMvcBuilders.standaloneSetup(controller))
                .build();
    }
}

和AbstractTest:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public abstract class AbstractTest {
    protected Logger LOG = LoggerFactory.getLogger(this.getClass());
}

----解决方案----

MockMvc standaloneSetup不知道web应用程序上下文,因此不知道安全过滤器链。必须使用web应用程序上下文和安全过滤器链设置MockMvc,才能测试安全方面。

这是我现在正在工作的解决方案,我编辑了AbstractControllerTest:

@WebAppConfiguration
public abstract class AbstractControllerTest extends AbstractTest  {
    protected MockMvc mockMvc;
    @Autowired
    protected WebApplicationContext wac;
    @Autowired
    FilterChainProxy springSecurityFilterChain;
    protected void setup() {
        mockMvc = MockMvcBuilders
            .webAppContextSetup(wac)
            .addFilters(springSecurityFilterChain)
            .build();
    }
    protected void setup(BaseController controller) {
        mockMvc = MockMvcBuilders.standaloneSetup(controller))
                .build();
    }
}

您应该在创建MockMvc 时添加springSecurityFilterChain

protected MockMvc mockMvc;
@Autowired
protected WebApplicationContext wac;
@Autowired
protected Filter springSecurityFilterChain;
protected void setup() {
    mockMvc = MockMvcBuilders
   .webAppContextSetup(wac)
   .addFilters(springSecurityFilterChain)
   .build();
}
@Test
@WithMockUser(username="xx", roles= {"TIMESHEET"})
public void createNew() throws FailingHttpStatusCodeException, MalformedURLException, IOException {
    
    assertTrue(Constants.isUserInRole("ROLE_TIMESHEET"), "user not in correct role");

其中Constants.isUserInRole定义为

public static Boolean isUserInRole(String role) {
    return Optional.ofNullable(SecurityContextHolder.getContext().getAuthentication()).map(x->x.getAuthorities()).get()
            .stream().anyMatch(x->x.getAuthority().equals(role));
}

然后使用此isUserInRole而不是request.isUserInRole.

相关内容

  • 没有找到相关文章

最新更新