2017-10-31 4 views
1

Ich habe ein viele @RestController s mit Methoden wie:Wie testen, ob @ PreAuthorize mit benutzerdefinierten Bean-Spel gültig ist?

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

Und irgendwo

@Component 
public class MyBean { 
    public boolean myMethod(String param1, Long param2) { 

     return importantSecurityCheck(); 
    } 
} 

Es funktioniert sehr gut, aber ich möglich dumme Fehler nach Refactoring vermeiden wollen (weil als soweit ich weiß, erkennt spring keinen fehler, bis die methode aufgerufen wird. also war es meine idee, einen test zu schreiben, der überprüft, ob der Ausdruck gültig ist (zB haben Parameter denselben typ und dieselben Namen sind gültig).

Ich habe versucht, so etwas zu tun:

@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); 
      } 

     } 
    }); 
} 

Welche Ausdrücke schön, aber alle ExpressionParser Beispiele, die ich mit der Arbeit mit einfacher Ausdrücke gefunden findet (ohne Sicherheitskontext, auch ohne @ am Anfang).

Wie überprüft man die Korrektheit? Oder gibt es vielleicht bessere Lösungen für dieses Problem?

Antwort

0

Ich musste einen solchen Testfall kürzlich auf answer another stack overflow question schreiben.

public class Foo { 

    public boolean isOk(String param) { 
     return "good".equals(param); 
    } 

    @PreAuthorize("@foo.isOk(#param1)") 
    public String bar(String param1) { 
     return "authOk"; 
    } 

} 

und ein Test @Configuration Klasse, die extends GlobalAuthenticationConfigurerAdapter:

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

dann:

@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 
    } 
} 

validiert Ihre @PreAuthorize Spel

gegeben.

Verwandte Themen