2013-03-12 5 views
11

Ich füge Spring Security zu einem Spring-Projekt hinzu. Die Architektur des Systems ist REST und der Benutzer kann auf verschiedene Ressourcen zugreifen.@ PreAuthorize funktioniert nicht mit Methoden Sicherheitsregeln und Methodenparametern

Ich möchte Administratoren und Benutzern, die Eigentümer dieser Informationen sind, Zugriff auf persönliche Informationen gewähren. Ich habe begonnen, einfach: Filterung Benutzerprofil wie folgt aus:

In meiner Dienstschicht Ich wollte Methode Anmerkungen und umfassen Methodenparameter verwenden ..

@PreAuthorize("hasRole('ROLE_ADMIN') or principal.userId == #id") 
public Usuario getUser(int id) throws DAOException { 
    ... 
} 

Aber das ist gar nicht funktioniert. Jeder Benutzer kann alle Profile sehen (Administratoren und alle Benutzer auch), wenn diese URL angefordert wird (Web Schicht):

@RequestMapping(value="/user/{uid}", method=RequestMethod.GET) 
    public ModelAndView getUser(@PathVariable int uid) throws DAOException { 
     userDAO = new UsuarioJPADAO(); 
     userService.setUsuarioDAO(userDAO); 

    return new ModelAndView("user", "user", userService.getUser(uid)); 
} 

Hier ist meine security.xml

<?xml version="1.0" encoding="UTF-8"?> 
<beans:beans xmlns="http://www.springframework.org/schema/security" 
     xmlns:beans="http://www.springframework.org/schema/beans" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:schemaLocation=" 
     http://www.springframework.org/schema/beans 
     http://www.springframework.org/schema/beans/spring-beans-3.1.xsd 
     http://www.springframework.org/schema/security 
     http://www.springframework.org/schema/security/spring-security-3.1.xsd"> 

<!-- Security Annotations --> 
    <global-method-security 
     pre-post-annotations="enabled"/> 

<http auto-config="true" use-expressions="true"> 
    <intercept-url pattern="/css/**" access="permitAll" /> 
    <intercept-url pattern="/images/**" access="permitAll" /> 
    <intercept-url pattern="/js/**" access="permitAll" /> 
    <intercept-url pattern="/favicon.ico" access="permitAll" /> 
    <intercept-url pattern="/login" access="permitAll" /> 

    <intercept-url pattern="/users" access="hasRole('ROLE_ADMIN')" /> 
    <intercept-url pattern="https://stackoverflow.com/users/page/*" access="hasRole('ROLE_ADMIN')" /> 
    <intercept-url pattern="/customers" access="hasRole('ROLE_ADMIN')" /> 
    <intercept-url pattern="/employees" access="hasRole('ROLE_ADMIN')" /> 

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

    <intercept-url pattern="/*" access="hasAnyRole('ROLE_ADMIN, ROLE_EMPLOYEE, ROLE_PARTNER, ROLE_USER')" /> 
    <intercept-url pattern="/*/*" access="hasAnyRole('ROLE_USER, ROLE_ADMIN')" /> 
    <intercept-url pattern="/*/*/*" access="hasAnyRole('ROLE_USER, ROLE_ADMIN')" /> 
    <intercept-url pattern="/*/*/*/*" access="hasAnyRole('ROLE_USER, ROLE_ADMIN')" /> 
    <intercept-url pattern="/*/*/*/*/*" access="hasAnyRole('ROLE_USER, ROLE_ADMIN')" /> 
    <intercept-url pattern="/*/*/*/*/*/*" access="hasAnyRole('ROLE_USER, ROLE_ADMIN')" /> 
    <intercept-url pattern="/*/*/*/*/*/*/*" access="hasAnyRole('ROLE_USER, ROLE_ADMIN')" /> 
    <form-login login-page="/login" login-processing-url="/doLogin" 
       authentication-failure-url="/login?error" 
       username-parameter="username" password-parameter="password" 
       default-target-url="/default" /> 

    <logout invalidate-session="true" logout-success-url="/login?logout" logout-url="/logout"/> 
</http> 
<authentication-manager> 
    <authentication-provider user-service-ref="UsuarioService"> 
    </authentication-provider> 
</authentication-manager>  

I habe Spring Security 3.1 book überprüft und anscheinend ist meine Konfiguration, wie Buch vorschlägt. Ich habe andere Stack Overflow Beiträge (here und) gelesen, aber ich hatte kein Glück.

Update: Added application-context.xml

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns:p="http://www.springframework.org/schema/p"  
     xmlns:aop="http://www.springframework.org/schema/aop" 
     xmlns:tx="http://www.springframework.org/schema/tx" 
     xmlns:mvc="http://www.springframework.org/schema/mvc" 
     xmlns:security="http://www.springframework.org/schema/security" 
     xmlns:context="http://www.springframework.org/schema/context" 
     xmlns:jee="http://www.springframework.org/schema/jee" 
     xsi:schemaLocation="http://www.springframework.org/schema/beans 
     http://www.springframework.org/schema/beans/spring-beans-3.1.xsd 
     http://www.springframework.org/schema/aop 
     http://www.springframework.org/schema/aop/spring-aop-3.1.xsd 
     http://www.springframework.org/schema/tx 
     http://www.springframework.org/schema/tx/spring-tx-3.1.xsd 
     http://www.springframework.org/schema/mvc 
     http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd 
     http://www.springframework.org/schema/context 
     http://www.springframework.org/schema/context/spring-context-3.1.xsd 
     http://www.springframework.org/schema/security 
     http://www.springframework.org/schema/security/spring-security-3.1.xsd"> 

    <context:annotation-config /> 

