jsp - 如何修复我用于方法级别安全性的角色层次结构
问题描述
我正在一个大型(28 个不同大小的控制器)jsp 项目中的控制器功能上实现方法级安全性(@PreAuthorize("hasRole('ROLE_OD')"))。权限很复杂,但有些角色是分层的:
ROLE_ADMIN > ROLE_OD ROLE_OD > ROLE_PD ROLE_PD > 成员 ROLE_ADMIN > ROLE_BGC
目前,如果角色层次结构由一个级别(ROLE_ADMIN > ROLE_OD)组成,则它适用于多个级别(ROLE_ADMIN > ROLE_OD ROLE_OD > ROLE_PD),我不知道为什么。
我不知道这是否重要,但我已经自定义了 User 和 UserPrivilege 对象,以便我可以在控制器方法中验证用户仅限于访问他们的信息。所有这些都有效,我可以从每个方法中成功访问 @AuthenticationPrincipal User 用户参数。当访问被拒绝时,我还可以查看每个用户的grantedAuthorities 以验证他们应该具有访问权限。
我以前从未输入过问题,所以我不确定多少代码就足够了,或者太多了,但我会尽力为您提供帮助我所需的一切。
我用 2 天时间研究了所有能找到的文档,并尝试了 5 种不同的方式来设置项目。我现在拥有它的方式,它适用于使用@PreAuthorize 的一个级别,但不适用于@Secure,即使我为此启用它也是如此。我还注意到,如果我不在层次结构中按降序排列角色,那么它甚至不会编译。我尝试了上千种不同的语法。
@PreAuthorize("hasRole('ROLE_OD')")
@RequestMapping(value="/testAccess",method = RequestMethod.GET)
public void testAccess(@AuthenticationPrincipal User user) {
System.out.println("user has access to this method!");
}
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class MethodLevelConfiguration extends GlobalMethodSecurityConfiguration {
@Bean
public RoleHierarchyImpl roleHierarchy(){
RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
roleHierarchy.setHierarchy("ROLE_ADMIN > ROLE_OD and ROLE_OD > ROLE_PD");
return roleHierarchy;
}
@Bean
public RoleVoter roleVoter() {
return new RoleHierarchyVoter(roleHierarchy());
}
@Autowired
private RoleHierarchy roleHierarchy;
@Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
expressionHandler.setPermissionEvaluator(new PermissionEvaluatorImpl());
expressionHandler.setRoleHierarchy(roleHierarchy);
return expressionHandler;
}
}
@Configuration
// @EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private PasswordEncoder myPasswordEncoder;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private WebAuthenticationDetailsSourceImpl authenticationDetailsSource;
@Bean
public WebAuthenticationDetailsSourceImpl authenticationDetailsSource() {
return new WebAuthenticationDetailsSourceImpl();
}
@Bean
public PasswordEncoder myPasswordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public DaoAuthenticationProvider authProvider() {
AuthenticationProviderImpl authProvider = new AuthenticationProviderImpl();
authProvider.setUserDetailsService(userDetailsService);
authProvider.setPasswordEncoder(myPasswordEncoder());
return authProvider;
}
@Bean(name = BeanIds.AUTHENTICATION_MANAGER)
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(myPasswordEncoder);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
[.antMatchers() here...]
http.headers().frameOptions().sameOrigin();
}
如果我以具有 ROLE_PD 或 ROLE_ADMIN 的用户身份登录,我会收到打印消息“用户有权访问此方法!”
如果我以具有 ROLE_OD 的用户身份登录,我会收到错误:.mmaExceptionHandlerExceptionResolver : Resolved [org.springframework.security.access.AccessDeniedException: Access is denied]
解决方案
您必须使用行分隔符分隔角色层次结构,请参阅Spring Security Reference:
11.1.4 分层角色
[...]
角色层次结构的使用允许您配置哪些角色(或权限)应包括其他角色。Spring Security 的 RoleVoter 的扩展版本,
RoleHierarchyVoter
配置了RoleHierarchy
,从中获取分配给用户的所有“可访问权限”。典型的配置可能如下所示:<bean id="roleVoter" class="org.springframework.security.access.vote.RoleHierarchyVoter"> <constructor-arg ref="roleHierarchy" /> </bean> <bean id="roleHierarchy" class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl"> <property name="hierarchy"> <value> ROLE_ADMIN > ROLE_STAFF ROLE_STAFF > ROLE_USER ROLE_USER > ROLE_GUEST </value> </property> </bean>
和源代码RoleHierarchyImpl
:
[...]
/** * Parse input and build the map for the roles reachable in one step: the higher role * will become a key that references a set of the reachable lower roles. */ private void buildRolesReachableInOneStepMap() { this.rolesReachableInOneStepMap = new HashMap<>(); for (String line : this.roleHierarchyStringRepresentation.split("\n")) {
[...]
推荐阅读
- javascript - HTML,打开链接点击页面上的任意位置
- ios - 将图像从 collectionView 传递到 tableviewcell
- php - 如何进行非阻塞 php exec 调用?
- scala - scala Akka中的Mallet Api抛出错误-请求遇到请求超时[GET /mallet Empty]
- r - 在 R 中为诊断图添加标签
- c++ - 使用 SDL2 和 OpenGL 使用 SDL TTF 显示文本
- list - 如何使用 AWS Amplify 和 Graphql 在 dynamodb 中附加列表对象
- parsing - 为什么无法解析字符串 | 锈
- python - 美丽的汤输出不是很可读
- kubernetes - 在 Container/Kubernetes/Docker 中部署 chef