【问题标题】:Custom permission evaluator for spring security throws ClassCastException春季安全性的自定义权限评估器抛出 ClassCastException
【发布时间】:2016-03-29 03:44:30
【问题描述】:

我已经发现出了什么问题,只是将其发布在这里,以便在谷歌上搜索此异常会返回除 Hibernate 问题之外的其他问题。

我正在尝试使用自定义权限评估器设置 Spring Security 4,但遇到此异常:

HTTP Status 500 - Request processing failed; nested exception is java.lang.ClassCastException: org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation cannot be cast to org.springframework.security.web.FilterInvocation

然后我请求一个http://localhost:8080/my-service/secured/root@boss,它应该评估这个方法:

@Controller
public class SecuredServiceController {

@Autowired
private SecuredService securedService;

@RequestMapping(value = "/secured/{name:.+}", method = RequestMethod.GET)
@PreAuthorize("hasPermission(#name, 'view.%')")
public ModelAndView stuff(@PathVariable("name") String name) throws ServletException, IOException {

    ModelAndView model = new ModelAndView();
    model.setViewName("hello");

    model.addObject("message", securedService.getSecret(name));
    return model;
}}

但它没有被调用,异常早在那之前就被抛出了。

这是我的spring-security.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:security="http://www.springframework.org/schema/security"
   xmlns:context="http://www.springframework.org/schema/context"
   xsi:schemaLocation="
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security-4.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-4.0.xsd">

<security:http auto-config="true" use-expressions="true">
    <security:intercept-url pattern="/j_spring_security_check" access="permitAll"/>
    <security:intercept-url pattern="/free" access="permitAll"/>
    <security:intercept-url pattern="/test*" access="isAuthenticated()"/>
    <security:logout invalidate-session="true" delete-cookies="JSESSIONID" logout-url="/logout"/>
</security:http>

<security:authentication-manager>
    <security:authentication-provider ref="myAuthenticationProvider"/>
</security:authentication-manager>
<bean id="myAuthenticationProvider"
      class="com.me.webcommon.spring_auth.MySpringAuthenticationProvider"/>

<security:global-method-security pre-post-annotations="enabled" secured-annotations="enabled">
    <security:expression-handler ref="expressionHandler"/>
</security:global-method-security>

<bean id="permissionEvaluator" class="com.me.webcommon.spring_auth.MyPermissionEvaluator"/>

<context:component-scan
        base-package="com.me.webcommon.spring_auth"/>
<bean id="expressionHandler"
      class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler">
    <property name="permissionEvaluator" ref="permissionEvaluator"/>
</bean>

【问题讨论】:

    标签: java spring spring-security proxy


    【解决方案1】:

    仔细查看异常,它表示方法代理不能转换为过滤器代理。这是因为我应该使用方法表达式处理程序 org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler
    相反,如果org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler
    并且spring创建了一种错误的代理对象来从调用中检索参数并将它们传递给我的permissionEvaluator,然后再调用该方法。

    这是一个有效的spring-security.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:security="http://www.springframework.org/schema/security"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://www.springframework.org/schema/security
        http://www.springframework.org/schema/security/spring-security-4.0.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-4.0.xsd">
    
    <security:http auto-config="true" use-expressions="true">
        <security:intercept-url pattern="/j_spring_security_check" access="permitAll"/>
        <security:intercept-url pattern="/free" access="permitAll"/>
        <security:intercept-url pattern="/test*" access="isAuthenticated()"/>
        <security:logout invalidate-session="true" delete-cookies="JSESSIONID" logout-url="/logout"/>
    </security:http>
    
    <security:authentication-manager>
        <security:authentication-provider ref="myAuthenticationProvider"/>
    </security:authentication-manager>
    <bean id="myAuthenticationProvider"
          class="com.me.webcommon.spring_auth.MySpringAuthenticationProvider"/>
    
    <security:global-method-security pre-post-annotations="enabled" secured-annotations="enabled">
        <security:expression-handler ref="expressionHandler"/>
    </security:global-method-security>
    
    <bean id="permissionEvaluator" class="com.me.webcommon.spring_auth.MyPermissionEvaluator"/>
    
    <context:component-scan
            base-package="com.me.webcommon.spring_auth"/>
    <!--here, it must be a method expression handler-->
    <bean id="expressionHandler"
          class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
        <property name="permissionEvaluator" ref="permissionEvaluator"/>
    </bean>
    

    【讨论】:

    • 哇...我在这个确切的问题上浪费了几乎一整天的时间。当我尝试添加 @PreAuthorize 注释时,我正在使用 DefaultWebSecurityExpressionHandler 并开始获取代理/过滤器异常。更改为 DefaultMethodSecurityExpressionHandler 解决了这个问题。有趣的是,我从 DefaultMethodSecurityExpressionHandler 开始,但切换到 DefaultWebSecurityExpressionHandler 以解决我不记得的其他问题。非常感谢您花时间为后代发布此内容。
    猜你喜欢
    • 2014-01-28
    • 2015-07-30
    • 2017-10-27
    • 2013-07-21
    • 2014-05-22
    • 2013-02-24
    • 1970-01-01
    • 2017-03-05
    • 1970-01-01
    相关资源
    最近更新 更多