Динамический контроль разрешений Spring Security очень прост | Заметки по отладке Java

Spring Boot Java
Динамический контроль разрешений Spring Security очень прост | Заметки по отладке Java

Эта статья участвует в "Месяце тем Java - Заметки по отладке Java", подробности см.Ссылка на мероприятие

Перед учебником динамического контроля доступа мы пользовательFilterInvocationSecurityMetadataSourceиAccessDecisionManager Два интерфейса реализуют динамический контроль разрешений. Есть много вещей, которые нам нужно сделать здесь, и есть определенная стоимость обучения. Сегодня я представлю более простой и понятный метод реализации динамического контроля разрешений.

Управление доступом на основе выражений

httpSecurity.authorizeRequests()
    .anyRequest()
    .access("hasRole('admin')")

Излишне говорить, что таким образом мы настроили выражениеhasRole('admin'), Spring Security позвонитSecurityExpressionRootизhasRole(String role)Способ определить, имеет ли текущий пользователь рольadmin, а потом принимать решение, выпускать или нет. Помимо статического управления разрешениями, этот метод также может динамически управлять разрешениями.

Выражения управления доступом на основе компонентов

Spring Security расширяет выражения для поддержки ссылок на любые общедоступныеSpring Bean, если у нас есть реализация следующего интерфейсаSpring Bean:

/**
 * 角色检查器接口.
 *
 * @author n1
 * @since 2021 /4/6 16:28
 */
public interface RoleChecker extends InitializingBean {

    /**
     * Check boolean.
     *
     * @param authentication the authentication
     * @param request        the request
     * @return the boolean
     */
    boolean check(Authentication authentication, HttpServletRequest request);
}

Проверка ролей на основе JDBC, здесь лучше всего сделать кеш:

/**
 * 基于jdbc的角色检查 最好这里做个缓存
 * @author n1
 * @since 2021/4/6 16:43
 */
public class JdbcRoleChecker implements RoleChecker {
    // 系统集合的抽象实现,这里你可以采用更加合理更加效率的方式
    private Supplier<Set<AntPathRequestMatcher>> supplier;


    @Override
    public boolean check(Authentication authentication, HttpServletRequest request) {
        Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();

       // 当前用户的角色集合
        System.out.println("authorities = " + authorities);
        //todo 这里自行实现比对逻辑
       //   supplier.get().stream().filter(matcher -> matcher.matches(request));
       // true false 为是否放行
        return true;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        Assert.notNull(supplier.get(), "function must not be null");
    } 
}

Мы можем настроить это такHttpSecurity:

httpSecurity.authorizeRequests()
    .anyRequest()
    .access("@roleChecker.check(authentication,request)")

пройти черезRoleCheckerсерединаAuthenticationМы можем получить информацию о текущем пользователе, особенно о наборе разрешений. пройти черезHttpServletRequestмы можем получить текущий запросURI. ДолженURIПравильное решение о доступе можно принять, оценив пересечение набора разрешений в системе и набора разрешений пользователя.

параметр пути

Иногда наш визитURIтакже содержит параметры пути, например./foo/{id}. Мы также можем комбинировать определенные выражения управления доступом на основе bean-компонентов сidзначение для контроля. Это должно быть написано так:

/**
 * 角色检查器接口.
 *
 * @author n1
 * @since 2021 /4/6 16:28
 */
public interface RoleChecker extends InitializingBean {

    /**
     * Check boolean.
     *
     * @param authentication the authentication
     * @param request        the request
     * @return the boolean
     */
    boolean check(Authentication authentication, String id);
}

Соответствующая конфигурация:

httpSecurity.authorizeRequests()
    .antMatchers("/foo/{id}/**")
    .access("@roleChecker.check(authentication,#id)")

так когда/foo/123Как только запрос перехвачен,123будет назначеноcheckв методеidиметь дело с.

Суммировать

Динамическое управление разрешениями этого выражения легче понять и понять, чем предыдущий метод. Но у него также есть свои ограничения, например, тип параметра в методе в выражении относительно один. и черезFilterInvocationSecurityMetadataSourceЭтот метод является более мощным и может настраивать некоторые решения доступа, что подходит для более сложных сценариев. Я:Код Фермер Маленький Толстый БратБольшое внимание делиться более оригинальным программированием сухим.