在sec中连接字符串和变量:授权thymeleaf标记

时间:2015-01-03 15:01:43

标签: spring spring-security spring-boot thymeleaf

我正在尝试使用thymeleaf标签:这样授权:

sec:authorize="hasPermission(#user, 'listagem_${item.simpleName}')"

但是当我部署并运行项目时,不会处理字符串listagem_${item.simpleName},因此不会显示内容。

任何人都知道能够在sec:authorize标签内进行连接的正确方法吗?

更新

尝试之后:

<span th:text="|hasPermission(#user, 'listagem_${item.simpleName}')|"></span>

看到我得到了正确的结果,我尝试将表达式|hasPermission(#user, 'listagem_${item.simpleName}')|传输到sec:authorize标签,如下所示:

<li th:each="item : ${menu}" sec:authorize="|hasPermission(#user, 'listagem_${item.simpleName}')|">

但是我收到了这个错误:

    Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.thymeleaf.exceptions.TemplateProcessingException: An error happened trying to parse Spring Security access expression "|hasPermission(#user, 'listagem_${item.simpleName}')|" (private/home:40)] with root cause

org.springframework.expression.spel.SpelParseException: EL1069E:(pos 0): missing expected character '|'
        at org.springframework.expression.spel.standard.Tokenizer.process(Tokenizer.java:194)
        at org.springframework.expression.spel.standard.Tokenizer.<init>(Tokenizer.java:84)
        at org.springframework.expression.spel.standard.InternalSpelExpressionParser.doParseExpression(InternalSpelExpressionParser.java:121)
        at org.springframework.expression.spel.standard.SpelExpressionParser.doParseExpression(SpelExpressionParser.java:60)
        at org.springframework.expression.spel.standard.SpelExpressionParser.doParseExpression(SpelExpressionParser.java:32)
        at org.springframework.expression.common.TemplateAwareExpressionParser.parseExpression(TemplateAwareExpressionParser.java:76)
        at org.springframework.expression.common.TemplateAwareExpressionParser.parseExpression(TemplateAwareExpressionParser.java:62)
        at org.thymeleaf.extras.springsecurity3.auth.AuthUtils.authorizeUsingAccessExpression(AuthUtils.java:186)
        at org.thymeleaf.extras.springsecurity3.dialect.processor.AuthorizeAttrProcessor.isVisible(AuthorizeAttrProcessor.java:100)
        at org.thymeleaf.processor.attr.AbstractConditionalVisibilityAttrProcessor.processAttribute(AbstractConditionalVisibilityAttrProcessor.java:58)
        at org.thymeleaf.processor.attr.AbstractAttrProcessor.doProcess(AbstractAttrProcessor.java:87)
        at org.thymeleaf.processor.AbstractProcessor.process(AbstractProcessor.java:212)
        at org.thymeleaf.dom.Node.applyNextProcessor(Node.java:1016)
        at org.thymeleaf.dom.Node.processNode(Node.java:971)
        at org.thymeleaf.dom.NestableNode.computeNextChild(NestableNode.java:672)
        at org.thymeleaf.dom.NestableNode.doAdditionalProcess(NestableNode.java:655)
        at org.thymeleaf.dom.Node.processNode(Node.java:990)
        at org.thymeleaf.dom.NestableNode.computeNextChild(NestableNode.java:672)
        at org.thymeleaf.dom.NestableNode.doAdditionalProcess(NestableNode.java:655)
        at org.thymeleaf.dom.Node.processNode(Node.java:990)
        at org.thymeleaf.dom.NestableNode.computeNextChild(NestableNode.java:672)
        at org.thymeleaf.dom.NestableNode.doAdditionalProcess(NestableNode.java:655)
        at org.thymeleaf.dom.Node.processNode(Node.java:990)
        at org.thymeleaf.dom.NestableNode.computeNextChild(NestableNode.java:672)
        at org.thymeleaf.dom.NestableNode.doAdditionalProcess(NestableNode.java:655)
        at org.thymeleaf.dom.Node.processNode(Node.java:990)
        at org.thymeleaf.dom.NestableNode.computeNextChild(NestableNode.java:672)
        at org.thymeleaf.dom.NestableNode.doAdditionalProcess(NestableNode.java:655)
        at org.thymeleaf.dom.Node.processNode(Node.java:990)
        at org.thymeleaf.dom.NestableNode.computeNextChild(NestableNode.java:672)
        at org.thymeleaf.dom.NestableNode.doAdditionalProcess(NestableNode.java:655)
        at org.thymeleaf.dom.Node.processNode(Node.java:990)
        at org.thymeleaf.dom.NestableNode.computeNextChild(NestableNode.java:672)
        at org.thymeleaf.dom.NestableNode.doAdditionalProcess(NestableNode.java:655)
        at org.thymeleaf.dom.Node.processNode(Node.java:990)
        at org.thymeleaf.dom.Document.process(Document.java:93)
        at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1155)
        at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1060)
        at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1011)
        at org.thymeleaf.spring4.view.ThymeleafView.renderFragment(ThymeleafView.java:335)
        at org.thymeleaf.spring4.view.ThymeleafView.render(ThymeleafView.java:190)
        at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1228)
        at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1011)
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:955)
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:877)
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966)
        at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:857)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:618)
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:725)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        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.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:537)
        at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1085)
        at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:658)
        at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:222)
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1556)
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1513)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.lang.Thread.run(Thread.java:745)

