#spring #spring-security #spring-security-acl
Вопрос:
Я следовал этому руководству, чтобы настроить безопасность с помощью списков управления доступом, которые отлично работают. После этого я также попытался реализовать ACL в WebSecurityConfigurerAdapter. Итак, я настроил компонент, который создаст DefaultWebSecurityExpressionHandler:
@Bean
public DefaultWebSecurityExpressionHandler webExpressionHandler(AclPermissionEvaluator aclPermissionEvaluator) {
final DefaultWebSecurityExpressionHandler webSecurityExpressionHandler = new DefaultWebSecurityExpressionHandler();
AclPermissionEvaluator permissionEvaluator = aclPermissionEvaluator();
webSecurityExpressionHandler.setPermissionEvaluator(permissionEvaluator);
return webSecurityExpressionHandler;
}
И я бы применил его к HttpSecurity в моем WebSecurityConfigurerAdapter:
@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, но здесь его просто нет.
Я отладил его и обнаружил, что точная точка сбоя находится в классе JdbcAclServiceImpl, предоставляемом Spring в следующем методе:
@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 resu<
}
Несмотря на то, что предоставленные параметры такие же, как если бы я использовал тег @PreAuthorize , result.containsKey(oid)
just НЕ МОЖЕТ найти acl в, хотя я вижу его с помощью отладчика, и я вижу, что oid
он должен соответствовать ему.
Итак, мой вопрос: должен ли Spring Security ACL вообще работать для защиты маршрутов или он должен использоваться только для защиты методов?
кстати, я использую Spring boot 2.5.5
Ответ №1:
Я нашел проблему. У класса AclPermissionEvaluator
есть метод public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission)
, который вызывается. Если я использую его как webExpressionHandler, то Serializable targetId
это всегда строка. Но для того, чтобы это сработало, оно должно быть длинным. Итак, одним из решений является расширение AclPermissionEvaluator
и переопределение рассматриваемого метода, чтобы он преобразовывал строку в Long, а затем она работала. Не забудьте затем фактически использовать пользовательский AclPermissionEvaluator
.