java - 测试时忽略 Spring Controller 上的 PreAuthorize 注释

标签 java spring spring-security mockito junit4

我正在使用 JUnit、Mockito 和 spring-test 测试我的 Spring MVC Controller 。不幸的是,测试忽略了我的 Controller 方法上的 @PreAuthorize 注释,我一直无法解决这个问题。关键代码片段如下,尽管我已经从 MyController 的依赖项中删除了不相关的模拟响应逻辑以保持简短。我正在使用 Spring 3.2 和 JUnit 4,我正在通过 Maven 和直接通过 Eclipse 运行测试(运行方式 -> JUnit 测试)。

现在我预计 getAccounts_ReturnsOkStatus 测试会失败,因为我没有提供任何身份验证,并且/accounts 路由映射到的方法使用预身份验证注释进行注释,但是该方法正在调用并绕过预授权检查。

MyControllerTest.java

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:applicationContext-test.xml" })
public class MyControllerTest {

    private MockMvc mockMvc;

    @Mock
    private MyService myService;

    @InjectMocks
    private MyController myController;

    @Before
    public void init() {
        MockitoAnnotations.initMocks(this);  
        mockMvc = MockMvcBuilders.standaloneSetup(myController).build();
    }

   @Test
   public void getAccounts_ReturnsOkStatus() throws Exception {
       // Make the GET request, and verify that it returns HttpStatus.OK (200)
       mockMvc.perform(MockMvcRequestBuilders.get("/accounts"))
              .andExpect(MockMvcResultMatchers.status().isOk());
   }
}

applicationContext-test.xml

<sec:global-method-security pre-post-annotations="enabled" />
<bean id="applicationContextProvider" class="com.myapp.springsupport.ApplicationContextProvider" />

<sec:authentication-manager alias="authenticationManager">
   <sec:authentication-provider>
       <sec:user-service>
           <sec:user name="test-superuser" password="test-pwd" authorities="ROLE_SUPERUSER" />
       </sec:user-service>
   </sec:authentication-provider>
</sec:authentication-manager>

MyController.java

@PreAuthorize("isAuthenticated() and hasRole('ROLE_SUPERUSER')")
@RequestMapping(value = "/accounts", method = RequestMethod.GET)
@ResponseBody
public Collection<Account> getAccounts() {
    return new ArrayList<Account>();
}

肯定会使用 applicationContext-test 应用程序上下文,因为使用手动身份验证

Authentication auth = new UsernamePasswordAuthenticationToken(name, password);
SecurityContextHolder.getContext().setAuthentication(am.authenticate(auth));

仅适用于测试配置中指定的用户凭据(在没有任何其他身份验证提供程序的情况下)。此外,我可以确定预授权被忽略了,因为我已经使用 SEL 测试过调用方法并进行了调试。

我错过了什么?

最佳答案

构建mockMvc时必须启用spring security进行测试。

在 Spring 4 中是这样的:

mockMvc = MockMvcBuilders.webAppContextSetup(context)
                         .apply(springSecurity())
                         .build();

在 Spring 3 中是这样的:

@Autowired
private Filter springSecurityFilterChain;
...
mockMvc = MockMvcBuilders.webAppContextSetup(context)
                         .addFilters(springSecurityFilterChain)
                         .build();

更多细节见:

关于java - 测试时忽略 Spring Controller 上的 PreAuthorize 注释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42087496/

相关文章:

java - C、C++ 或 Objective-C 中的 System.arraycopy() 等效项

java - 替换任意长度的子串

java - 从 Spring JDBC 模板执行 SQL 文件

java - spring-boot 中存在多个 WebSecurityConfigurerAdapter 的问题

java - Spring中使用密码编码时用户登录失败

java - 向类 org.springframework.web.context.ContextLoaderListener 的监听器实例发送上下文初始化事件的异常

java - 在 Java 中写入数组

java - 从 Spring MVC 中的 Controller 操作重定向到外部 URL

spring - 如何在 Spring Security 3.2 中有问题地设置 Access-Control-Allow-Origin 过滤器

java - 使用扫描仪读取文本文件并使用列表进行打印