Spring方法安全性对我不起作用

时间:2011-10-24 04:35:01

标签: spring

我是春天安全的新手。

我尝试在我的应用程序中使用spring security。基本的Spring安全功能正常。

但是当我尝试保护方法只允许特定角色时,它不受保护,并且该方法可以适用于每个角色。

这里我给出了我的代码片段。我可能知道我错了。

我用于此应用程序的库是

01.aopalliance-1.0.jar
02.jcl-over-slf4j-1.6.1.jar
03.jstl-1.2.jar
04.logback-classic-0.9.29.jar
05.logback-core-0.9.29.jar
06.mysql-connector-java-5.1.12-bin.jar
07.org.springframework.jdbc-3.1.0.RC1.jar
08.org.springframework.transaction-3.1.0.RC1.jar
09.slf4j-api-1.6.1.jar
10.spring-aop-3.0.6.RELEASE.jar
11.spring-asm-3.0.6.RELEASE.jar
12.spring-beans-3.0.6.RELEASE.jar
13.spring-context-3.0.6.RELEASE.jar
14.spring-context-support-3.0.6.RELEASE.jar
15.spring-core-3.0.6.RELEASE.jar
16.spring-expression-3.0.6.RELEASE.jar
17.spring-security-config-3.1.0.RC3.jar
18.spring-security-core-3.1.0.RC3.jar
19.spring-security-crypto-3.1.0.RC3.jar
20.spring-security-taglibs-3.1.0.RC3.jar
21.spring-security-web-3.1.0.RC3.jar
22.spring-web-3.0.6.RELEASE.jar
23.spring-webmvc-3.0.6.RELEASE.jar

的web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/applicationContext.xml
            /WEB-INF/security-app-context.xml
            /WEB-INF/application-data-source.xml
        </param-value>
    </context-param>

    <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>
    <!--
      - Provides core MVC application controller. See bank-servlet.xml.
     -->
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>*.htm</url-pattern>
    </servlet-mapping>

    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>

调度-servlet.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
                           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                           http://www.springframework.org/schema/aop
                           http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
                           http://www.springframework.org/schema/tx
                           http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
                           http://www.springframework.org/schema/security
                           http://www.springframework.org/schema/security/spring-security-3.1.xsd"
       xmlns:ns1="http://www.springframework.org/schema/security">

    <ns1:global-method-security pre-post-annotations="enabled"/>

    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>

    <bean id="viewResolver"
          class="org.springframework.web.servlet.view.InternalResourceViewResolver"
          p:prefix="/pages/result/"
          p:suffix=".jsp" >
          <property name="viewClass">
            <value>
              org.springframework.web.servlet.view.JstlView
            </value>
          </property>
    </bean>

    <!--
    The index controller.
    -->

    <bean name="indexController"
          class="org.springframework.web.servlet.mvc.ParameterizableViewController"
          p:viewName="index" />

    <bean name="/action.htm" id="action" class="com.spt3.controller.ActionController">
        <property name="methodNameResolver">
            <ref bean="paramResolver"/>
        </property>
    </bean>

    <bean id="paramResolver" class="org.springframework.web.servlet.mvc.multiaction.ParameterMethodNameResolver">
        <property name="paramName">
            <value>action</value>
        </property>
    </bean>

</beans>

的applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:security="http://www.springframework.org/schema/security"
    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.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd">


</beans>

安全应用程式内-context.xml中

<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.0.xsd
                    http://www.springframework.org/schema/security 
                    http://www.springframework.org/schema/security/spring-security-3.1.xsd">

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

    <http use-expressions="true" auto-config="true" access-denied-page="/pages/accessDenied.jsp">
            <intercept-url pattern="/index.jsp" access="permitAll" />
            <intercept-url pattern="/**.htm" access="isAuthenticated()"/>
            <intercept-url pattern="/pages/*" access="permitAll" />
            <intercept-url pattern="/user/*" access="isAuthenticated()"/>            
            <intercept-url pattern="/md/*" access="hasRole('MD')"/>
            <intercept-url pattern="/admin/*" access="hasAnyRole('Administrator','MD')"/>
            <intercept-url pattern="/manager/*" access="hasAnyRole('Manager','MD')"/>
            <form-login login-page="/pages/login.jsp" authentication-failure-url="/pages/loginfailed.jsp"/>
            <logout logout-success-url="/index.jsp"/>
    </http>

    <beans:bean id="encoder" class="com.spt3.encoder.MyPasswordEncoder"/>

    <authentication-manager>
      <authentication-provider>
        <password-encoder ref="encoder"/>
        <jdbc-user-service data-source-ref="dataSource"

                   users-by-username-query="
                      select username,password, enabled
                      from users where username=?"

                   authorities-by-username-query="
                      select u.username, ur.authority from users u, user_roles ur where u.user_id = ur.user_id and u.username =?  "
        />
      </authentication-provider>
    </authentication-manager>

</beans:beans>

应用 - 数据 - source.xml

<beans xmlns="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.0.xsd">

   <bean id="dataSource"    class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:3306/app" />
        <property name="username" value="uname" />
        <property name="password" value="pword" />
    </bean>

</beans>

ActionController.java

package com.spt3.controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.multiaction.MultiActionController;
import com.spt3.infc.ActionInterface;
import org.springframework.security.access.prepost.PreAuthorize;