<context:component-scan base-package="com.pe.fs" /> 

<mvc:annotation-driven /> 

<mvc:resources mapping="/**" location="/" /> 

<mvc:interceptors> 
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"> 
    <property name="paramName" value="lang" /> 
</bean> 
</mvc:interceptors> 

<!-- DataSource --> 
<bean id="jpaDataSource" class="oracle.jdbc.pool.OracleDataSource" 
    destroy-method="close" 
    p:driverType="oracle.jdbc.OracleDriver" 
    p:user="**********" 
    p:password="**********" 
    p:uRL="jdbc:oracle:thin:@localhost:1521:XE" 
/> 

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
    <property name="persistenceXmlLocation" value="classpath*:META-INF/persistence.xml"></property> 
    <property name="persistenceUnitName" value="freesunPU" /> 
    <property name="dataSource" ref="jpaDataSource" /> 
    <property name="jpaVendorAdapter"> 
     <bean class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter"> 
      <property name="showSql" value="false" /> 
     </bean> 
    </property> 
    <property name="loadTimeWeaver"> 
     <bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/> 
    </property> 
</bean> 

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" 
    p:entityManagerFactory-ref="entityManagerFactory" /> 

<tx:annotation-driven mode="aspectj"/> 

<context:load-time-weaver aspectj-weaving="autodetect" /> 

Update: Ich habe spring-security-aspects auf POM und keine Änderungen gegeben. Andere Änderungen, die in Antworten vorgeschlagen wurden, wurden getestet, aber Anmerkungen wie @PreAuthorize funktionieren immer noch nicht. Kann das ein Problem zwischen Kontexten sein? Kann die Verwendung von aspectJ der Grund sein?

Was mache ich falsch?

+0

Ihre 'Usuario getUser (int id)' Methode ist in einer Schnittstelle definiert? Standardmäßig funktioniert diese Art von Annotationen möglicherweise nicht (JDK-Proxies werden zum Hinzufügen von Berechtigungsprüfungen zur Laufzeit verwendet und können nur auf Interface-Methoden abzielen). –

+0

@MaksymDemidas Nein. My UsuarioService implementiert UserDetailsService. Ich arbeite auch mit meiner eigenen UsuarioDetails Klasse, die meine Domain Usuario erweitert und UserDetails implementiert – Spacemonkey

+0

wft man? :) ändere ""/*/*/*/*/* "" in "/ **" – Yura

Antwort

9

Endlich habe ich eine Lösung gefunden. In SO fand ich einige nützliche Antworten. Siehe here und here.

Ich bewegte global-method-security zu application-context.xml, die der Kontext meiner Dienste ist.

<security:global-method-security 
    mode="aspectj" 
    secured-annotations="enabled" 
    jsr250-annotations="disabled" 
    pre-post-annotations="enabled"/> 

Wo mode="aspectj" wie Javadoc sagt:

... verwendet werden kann, um festzulegen, dass AspectJ anstelle des AOP Standard Frühling verwendet werden soll. Falls festgelegt, müssen gesicherte Klassen mit dem AnnotationSecurityAspect aus dem Modul Federsicherheitsaspekte verwoben werden.

Natürlich, ich habe hinzugefügt, um POM spring-security-aspects:

<dependency> 
    <groupId>org.springframework.security</groupId> 
    <artifactId>spring-security-aspects</artifactId> 
    <version>3.1.3.RELEASE</version> 
</dependency> 
+0

froh zu sehen, dass Sie die Lösung gefunden haben! –

+0

Sehr geehrte @MaksymDemidas, danke für Ihre Hilfe. – Spacemonkey

+0

move global-method-security löste mein Problem. http://docs.spring.io/spring-security/site/faq/faq.html#faq-method-security-in-web-context – user227353

0

neue Schnittstelle hinzufügen:

public interface UserService extends UserDetailsService { 
    Usuario getUser(int id) throws DAOException 
} 

Implementieren Sie es in Ihrem Benutzerdienst und versuchen Sie es erneut. Spring kann die angeforderten Berechtigungsprüfungen mithilfe von JDK-Proxys hinzufügen.

Als weitere Option können Sie Spring so konfigurieren, dass einige schwerere Bibliotheken wie Javassist oder AspectJ verwendet werden. In diesem Fall ist keine Schnittstelle erforderlich.

BEARBEITEN. Stellen Sie sicher, dass global-method-security im selben Spring-Kontext mit Ihrer Benutzer-Service-Bean deklariert ist.

+0

Funktioniert nicht beim Hinzufügen der Schnittstelle .. Sollte ich die Methode wie in meinem Post, nicht in der Schnittstelle, kommentieren, nicht? – Spacemonkey

+0

Ja, Annotationen werden normalerweise auf der Implementationsseite angewendet –

+1

Bitte zeigen Sie Ihre Spring Xml. Sie können zwei Frühlingskontexte haben (für Bohnen und für Spring MVC). Sind Sie sicher, dass Ihr Global-Method-Security-Element im selben Kontext mit Ihrem Benutzerservice definiert ist? –

0

Der alternative Weg, damit es funktioniert ist es, den folgenden Code in Ihr security.xml hinzufügen

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

Es wird Stellen Sie sicher, dass nur Administratoren auf die Ressourcen zugreifen können, die mit Muster/Benutzer/beginnen.