我们有测试安全性表达式有效性的问题。
在测试中,我们使用的是unsecured
配置文件,这意味着方法安全性已禁用。这是在项目开始时完成的,以加快测试速度,因为当时很难生成正确的(权限方面的)数据。我们还有一个启用安全性的标准测试配置文件,用于单独的“安全性”测试。
开发人员可能会重构某些内容(即方法中的参数名称),却忽略了更新权限表达式的情况。并不常见,但这仍然是错误的根源。
我的想法是在启动时扫描所有方法,并寻找带有PreAuthorize("hasPermission(...))
批注的方法,然后将SpelExpressionParser
与正确的MethodInvocation
一起使用以验证权限表达式在正确的EvaluationContext
中。不幸的是,我到达PreInvocationExpressionAttribute
这是一个受程序包保护的类-这意味着我的解决方案或背后的意图根本不是框架所支持的。
请牢记以下要求:
该应用程序仍然具有多个旧组件,这使得难以设置适当的身份验证上下文(由于数据库约束,因为大多数域测试都是使用嵌入式DB的集成测试),
为所有案例编写测试是不现实的,因为已经有许多具有单独权限的角色(并且还会有更多角色),这将需要重复许多行代码
理想情况下,该解决方案将获得可用的安全角色列表,并验证只有正确的角色才能做到,并且表达式有效,
透明地实现权限表达式有效性检查的一些好方法,而对于编写测试的开发人员却没有太多开销?
答案 0 :(得分:2)
Spring为您提供了这样的工具(see @WithMockUser
, @WithAnonymousUser
, @WithUserDetails
),这些注释只需要创建应用程序上下文并将适当的注释添加到您的测试方法中,就可以使用正常测试来测试安全级别:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class WithMockUserTests {
@Test
@WithMockUser(username="admin",roles={"USER","ADMIN"})
public void getMessageWithMockUserCustomUser() {
String message = messageService.getMessage();
...
}
}
,如果您要测试的代码使用的是@PreAuthorize ...
方法或SecurityContextHolder.getContext()
,则将为您提供在注释中指定的用户。
如果存在一些复杂的安全流程,您还可以创建SecurityContextFactory
并使用@WithSecurityContext
进行测试。
您也可以将这种方法与嘲笑Mvc Run unit tests on controllers that require authentication一起使用。
但是,如果要在没有Spring的测试工具(例如MockMvc
...)的情况下测试应用程序,例如。使用RestTemplate
或RestAssure
,则最好的方法是破坏测试中的安全配置并使用新配置中的用户
@TestConfiguration
@Order(1)
@EnableGlobalMethodSecurity(prePostEnabled=true)
static class TestSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http....
}
}