public class ActionController extends MultiActionController implements ActionInterface {

    public ActionController(){
    }

    public ModelAndView getResult(HttpServletRequest request,HttpServletResponse response)throws Exception{
        System.out.println(" - - - - - getResult() - - - - - ");
        try{
            this.getPersonalInformation("MD");
        }catch(Exception e){
            System.out.println(" Exception : "+e);
        }
        return new ModelAndView("result");
    }

    public void getPersonalInformation(String role){
        System.out.println(" "+role+"'s-Personal Information.");
    }
}

ActionInterface.java

package com.spt3.infc;

import org.springframework.security.access.prepost.PreAuthorize;
public interface ActionInterface {

    @PreAuthorize("hasRole('MD')") // Secured method only for role MD
    public void getPersonalInformation(String role);
}

从url访问getResult()方法时( 可以调用http://127.0.0.1:8080/myapp/action.htm?action=getResult)安全方法。

我的预期结果应为

  • getPersonalInformation()方法只能访问用户角色MD

现在实际结果

  • getPersonalInformation()方法正在调用每个用户角色。

使用豆子后 - 编辑(1)此处

使用bean注入时发生了同样的问题。

我在这里用代码片段更改了文件。

ActionController.java就像

package com.spt3.controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.multiaction.MultiActionController;
import com.spt3.infc.ActionInterface;

public class ActionController extends MultiActionController {

    private ActionInterface actionInterface;

    public ActionController(){
    }

    public ActionController(ActionInterface actionInterface){
        this.actionInterface=actionInterface;
    }

    public ModelAndView getResult(HttpServletRequest request,HttpServletResponse response)throws Exception{
        System.out.println(" - - - - - getResult() - - - - - ");
        try{
            actionInterface.getPersonalInformation("MD");
        }catch(Exception e){
            System.out.println(" Exception : "+e);
        }
        return new ModelAndView("result");
    }

}

ActionInterface.java

package com.spt3.infc;

public interface ActionInterface {

    public void getPersonalInformation(String role);
}

bean类名为ActionBean.java

package com.spt3.bean;


import com.spt3.infc.ActionInterface;
import org.springframework.security.access.annotation.Secured;

public class ActionBean implements ActionInterface{

    @Secured("MD")
    public void getPersonalInformation(String role){
        System.out.println(" "+role+"'s-Personal Information.");
    }

}

我使用构造函数注入来注入对象。

<bean id="actionBean" class="com.spt3.bean.ActionBean"/> <!-- Bean class -->
<bean name="/action.htm" id="action" class="com.spt3.controller.ActionController">
        <property name="methodNameResolver">
            <ref bean="paramResolver"/>
        </property>
        <constructor-arg index="0" ref="actionBean"/> <!-- Injecting object to controller -->
    </bean>

我错了。请给我解决方案。

问题已解决。

这是我遵循的步骤。

  1. 在适当的xml文件中配置bean
  2. 我用豆子注射。
  3. 我使用了@PreAuthorize注释。
  4. 最后,当程序成功运行时,类看起来像以下代码段。

    ActionBean是我创建的一个单独的类,我实现了ActionInterface.java类并实现了方法getPersonalInformation()方法。

    ActionInterface.java看起来像这样

    package com.spt3.infc;
    
    public interface ActionInterface {
    
        public void getPersonalInformation(String role);
    }
    

    和ActionBean.java看起来像这样

    package com.spt3.bean;
    
    
    import com.spt3.infc.ActionInterface;
    import org.springframework.security.access.prepost.PreAuthorize;
    
    public class ActionBean implements ActionInterface{
    
        @PreAuthorize("hasRole('MD')")
        public void getPersonalInformation(String role){
            System.out.println(" "+role+"'s-Personal Information.");
        }
    
    }
    

    ActionController.java看起来像这样

    package com.spt3.controller;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import org.springframework.web.servlet.ModelAndView;
    import org.springframework.web.servlet.mvc.multiaction.MultiActionController;
    import com.spt3.infc.ActionInterface;
    
    public class ActionController extends MultiActionController {
    
        private ActionInterface actionInterface;
    
        public ActionController(){
        }
    
        public ActionController(ActionInterface actionInterface){
            this.actionInterface=actionInterface;
        }
    
        public ModelAndView getResult(HttpServletRequest request,HttpServletResponse response)throws Exception{
            System.out.println(" - - - - - getResult() - - - - - ");
            try{
                actionInterface.getPersonalInformation("MD");
            }catch(Exception e){
                System.out.println(" Exception : "+e);
            }
            return new ModelAndView("result");
        }
    
    }
    
    祝你好运...... 非常感谢。

1 个答案:

答案 0 :(得分:3)

Spring安全性通过使用spring bean周围的代理来工作,它绕过对bean方法的调用,如果用户没有适当的角色则抛出异常。但是你的控制器不会调用任何spring bean方法。它确实调用了一个实例方法:this.getPersonalInformation()

执行此操作时,您不会调用另一个Spring bean方法,因此Spring无法拦截调用,因此无法验证用户是否具有相应的角色。

getPersonalInformation方法放在另一个Spring bean中,在控制器中注入这个bean,一切都应该没问题。

旁注:为什么不简单地使用@Secured("MD")注释来表示这种情况?为什么不直接在getResult方法上添加注释?