【问题标题】:@PreAuthorize annotation not working spring security@PreAuthorize 注释不起作用弹簧安全性
【发布时间】:2012-08-04 04:25:03
【问题描述】:

我发现了很多类似的问题,但没有一个能解决我的问题。 我的问题是ROLE_USER可以访问ROLE_ADMIN的功能

我的 spring-security.xml 代码如下。

<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:s="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">   

<s:http auto-config="true" use-expressions="true">
    <s:intercept-url pattern="/index.jsp" access="permitAll" />
    <s:intercept-url pattern="/welcome*" access="hasRole('ROLE_USER')" />
    <s:intercept-url pattern="/helloadmin*" access="hasRole('ROLE_ADMIN')" />

    <s:form-login login-page="/login" default-target-url="/welcome"
        authentication-failure-url="/loginfailed" />
    <s:logout logout-success-url="/logout" />
</s:http>

<s:authentication-manager>
  <s:authentication-provider>
    <s:user-service>
        <s:user name="asif" password="123456" authorities="ROLE_USER,ROLE_ADMIN" />
        <s:user name="raheel" password="123456" authorities="ROLE_USER" />          
    </s:user-service>
  </s:authentication-provider>
</s:authentication-manager>

当我添加&lt;s:global-method-security pre-post-annotations="enabled"/&gt; 我的代码显示资源未找到错误,当我删除我的代码时执行成功,但 ROLE_USER 可以访问 ROLE_ADMIN 函数

我的控制器功能是。

