我有很多@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
示例都使用了更简单的表达式(没有安全上下文,即使开头没有@
)。
如何检查它的正确性?或者可能有更好的解决方案来解决这个问题?
答案 0 :(得分:0)
我最近必须写一个这样的测试用例answer another stack overflow question。
假设:
public class Foo {
public boolean isOk(String param) {
return "good".equals(param);
}
@PreAuthorize("@foo.isOk(#param1)")
public String bar(String param1) {
return "authOk";
}
}
以及@Configuration
:
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
}
}
将验证您的@PreAuthorize
SpEL。