SpelEvaluationException: EL1004E:(pos 0): Method call: Method hasPermission(java.lang.String) 在 MethodSecurityExpressionRoot 类型上

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23154239/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 21:05:26  来源:igfitidea点击:

SpelEvaluationException: EL1004E:(pos 0): Method call: Method hasPermission(java.lang.String) cannot be found on MethodSecurityExpressionRoot type

javaspringspring-mvcspring-security

提问by Kleber Mota

I add to my project a class CustomPermissionEvaluator, configured by a configuration class MethodSecurityConfig, but when I try run my application, after I inform my login credencials, I am receiving this error message:

我向我的项目添加了一个类 CustomPermissionEvaluator,由配置类 MethodSecurityConfig 配置,但是当我尝试运行我的应用程序时,在我通知我的登录凭据后,我收到此错误消息:

Grave: Servlet.service() for servlet [dispatcher] in context with path [/webapp2] threw exception [Request processing failed; nested exception is java.lang.IllegalArgumentException: Failed to evaluate expression 'hasPermission('admin_main')'] with root cause
org.springframework.expression.spel.SpelEvaluationException: EL1004E:(pos 0): Method call: Method hasPermission(java.lang.String) cannot be found on org.springframework.security.access.expression.method.MethodSecurityExpressionRoot type
    at org.springframework.expression.spel.ast.MethodReference.findAccessorForMethod(MethodReference.java:202)
    at org.springframework.expression.spel.ast.MethodReference.getValueInternal(MethodReference.java:118)
    at org.springframework.expression.spel.ast.MethodReference.getValueInternal(MethodReference.java:80)
    at org.springframework.expression.spel.ast.SpelNodeImpl.getTypedValue(SpelNodeImpl.java:102)
    at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:98)
    at org.springframework.security.access.expression.ExpressionUtils.evaluateAsBoolean(ExpressionUtils.java:11)
    at org.springframework.security.access.expression.method.ExpressionBasedPreInvocationAdvice.before(ExpressionBasedPreInvocationAdvice.java:41)
    at org.springframework.security.access.prepost.PreInvocationAuthorizationAdviceVoter.vote(PreInvocationAuthorizationAdviceVoter.java:54)
    at org.springframework.security.access.prepost.PreInvocationAuthorizationAdviceVoter.vote(PreInvocationAuthorizationAdviceVoter.java:24)
    at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:62)
    at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:206)
    at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:60)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:631)
    at com.spring.webapp.lojavirtual.acesso.controller.PrivadoController$$EnhancerByCGLIB$$e6bb4ae6_2.admin(<generated>)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:219)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:745)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:686)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:936)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:827)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:146)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:154)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:199)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:57)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:343)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:260)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1023)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:744)

My class CustomPermissionEvaluator is that:

我的类 CustomPermissionEvaluator 是:

@Component
public class CustomPermissionEvaluator implements PermissionEvaluator {

    public CustomPermissionEvaluator() {
    }

    @Override
    public boolean hasPermission(Authentication arg0, Object arg1, Object arg2) {
        System.out.println("CustomPermissionEvaluator.hasPermission");
        if (arg0 == null || !arg0.isAuthenticated())
            return false;
        else
            return arg0.getAuthorities().contains(arg1);
    }

    @Override
    public boolean hasPermission(Authentication arg0, Serializable arg1, String arg2, Object arg3) {
        throw new RuntimeException("Id-based permission evaluation not currently supported.");
    }

}

My configuration class MethodSecurityConfig is that:

我的配置类 MethodSecurityConfig 是:

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {

    protected MethodSecurityExpressionHandler createExpressionHandler() {
        System.out.println("MethodSecurityConfig.createExpressionHandler");
        DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
        expressionHandler.setPermissionEvaluator(new CustomPermissionEvaluator());
        return expressionHandler;
    }

}

Full code of my security layer can be found here:

我的安全层的完整代码可以在这里找到:

https://github.com/klebermo/webapp2/tree/master/src/com/spring/webapp/lojavirtual/config/security

https://github.com/klebermo/webapp2/tree/master/src/com/spring/webapp/lojavirtual/config/security

Anyone can point what I am doing wrong here?

任何人都可以指出我在这里做错了什么?

UPDATE

更新

I use the annotation @PreAuthorize in this way:

我以这种方式使用注释@PreAuthorize:

@Controller
@RequestMapping(value="privado")
public class PrivadoController {