@PreAuthorize("hasRole('ROLE_ADMIN')")
@RequestMapping(value="/delete", method = RequestMethod.GET)
public String DeleteAll(ModelMap model, Principal principal ) {

    org.springframework.security.core.userdetails.User activeUser = (org.springframework.security.core.userdetails.User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    System.out.println("Active user is "+activeUser.getUsername()+"Authorities are "+activeUser.getAuthorities());
    return "deleteUsers";

}

【问题讨论】:

    标签: java spring spring-security


    【解决方案1】:

    我在使用注释时遇到了同样的问题,问题是我的控制器中没有 @Controller 注释。


    看来你需要:

    • Spring Security 配置中的这些注释:

      @Configuration
      @EnableWebSecurity
      @EnableGlobalMethodSecurity(prePostEnabled = true)
      
    • 控制器中的这些注释:

      @Controller
      public class ServiceRS {
      
          @RequestMapping(value = "/admin", method = RequestMethod.GET)
          @PreAuthorize("hasAuthority('ROLE_ADMIN')")
          public void wsAdmin() {
              [...]
          }
      }
      

    另外,如果您仍有问题,请考虑将其添加到您的 log4j2 配置中:

        <Logger name="org.springframework.security" level="trace" additivity="false">
            <AppenderRef ref="Console" />
            <AppenderRef ref="RollingRandomAccessFile" />
        </Logger>
    

    如果 Spring 考虑您的注释,您将在日志中看到:

    TRACE org.springframework.security.access.prepost.PrePostAnnotationSecurityMetadataSource {} [main] Looking for Pre/Post annotations for method 'wsAdmin' on target class '***.ServiceRS' 
    DEBUG org.springframework.security.access.prepost.PrePostAnnotationSecurityMetadataSource {} [main] @org.springframework.security.access.prepost.PreAuthorize(value=hasAuthority('ROLE_ADMIN')) found on specific method: public void ***.ServiceRS.wsAdmin() 
    DEBUG org.springframework.security.access.method.DelegatingMethodSecurityMetadataSource {} [main] Caching method [CacheKey[***.ServiceRS; public void ***.ServiceRS.wsAdmin()]] with attributes [[authorize: 'hasAuthority('ROLE_ADMIN')', filter: 'null', filterTarget: 'null']] 
    

    显然你可以考虑在org.springframework.security.access.expression.SecurityExpressionRoot中的相应方法中添加断点,以查看是否使用注释中的条件完成了调用。

    问候。

    【讨论】:

      【解决方案2】:

      将下面的标签放在另一个spring配置文件中,而不是spring安全配置文件中。

      我也遇到了同样的错误。

      <security:global-method-security secured-annotations="enabled" proxy-target-class="true"/>
      

      【讨论】:

        【解决方案3】:

        如果您使用的是 XML 配置,请不要忘记添加以下属性:

        &lt;s:global-method-security pre-post-annotations="enabled"/&gt;

        如果您使用的是 Java Configuration,请不要忘记添加以下注解:

        @EnableGlobalMethodSecurity(prePostEnabled = true)

        【讨论】:

          【解决方案4】:

          你应该有

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

          如果您希望 @PreAuthorize 注释起作用。


          回答评论:

          您似乎缺少 spring-aop 依赖项。

          如果你使用的是 maven,你需要:

          <dependency>
              <groupId>org.springframework</groupId>
              <artifactId>spring-aop</artifactId>
              <version>${org.springframework.version}</version>
          </dependency>
          

          如果没有,您可以从here 获取罐子。

          【讨论】:

          • 是的,我知道,但是当我添加 我的代码显示资源未找到错误,你知道如何解决吗?
          • 异常将上下文初始化事件发送到类 org.springframework.web.context.ContextLoaderListener org.springframework.beans.factory.BeanDefinitionStoreException 的侦听器实例:从 ServletContext 资源解析 XML 文档时出现意外异常 [/WEB-INF /spring-security.xml];嵌套异常是 java.lang.NoClassDefFoundError: org/aopalliance/intercept/MethodInterceptor
          • 我正在使用 spring security3.07
          【解决方案5】:

          我也面临同样的问题。当我将以下元素从 applicationContext.xml 移动到 *-servlet.xml(我的调度程序的配置 xml)时,我的问题解决了。

          <security:global-method-security secured-annotations="enabled"/>
          

          您必须在调度程序的 xml 中包含此元素,而不是在应用程序的 xml 中
          Spring FAQ

          【讨论】:

          • 如果您至少没有在 servlet 的 xml 配置中定义 global-security-method,这绝对是正确的答案-
          • 这是确切的问题,+1 用于提及 Spring FAQ 链接以进行解释。
          【解决方案6】:

          在使用带有 Web 异步支持的 Servlet 3 时会出现此问题。 Spring Security 3.1.4 及以下版本一旦进入Callable 方法的匿名方法,就会失去它们的安全上下文。

          升级Spring Security to 3.2.0 RC1 将解决您的问题。

          Maven 依赖:

          <dependencies>
              <dependency>
                  <groupId>org.springframework.security</groupId>
                  <artifactId>spring-security-web</artifactId>
                  <version>3.2.0.RC1</version>
              </dependency>
              <dependency>
                  <groupId>org.springframework.security</groupId>
                  <artifactId>spring-security-config</artifactId>
                  <version>3.2.0.RC1</version>
              </dependency>
          </dependencies>
          
          <repositories>
              <repository>
                  <id>spring-milestones</id>
                  <name>Spring Milestones</name>
                  <url>http://repo.spring.io/milestone</url>
                  <snapshots>
                      <enabled>false</enabled>
                  </snapshots>
              </repository>
          </repositories>
          <repositories>
              <repository>
                  <id>spring-milestones</id>
                  <name>Spring Milestones</name>
                  <url>http://repo.spring.io/milestone</url>
                  <snapshots>
                      <enabled>false</enabled>
                  </snapshots>
              </repository>
          </repositories>
          

          【讨论】:

            【解决方案7】:

            以上答案都不适合我。我不得不走添加安全装饰器的路线。

            装饰器被放置在文件servlet-context.xml中的bean上。

            首先将安全模式添加到 XML 命名空间:

            <beans:beans xmlns="http://www.springframework.org/schema/mvc"
            ...
            xmlns:security="http://www.springframework.org/schema/security"
            xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">
            

            然后将装饰器应用到服务 bean 的实现上,像这样..

            <beans:bean id="myService" class="my.service.impl.MyServiceImpl" scope="request">
                <security:intercept-methods>
                    <security:protect access="ROLE_USER" method="get*"/>
                    <security:protect access="ROLE_ADMIN" method="set*"/>
                </security:intercept-methods>
            </beans:bean>
            

            【讨论】:

              【解决方案8】:

              这可能对你有帮助:

              <security:global-method-security secured-annotations="enabled" proxy-target-class="true"/>
              

              问候。

              【讨论】:

                【解决方案9】:

                试试@Secured注解,

                那么你就有了

                @Secured("ROLE_ADMIN")
                @RequestMapping(value="/delete", method = RequestMethod.GET)
                public String DeleteAll(ModelMap model, Principal principal ) {
                
                  ...
                
                }
                

                这里是a detailed blog post about it

                【讨论】:

                  猜你喜欢
                  • 2019-04-27
                  • 2011-01-02
                  • 1970-01-01
                  • 2011-06-22
                  • 2015-06-20
                  • 1970-01-01
                  • 2012-08-22
                  相关资源
                  最近更新 更多