可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm using Spring Security 3.2.5.RELEASE with ThymeLeaf 2.1.4.RELEASE. I've defined Role Hierarchy in my security context. In my view layer I'm using sec:authorize
attribute to define menu items. I expect to see all menu items under the top level role but I only see the menus defined under that role. How can I fix this problem so that I see all menus under the top level?
Any pointers would be really appreciated. Thanks.
<beans:bean id="roleVoter" class="org.springframework.security.access.vote.RoleHierarchyVoter"> <beans:constructor-arg ref="roleHierarchy"/> </beans:bean> <beans:bean id="roleHierarchy" class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl"> <beans:property name="hierarchy"> <beans:value> ROLE_ADMINISTRATOR > ROLE_MANAGER > ROLE_CONTENT_ADMINISTRATOR </beans:value> </beans:property> </beans:bean>
And in my view page I'm using sec:authorize
attribute like below:
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3"> <body th:fragment="admin-menu" sec:authorize="hasRole('ROLE_ADMINISTRATOR')"> <li> <a href="#"><i class="fa fa-users"></i> <span class="nav-label">Users</span> </a> </li> </body> </html>
回答1:
In order to get the role hierarchy worked in thymeleaf templates as well as in the common security (annotation) config, you need only 2 things:
Make the bean:
@Bean public RoleHierarchyImpl roleHierarchy() { RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl(); String hierarchy = "ADMIN_GLOBAL_MANAGEMENT > ADMIN_COMMON " + "ADMIN_GLOBAL_MANAGEMENT > ADMIN_USER_MANAGEMENT " + "ADMIN_GLOBAL_MANAGEMENT > ADMIN_PAYMENT_MANAGEMENT " + "ADMIN_GLOBAL_MANAGEMENT > ADMIN_MESSAGE_MANAGEMENT"; roleHierarchy.setHierarchy(hierarchy); return roleHierarchy; }
Extend WebSecurityConfigurerAdapter and override a method:
@EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { ... @Override public void configure(WebSecurity web) throws Exception { DefaultWebSecurityExpressionHandler expressionHandler = new DefaultWebSecurityExpressionHandler(); expressionHandler.setRoleHierarchy(roleHierarchy()); web.expressionHandler(expressionHandler); }
回答2:
I had a similar problem with a similar hierarchy. The answer is explained here Spring Security Role Hierarchy issues. This works for me:
<sec:http> ... <sec:expression-handler ref="defaultWebSecurityExpressionHandler" /> ...
<beans:bean id="roleHierarchy" class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl"> <beans:property name="hierarchy"> <beans:value> ROLE_SYSTEMADMIN > ROLE_JOURNALADMIN ROLE_JOURNALADMIN > ROLE_ESUBS ROLE_ESUBS > ROLE_STAFF </beans:value> </beans:property> </beans:bean> <beans:bean id="methodSecurityExpressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler"> <beans:property name = "roleHierarchy" ref="roleHierarchy"/> </beans:bean> <beans:bean id="defaultWebSecurityExpressionHandler" class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler"> <beans:property name="roleHierarchy" ref="roleHierarchy"/> </beans:bean> <beans:bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased"> <beans:constructor-arg> <beans:list> <beans:bean id="roleVoter" class="org.springframework.security.access.vote.RoleHierarchyVoter"> <beans:constructor-arg ref="roleHierarchy" /> </beans:bean> <beans:bean class="org.springframework.security.web.access.expression.WebExpressionVoter"> <beans:property name="expressionHandler" ref="defaultWebSecurityExpressionHandler"/> </beans:bean> </beans:list> </beans:constructor-arg> </beans:bean>
回答3:
As a first instance I tried to update my dependencies, but with no luck.
Shortly what my application have: - web security configuration using role hierarchy - enabled global method security @EnableGlobalMethodSecurity(prePostEnabled = true)
All parts where working properly except Thymeleaf expression sec:authorize="hasRole('ROLE_USER')"
did not take hierarchy into account.
Then I tried to debug, and I found out that when expression was evaluated, there were 2 DefaultWebSecurityExpressionHandler
: - 1 with key webSecurityExpressionHandler
- 1 with key defaultWebSecurityExpressionHandler
(bean defined by me with hierarchy.
So I had 2 options: - either intercept webSecurityExpressionHandler
an d sets role hierarchy on it; or - rename my bean definition from defaultWebSecurityExpressionHandler
to webSecurityExpressionHandler
.
As I don't need to have to security expression handler, I picked option number 2.
Note: In case you want to see if you don't have any other beans, see org.thymeleaf.extras.springsecurity4.auth.AuthUtils@243
(Line 243, method getExpressinHandler)
This might be the case in older version (inlcuding Thymeleaf 2.x.x)