1

我按照本指南使用 ACL 设置安全性,效果很好。之后我还尝试在 WebSecurityConfigurerAdapter 中实现 ACL。所以我设置了一个 bean,它会创建一个 DefaultWebSecurityExpressionHandler:

    @Bean
    public DefaultWebSecurityExpressionHandler webExpressionHandler(AclPermissionEvaluator aclPermissionEvaluator) {
        final DefaultWebSecurityExpressionHandler webSecurityExpressionHandler = new DefaultWebSecurityExpressionHandler();
        AclPermissionEvaluator permissionEvaluator = aclPermissionEvaluator();
        webSecurityExpressionHandler.setPermissionEvaluator(permissionEvaluator);
        return webSecurityExpressionHandler;
    }

我会将它应用于我的 WebSecurityConfigurerAdapter 中的 HttpSecurity:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable()
        .authorizeRequests()
        .expressionHandler(webExpressionHandlerWithACL)
        .antMatchers(HttpMethod.PUT, "/api/user/users/{ID}").access("isAuthenticated() and hasPermission(#ID, 'xxx.xxx.xxx.xxx.xxx.UserDto', 'write')")
        .anyRequest().authenticated()
        .and()
        .exceptionHandling().authenticationEntryPoint(authenticationEntryPoint)
        .and()
        .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

    http.addFilterBefore(filter, UsernamePasswordAuthenticationFilter.class);
}

但这只是行不通。这个完全相同的表达式在 @PreAuthorize 标记中起作用,但在这里它不起作用。我调试了一下,发现准确的故障点在Spring提供的JdbcAclServiceImpl类中,方法如下:

@Override
public Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, List<Sid> sids)
        throws NotFoundException {
    Map<ObjectIdentity, Acl> result = this.lookupStrategy.readAclsById(objects, sids);
    // Check every requested object identity was found (throw NotFoundException if
    // needed)
    for (ObjectIdentity oid : objects) {
        if (!result.containsKey(oid)) {
            throw new NotFoundException("Unable to find ACL information for object identity '" + oid + "'");
        }
    }
    return result;
}

即使提供的参数与我使用 @PreAuthorize 标记时相同,result.containsKey(oid)但即使我可以在调试器中看到它并且我看到oid应该匹配它,也只是无法找到 acl。

所以我的问题是:Spring Security ACL 是否应该工作以保护路由,还是仅用于保护方法?

顺便说一句,我正在使用 Spring Boot 2.5.5

4

1 回答 1

0

我发现了问题。该类AclPermissionEvaluator有一个public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission)被调用的方法。如果我将它用作 webExpressionHandler,那么Serializable targetId它总是一个字符串。但要使它起作用,它需要一个 Long。因此,一种解决方案是扩展AclPermissionEvaluator和覆盖有问题的方法,以便将 String 转换为 Long,然后它可以工作。不要忘记然后实际使用自定义AclPermissionEvaluator

于 2022-02-20T14:01:57.893 回答