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

时间:2017-10-31 22:53:14

标签: java spring spring-security annotations spring-el

我有很多@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示例都使用了更简单的表达式(没有安全上下文,即使开头没有@)。

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

1 个答案:

答案 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。