我在这里缺少什么?

2 个答案:

答案 0 :(得分:1)

我一直遇到类似字符串连接和百日咳sec:authorize属性的问题,尽管不完全相同的情况下它可能对遇到这个问题的其他人有用。

我想根据用户(主体)权限限制某些元素的可见性。在这个例子中,我有一个显示客户详细信息的页面,其他用户可以访问,但只有&#34;客户经理&#34;可以看到电子邮件地址。当我对权限字符串进行硬编码时,一切正常:

<th:block sec:authorize="hasAuthority('VIEW_USER_EMAIL')"> ... </th:block>

我宁愿不在我的模板上散布随机字符串,因为它们很可能在某些时候被重构并且容易出错。我有一个包含大量public static final String字段的类,名为Permission。我本来希望使用enum,但我无法通过我在应用程序see this question for more details其他位置使用的@PreAuthorize@Secured这样的注释进行引用

解决方案是从模板中的表达式引用我的Permission类。这可以使用SpEL type operator T()来实现。我在通过试验错误获得语法方面遇到了一些麻烦,直到最后这个工作:

<th:block sec:authorize="hasAuthority(T(com.example.app.Permission).VIEW_USER_EMAIL)"> ... </th:block>

现在这意味着如果Permission类或VIEW_USER_EMAIL字段不存在或者存在拼写错误,则会抛出异常。这是对静默失败并且可能拒绝访问的巨大改进。

以下是我之前尝试过的一些尝试:

sec:authorize="hasAuthority('${T(com.example.app.Permission).VIEW_USER_EMAIL}')" sec:authorize="hasAuthority(${T(com.example.app.Permission).VIEW_USER_EMAIL})" sec:authorize="${hasAuthority('T(com.example.app.Permission).VIEW_USER_EMAIL')}"

看起来像你的传递的任何表达式中的一个前导${和尾随}的百里香弹簧安全方言条带并试图评估整个表达式,这就是为什么任何形式的连接可能都没有&# 39;工作。

供参考,这是我的Permission课程:

public final class Permission { public static final String VIEW_USER_EMAIL = "VIEW_USER_EMAIL"; }

答案 1 :(得分:1)

在我的情况下,我在变量中有用户角色名称。我终于设法使它与

一起工作了
<div th:if="${#authorization.expression('hasRole('''+objectDTO.roleName+''')')}"></div>

这个想法来自这里(注意用双引号来逃避名称)https://github.com/thymeleaf/thymeleaf-extras-springsecurity#using-the-expression-utility-objects