2010-06-21 12 views

Antwort

63

Ja, es funktioniert gut.

Sie müssen <security:global-method-security pre-post-annotations="enabled" /> in ...-servlet.xml. Es erfordert auch CGLIB proxies, also sollten entweder Ihre Controller keine Schnittstellen haben, oder Sie sollten proxy-target-class = true verwenden.

+1

ich, dass Sicherheitsanwendung in meinem Frühjahr Kontext gestellt (ich hatte es eigentlich schon), aber Spring macht mit Controllern, die @Controller verwenden, nichts aus. Muss ich etwas Besonderes tun, um dies über das, was Sie gesagt haben, zu arbeiten? In – egervari

+13

Ich sagte, 'global-method-security' sollte im DispatcherServlet-Kontext (' ...- servlet.xml') nicht im "Frühling Sicherheit Anwendungskontext" sein. – axtavt

+0

Danke! Ich habe es nicht bewegt, weil ich nicht sehen konnte, warum es einen Unterschied machen würde, da es zusammengeführt wird ... Ich denke, es hat nicht funktioniert;) Arbeitet jetzt! – egervari

20

Siehe Spring Security FAQ (Hervorhebung von mir). getrennt von dem Hauptanwendungskontext

In einer Feder Web-Anwendung, die der Anwendungskontext ist häufig die Spring MVC Bohnen für den Dispatcher Servlet hält. Es wird oft in einer Datei namens myapp-servlet.xml definiert, wobei "myapp" der Name ist, der dem Spring DispatcherServlet in web.xml zugewiesen wird. Eine Anwendung kann mehrere DispatcherServlets mit jeweils einem eigenen isolierten Anwendungskontext haben. Die Beans in diesen "Kind" -Kontexten sind für den Rest der -Anwendung nicht sichtbar. Der "übergeordnete" Anwendungskontext wird von dem ContextLoaderListener geladen, den Sie in Ihrer web.xml definieren, und ist für alle untergeordneten Kontexte sichtbar. In diesem übergeordneten Kontext definieren Sie normalerweise Ihre Sicherheitskonfiguration, einschließlich des Elements . Daher werden Sicherheitseinschränkungen für Methoden in diese Web-Beans nicht erzwungen, da die Beans aus dem DispatcherServlet-Kontext nicht angezeigt werden. Sie müssen entweder die Deklaration in den Webkontext verschieben oder die Beans, die Sie sichern möchten, in den Hauptanwendungskontext verschieben.

Im Allgemeinen empfehlen wir die Anwendung der Methoden-Sicherheit bei der Schicht statt auf einzelnen Web-Controllern.

Wenn Sie pointcuts zu Service-Layer anwenden müssen Sie nur <global-method-security> in Ihrer App Sicherheitskontext setzen.

+0

Wurde versucht, @ PreAuthorize im Controller zu verwenden, hat nicht funktioniert, funktionierte, sobald ich in die Serviceebene wechselte. – MarCrazyness

16

Wenn Sie mit Spring 3.1, können Sie mit diesem ein paar ziemlich coole Sachen zu tun. Werfen Sie einen Blick auf https://github.com/mohchi/spring-security-request-mapping. Es ist ein Beispielprojekt, das @PreAuthorize mit Spring MVC ist RequestMappingHandlerMapping integriert, so dass Sie so etwas wie zu tun:

@RequestMapping("/") 
@PreAuthorize("isAuthenticated()") 
public String authenticatedHomePage() { 
    return "authenticatedHomePage"; 
} 

@RequestMapping("/") 
public String homePage() { 
    return "homePage"; 
} 

Ein Antrag auf „/“ nennen authenticatedHomePage(), wenn der Benutzer authentifiziert ist. Andernfalls wird homePage() aufgerufen.

9

Es ist mehr als zwei Jahre, seit diese Frage gestellt wurde, aber wegen der Probleme, die ich heute hatte, würde ich eher davon abraten, @Secured, @PreAuthorize usw. unter @Controller s zu verwenden.

Was für mich nicht mochte, war arbeiten @Validated mit @Secured Controller kombiniert:

@Controller 
@Secured("ROLE_ADMIN") 
public class AdministrationController { 

// @InitBinder here... 

@RequestMapping(value = "/administration/add-product", method = RequestMethod.POST) 
public String addProductPost(@ModelAttribute("product") @Validated ProductDto product, BindingResult bindingResult) { 
    // ... 
} 

Validator einfach nicht Feuer (Spring MVC 4.1.2, Spring Security 3.2.5) und keine Kontrollen durchgeführt werden.

ähnliche Probleme verursacht werden, durch CGLIB Proxies, die von Spring (wenn es keine Schnittstelle, die von einer Klasse implementiert ist, erzeugt Frühling CGLIB Proxy, wenn die Klasse eines beliebige Schnittstelle implementiert dann JDK Proxy generiert wird - documentation, well explained here und here).

Wie in den Antworten erwähnt, die ich oben verlinkt habe, ist es besser, Spring Security-Annotationen auf Service-Layer zu verwenden, die normalerweise Schnittstellen implementieren (also JDK-Proxies), da dies nicht zu solchen Problemen führt.

Wenn Sie Web-Controller sichern möchten, ist die bessere Idee, <http> und <intercept-url /> zu verwenden, die an bestimmte URLs statt Methoden in Controllern gebunden sind und recht gut funktionieren. In meinem Fall:

<http use-expressions="true" disable-url-rewriting="true"> 

    ... 

    <intercept-url pattern="/administration/**" access="hasRole('ROLE_ADMIN')" /> 

</http> 
1

Um die Antwort zu erweitern durch Andy vorgesehen ist, können Sie:

@PreAuthorize("hasRole('foo')") 

die spezifische Rolle zu überprüfen.

2

Es gibt bereits eine Antwort darauf, wie es funktioniert, indem man die XML-Konfiguration ändert; Wenn Sie jedoch mit Code-basierten Konfiguration arbeiten, können Sie das gleiche erreichen, indem die folgende Anmerkung über Ihre @Configuration Klasse platzieren:

@EnableGlobalMethodSecurity(prePostEnabled=true)