    @RequestMapping(value="admin")
    @PreAuthorize("hasPermission('admin_main')")
    public ModelAndView admin() {
        ModelAndView mav = new ModelAndView();
        mav.setViewName("privado/admin");
        return mav;
    }

    @RequestMapping(value="customer")
    @PreAuthorize("hasPermission('customer_main')")
    public ModelAndView customer() {
        ModelAndView mav = new ModelAndView();
        mav.setViewName("privado/customer");
        return mav;
    }

}

采纳答案by Kleber Mota

Ok, finally I get to work done this part of my project. The final code for the CustomPermissionEvaluator is:

好的,最后我开始完成我项目的这一部分。CustomPermissionEvaluator 的最终代码是:

@Component
public class CustomPermissionEvaluator implements PermissionEvaluator {

    public CustomPermissionEvaluator() {
    }

    public boolean hasPermission(Authentication arg0, Object arg1) {
        System.out.println("CustomPermissionEvaluator.hasPermission");
        System.out.println("arg0 = "+arg0);
        System.out.println("arg1 = "+arg1);

        if (arg0 == null || !arg0.isAuthenticated()) {
            System.out.println("false");
            return false;
        }
        else {
            System.out.println("true");
            for(GrantedAuthority authority: arg0.getAuthorities()) {
                if(authority.getAuthority().equals(arg1))
                    return true;
            }
            return false;
        }
    }

    @Override
    public boolean hasPermission(Authentication arg0, Object arg1, Object arg2) {
        System.out.println("CustomPermissionEvaluator.hasPermission");
        System.out.println("arg0 = "+arg0);
        System.out.println("arg1 = "+arg1);
        System.out.println("arg2 = "+arg2);

        if (arg0 == null || !arg0.isAuthenticated()) {
            System.out.println("false");
            return false;
        }
        else {
            System.out.println("true");
            for(GrantedAuthority authority: arg0.getAuthorities()) {
                if(authority.getAuthority().equals(arg2))
                    return true;
            }
            return false;
        }
    }

    @Override
    public boolean hasPermission(Authentication arg0, Serializable arg1, String arg2, Object arg3) {
        throw new RuntimeException("Id-based permission evaluation not currently supported.");
    }

}

回答by Christian St.

... Method hasPermission(java.lang.String) cannot be found ...

The method hasPermission()is called at any time with only one argument, but you provide it with 3 and 4 arguments:

该方法hasPermission()在任何时候都只有一个参数被调用,但是你提供了 3 个和 4 个参数:

public boolean hasPermission(Authentication arg0, Object arg1, Object arg2)
public boolean hasPermission(Authentication arg0, Serializable arg1, String arg2, Object arg3)

Add the method public boolean hasPermission(String permission)and try again.

添加方法public boolean hasPermission(String permission)并重试。

回答by Artem Bilan

You don't show the code where you use hasPermission('admin_main').

您不会在使用hasPermission('admin_main').

Although it is wrong anyway: your CustomPermissionEvaluatordoesn't have a method with single argument. Or in terms of Spring Security like this:

尽管无论如何它都是错误的:您CustomPermissionEvaluator没有带有单个参数的方法。或者就这样的 Spring Security 而言:

boolean hasPermission(Authentication authentication, Object permission);

Maybe do you want to use hasRole('admin_main')?..

也许你想用hasRole('admin_main')?..

The main your problem that you don't provide enough arguments for method implementations.

您的主要问题是您没有为方法实现提供足够的参数。

回答by Kleber Mota

Then I solve the problem presented here changing the call for hasPermission in the methods from my controller. The final code for them are:

然后我解决了这里提出的问题,在我的控制器的方法中更改了对 hasPermission 的调用。他们的最终代码是:

@Controller
@RequestMapping(value="privado")
public class PrivadoController {

    @RequestMapping(value="admin")
    @PreAuthorize("hasPermission(#usuario, 'admin_main')")
    public ModelAndView admin() {
        ModelAndView mav = new ModelAndView();
        mav.setViewName("privado/admin");
        return mav;
    }

    @RequestMapping(value="customer")
    @PreAuthorize("hasPermission(#usuario, 'customer_main')")
    public ModelAndView customer() {
        ModelAndView mav = new ModelAndView();
        mav.setViewName("privado/customer");
        return mav;
    }

}

(Now I am trying find the correct argument for replace #usuario, which is returning a null value, but this is subject for another topic).

(现在我正在尝试找到替换 #usuario 的正确参数,它返回一个空值,但这是另一个主题的主题)。