Как предоставить пользователям доступ к адресам, начинающимся с определённого сочетания, в соответствии с их ролями?

Как настроить Spring Security так, чтобы у пользователя с определённой ролью был доступ только к URL, начинающихся с определённого значения? В данном случае задача такая:

USER → все URL, начинающиеся с /user (например, /user, /user/, /user/update-info)

ADMIN → все URL, начинающиеся с /admin (например, /admin, /admin/, /admin/update-user)

Пробовал так (должно работать, я считаю!)

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/admin", "/admin/**").hasRole("ADMIN")
                .antMatchers("/user", "/user/**").hasRole("USER")
                .anyRequest().authenticated()
                .and().formLogin().successHandler(successUserHandler)
                .and().logout().logoutUrl("/logout").logoutSuccessUrl("/login");
    }

и так

// ...
                .antMatchers("/admin/", "/admin/**").hasRole("ADMIN")
                .antMatchers("/user/", "/user/**").hasRole("USER")
// ...

и ещё несколько вариаций. Всё одно – ошибка 403 ("forbidden", то есть нет прав)

Мэтчеры могут работать шиворот-навыворот

введите сюда описание изображения

введите сюда описание изображения

введите сюда описание изображения

Но одновременно и нет

введите сюда описание изображения

введите сюда описание изображения

Все скриншоты сделаны после входа в пользователя mickey_m, который имеет роль USER. Джоинтейбл:

введите сюда описание изображения

Как мне реализовать свою задачу и почему Spring Security так себя ведёт (на мой взгляд, странно)?

Версия Boot 2.6.2, а Security – 5.6.1. Гуглил по такому запросу. Репо здесь (Security конфиг может отличаться от того, что на скриншотах)

Я знаю, что скриншоты здесь не любят, но я действительно не знаю, как передать эту информацию столь же полно и достоверно с помощью текста

UPD: Запустил с дебаг-логом и увидел это. Возможно, это связано с проблемой. Но почему он проверяет с префиксом? Я префиксы нигде не ставил. Зашёл в класс FilterSecurityInterceptor, но ничего там не увидел

DEBUG 3888 --- [nio-8080-exec-6] o.s.s.w.a.i.FilterSecurityInterceptor    : Failed to authorize filter invocation [GET /user] with attributes [hasRole('ROLE_USER')]

UPD2: Кажется, я нашёл бандита, который мне всё портит (SecurityExpressionRoot). Но как его обезвредить? Как сделать так, чтобы роли проверялись без этого дефолтного суффикса?

public abstract class SecurityExpressionRoot implements SecurityExpressionOperations {
// ...
private String defaultRolePrefix = "ROLE_";
// ...
    public final boolean hasRole(String role) {
        return this.hasAnyRole(role);
    }

    public final boolean hasAnyRole(String... roles) {
        return this.hasAnyAuthorityName(this.defaultRolePrefix, roles);
    }

    private boolean hasAnyAuthorityName(String prefix, String... roles) {
        Set<String> roleSet = this.getAuthoritySet();
        String[] var4 = roles;
        int var5 = roles.length;

        for(int var6 = 0; var6 < var5; ++var6) {
            String role = var4[var6];
            String defaultedRole = getRoleWithDefaultPrefix(prefix, role);
            if (roleSet.contains(defaultedRole)) {
                return true;
            }
        }

        return false;
    }

UPD3: Слава чатботам (мне помог Sage)! ? Когда роботы восстанут против людей, я займу нейтралитет ?

    @Bean
    public GrantedAuthorityDefaults grantedAuthorityDefaults() {
        return new GrantedAuthorityDefaults(""); // удаление дефолтного префикса "ROLE_"
    }

Ответы (0 шт):