如何测试带有自定义bean spel的@PreAuthorize是否有效



我有很多@RestController,它们的方法如下:

@PreAuthorize("@myBean.myMethod(#param1, #param2)")
public void foo(String param1, Long param2) {}

在某个地方

@Component
public class MyBean {
public boolean myMethod(String param1, Long param2) {
return importantSecurityCheck();
}
}

它工作得很好我想避免重构后可能出现的愚蠢错误(因为据我所知,spring在调用方法之前不会检测到错误),所以我的想法是编写测试,检查表达式是否有效(例如,参数具有相同的类型和名称)。

我试着做这样的事情:

@Test
public void checkSecurityExpressions() {
Map<String, Object> beansWithAnnotation = applicationContext.getBeansWithAnnotation(RestController.class);
beansWithAnnotation.forEach((name, bean) -> {
Method[] methods = AopUtils.getTargetClass(bean).getMethods();
for (Method method : methods) {
PreAuthorize annotation = method.getAnnotation(PreAuthorize.class);
if (annotation != null) {
String securityExpression = annotation.value();
System.out.println(securityExpression);
}
}
});
}

它可以很好地找到表达式,但我发现的所有ExpressionParser示例都可以使用更简单的表达式(没有安全上下文,甚至一开始没有@)。

如何检查它的正确性?或者也许有更好的解决方案来解决这个问题?

我最近不得不写一个这样的测试用例来回答另一个堆栈溢出问题。

给定:

public class Foo {
public boolean isOk(String param) {
return "good".equals(param);
}
@PreAuthorize("@foo.isOk(#param1)")
public String bar(String param1) {
return "authOk";
}
}

以及测试CCD_ 4类extends GlobalAuthenticationConfigurerAdapter:

@Override
public void init(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("foo").password("bar").roles("admin");
}

然后:

@Autowired
private Foo foo;
@Test
public void test() {
SecurityContext ctx = SecurityContextHolder.createEmptyContext();
ctx.setAuthentication(new UsernamePasswordAuthenticationToken("foo", "bar"));
SecurityContextHolder.setContext(ctx);
assertThat(foo.bar("good")).isEqualTo("authOk");
try {
foo.bar("bad");
fail("Expected AccessDeniedException");
}
catch (AccessDeniedException e) {
// expected
}
}

将验证您的@PreAuthorizeSpEL。

最新更新