2013-07-03 12 views
10

używam sprężyna w pre-autoryzacji adnotacji następująco:Używanie zmiennych statycznych w adnotacjach Wiosna

@PreAuthorize("hasRole('role')"); 

Jednak mam już „rolę” określony jako statyczny ciąg na innej klasy. Gdy próbuję użyć tej wartości:

@PreAuthorize("hasRole(OtherClass.ROLE)"); 

pojawia się błąd:

org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 14): Field or property 'OtherClass' cannot be found on object of type 'org.springframework.security.access.expression.method.MethodSecurityExpressionRoot' 

Czy istnieje sposób, aby uzyskać dostęp do zmiennych statycznych, jak to z adnotacją pre-autoryzacji?

Odpowiedz

16

spróbuj wykonać następujące czynności, które wykorzystuje Wiosna Expression Język ocenić typ:

@PreAuthorize("hasRole(T(fully.qualified.OtherClass).ROLE)"); 

Pamiętaj, aby podać pełną nazwę klasy.

Documentation

+0

Działa świetnie, dziękuję! – RobEarl

+0

@RobEarl Awesome Glad, że mogę pomóc. Też się też czegoś nauczyłem. –

+0

Działa, ale wciąż jest interpretowanym ciągiem znaków, więc nie będzie "widziany" przez Eclipse podczas refaktoryzacji, np. nazwa chyba. – yglodt

3

Spróbuj czegoś takiego:

@PreAuthorize("hasRole(T(com.company.enumpackage.OtherClass).ROLE.name())"); 

Jeśli OtherClass enum jest zadeklarowana jako public static, następnie trzeba użyć $ znak:

@PreAuthorize("hasRole(T(com.company.ParentTopLevelClass$OtherClass).ROLE.name())"); 

name() aby zapobiec Futer problemy, jeśli toString() zostanie nadpisany później

4

Przyjęta odpowiedź od Kevina Bowersoxa działa, ale nie podobało mi się posiadanie rzeczy T (w pełni kwalifikowanych), więc wciąż szukałem. Zacząłem tworząc niestandardową metodę zabezpieczeń przy użyciu odpowiedź od James Watkins tutaj:

How to create custom methods for use in spring security expression language annotations

Jednak zamiast String, kiedyś moją klasę enums.Permissions jako typ parametru:

@Component 
public class MySecurityService { 
    public boolean hasPermission(enums.Permissions permission) { 

     ...do some work here... 

     return true; 
    } 
} 

teraz miłe jest to, że kiedy ja nazywam hasPermission z adnotacją, że nie trzeba mieć, aby wpisać całą ścieżkę, ale trzeba ją ująć w apostrofy:

@PreAuthorize("@mySecurityService.hasPermission('SOME_ROLE_NAME')") 

Ponieważ metoda hasPermission oczekuje wyliczenia, automatycznie znajdzie wartość wyliczenia o tej nazwie. Jeśli nie go znaleźć dostaniesz wyjątek:

org.springframework.expression.spel.SpelEvaluationException: Type conversion problem, cannot convert from java.lang.String to enums.Permissions 

Można zmienić nazwę hasPermission do hasRole, w którym to przypadku jedyny kompromis jest to, że jesteś handlowych (T) dla fully.qualified.path @mySecurityService i dodatkowe pojedyncze cudzysłowy.

Nie jestem pewien, czy jest lepszy, ale jest. Ponieważ żadna z nich i tak nie zweryfikuje wartości podczas kompilacji, moim następnym krokiem jest stworzenie procesora adnotacji.

Mam też dać kredyt krosenvold za wskazanie, że wiosna może automatycznie konwertować do wyliczenia: https://stackoverflow.com/a/516899/618881

6

celu umożliwienia zapisu wyrażeń bez nazw pakietów:

<sec:global-method-security> 
    <sec:expression-handler ref="methodSecurityExpressionHandler"/> 
</sec:global-method-security> 

<bean id="methodSecurityExpressionHandler" class="my.example.DefaultMethodSecurityExpressionHandler"/> 

Następnie przedłużyć DefaultMethodSecurityExpressionHandler:

public class DefaultMethodSecurityExpressionHandler extends org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler { 

    @Override 
    public StandardEvaluationContext createEvaluationContextInternal(final Authentication auth, final MethodInvocation mi) { 
     StandardEvaluationContext standardEvaluationContext = super.createEvaluationContextInternal(auth, mi); 
     ((StandardTypeLocator) standardEvaluationContext.getTypeLocator()).registerImport("my.example"); 
     return standardEvaluationContext; 
    } 
} 

teraz tworzyć my.example.Roles.java:

public class Roles { 

    public static final String ROLE_UNAUTHENTICATED = "ROLE_UNAUTHENTICATED"; 

    public static final String ROLE_AUTHENTICATED = "ROLE_AUTHENTICATED"; 
} 

i odnoszą się do niego bez nazwy pakietu w adnotacji:

@PreAuthorize("hasRole(T(Roles).ROLE_AUTHENTICATED)") 

zamiast:

@PreAuthorize("hasRole(T(my.example.Roles).ROLE_AUTHENTICATED)") 

czyni go bardziej czytelny IMHO. Role są teraz wpisane. Napisz:

@PreAuthorize("hasRole(T(Roles).ROLE_AUTHENTICATEDDDD)") 

a dostaniesz startowe błędy, które nie zostały tam jeśli napisał:

@PreAuthorize("hasRole('ROLE_AUTHENTICATEDDDD')") 
+0

Dobre rozwiązanie. Mając błędy startowe byłoby miło, ale nie sądzę, że możesz osiągnąć to w ten sposób. Ocena nadal ma miejsce w czasie wykonywania. Nie znalazłem lepszego rozwiązania, ale trudne ... – chris

Powiązane problemy