简体   繁体   中英

Spring Security 3.0: Method Security being ignored

I'm new to Spring Security and I'm having trouble getting Spring Method Security to work in my web application although (I believe) I've setup the web.xml , applicationContext.xml and applicationContext-security.xml to enable and use Spring method security. This web application uses GWT and RESTful services and I have successfully implemented security via user authentcation ie forcing users to login to the web app - and even implemented Single-Sign-On using SPNEGO with Keberos and Active Directory. However, when I add the <global-method-security> element to the security context and specify appropriate annotations against the desired Java methods, nothing appears to happen!

I'm specifically trying to get @PostFilter to work (but getting any method security to work would be great!), however the returned list is NOT filtered, no related errors are generated and no exceptions are listed in the Tomcat log files.

I'm sure there's something quite basic and fundamental that I've overlooked but none of the examples I've seen clearly state what ALL of the pre-requistes are to get method security to work eg do I really need to use AOP and if so, how? All the examples simply say to add the <global-method-security> element to the application context (with appropriate attributes ie pre-post-annotations="enabled" ) and then use the corresponding annotations along-side the methods you wish to secure.....then - like magic - it should work!

Anyway, here's my configuration files:

web.xml

<web-app>
    <display-name>Jersey Rest Servlet</display-name>
    <context-param>
        <param-name>contextConfigLocation</param-name>
            <param-value>
                classpath:applicationContext.xml
                classpath:applicationContext-security.xml
            </param-value>
    </context-param>

    <!-- Hook into Spring Security framework -->
    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>


    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <servlet>
        <servlet-name>JerseyRESTService</servlet-name>
        <servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class>
        <load-on-startup>1<load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>JerseyRESTService</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>

    <welcome-file-list>
        <welcome-file>/jsp/Home.jsp</welcome-file>
    </welcome-file-list>

</web-app>

applicationContext.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:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.1.xsd">

    <context:component-scan base-package="com.myorg.webservices.impl" />

    <bean id="mongo" class="com.mongodb.Mongo">
        <constructor-arg name="host" value="localhost" />
        <constructor-arg name="port" value="27017" />
    </bean>

    <bean id="db" class="com.myorg.dao.DBFactory">
        <constructor-arg name="mongo" ref="mongo">
        <constructor-arg name="name" value="mydatabase" />
    </bean>

</beans>

applicationContext-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"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-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.0.3.xsd">

    <!-- Enable annotations-based security -->
    <global-method-security pre-post-annotations="enabled" />


    <http use-expresions="true">
        <intercept-url> pattern="/**" access="isAuthenticated()" /l>
        <form-login />
    </http>

    <authentication-manager>
        <authentication-provider>
            <user-service>
                <user name="testadmin" password="password" authorities="supervisor, user" />
                <user name="testuser001" password="password" authorities="user" />
            </user-service>
        </authentication-provider>
    </authentication-manager>

</beans:beans>

And finally, the java source file containing the method I wish to filter on.

DomainPageDecorator.java

package  com.myorg.client.domain;

import java.util.ArrayList;
import java.util.List;
import org.springframework.security.access.prepost.PostFilter;
import org.springframework.security.access.prepost.PreAuthorize;

public class DomainPageDecorator extends PageDecorator<DomainData> 
{
    public DomainPageDecorator (int numberOfRecordsOnPage)
    {
        this.setPageSize(numberOfRecordsOnPage);
    }


    "       "
    "       "
    "       "

    /* Use Spring Method Security to only allow 'ACTIVE' objects through */
    @PreAuthorize("hasRole('ROLE_USER')")
    @PostFilter("filterObject.getStatus()=='ACTIVE' ")
    public List<DomainObject> convertToList()
    {
        List<DomainObject> dataList = new ArrayList<DomainObject>();

        for (int i = 0; i < data.getPage().getLength(); i++)
        {
            dataList.add(new DomainObject(data.getPage().get(i) ) );
        }

        return dataList;
    }

    public DomainObject getFirstItem()
    {
        return new DomainObject(data.getPage().get(0) );
    }
}

Can anyone please tell me what am I missing or doing wrong?

NB: I work in a secured environment which prevents me from posting stack traces and large code segments etc onto the internet from my development machine. However, I should still be able provide any further information that's needed to help resolve this problem even though I'll be typing it all up :-( Apologies in advance for any typos

You can apply these annotations only to beans declared in some spring context file . From provided code it looks like your DomainPageDecorator class is not managed by spring. Make it managed:

  1. Declare it (via some annotation like @Component or directly in the xml).
  2. Retrieve it via Spring (instead of using new keyword). Use @Inject or XML.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM