spring -security: авторизация без аутентификации

Я пытаюсь интегрировать Spring Security в свое веб-приложение. Это кажется довольно простым, если вы интегрируете весь процесс аутентификации и авторизации.

Однако и аутентификация, и авторизация кажутся настолько связанными, что мне требуется очень много времени, чтобы понять, как я могу разделить эти процессы и получить аутентификацию независимо от авторизации.

Процесс аутентификации является внешним по отношению к нашей системе (на основе единого входа), и его нельзя изменить. Тем не менее, как только пользователь завершает этот процесс, он загружается в сеанс, включая роли.

Мы пытаемся использовать эту информацию для процесса авторизации Spring Security, то есть заставить его получать роли из пользовательского сеанса вместо того, чтобы получать их через провайдер аутентификации.

Есть ли способ добиться этого?


person markitus82    schedule 24.08.2009    source источник


Ответы (7)


Если ваша аутентификация уже выполнена с использованием службы единого входа, вам следует использовать один из Spring security фильтры предварительной аутентификации. Затем вы можете указать службу UserDetails (возможно, настраиваемую), которая будет использовать принцип предварительно аутентифицированного пользователя для заполнения GrantedAuthority

SpringSecurity включает несколько фильтров предварительной аутентификации, включая J2eePreAuthenticatedProcessingFilter и RequestHeaderPreAuthenticatedProcessingFilter. Если вы не можете найти тот, который работает для вас, также возможно, и не так сложно написать свой собственный, при условии, что вы знаете, где в запросе ваша реализация SSO заполняет данные. (Это, конечно, зависит от реализации.)

Просто реализуйте интерфейс Filter и выполните что-нибудь вроде это в методе doFilter:

public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {

    // principal is set in here as a header or parameter. you need to find out 
    // what it's named to extract it
    HttpServletRequest req = (HttpServletRequest) request; 

    if (SecurityContextHolder.getContext().getAuthentication() == null) {
        // in here, get your principal, and populate the auth object with 
        // the right authorities
        Authentication auth = doAuthentication(req); 
        SecurityContextHolder.getContext().setAuthentication(auth);
    }

    chain.doFilter(request, response);
}
person nont    schedule 24.08.2009
comment
привет нет, я работал над этим. Ваш ответ очень полезен, хотя теперь я должен отложить этот вопрос на несколько дней. Я вернусь к нему и расскажу, как дела. Спасибо! - person markitus82; 26.08.2009
comment
Для нашего приложения этого было недостаточно ... Мне нужно было добавить в сеанс также SecurityContext следующим образом: session.setAttribute (HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext ()); - person A. Masson; 23.05.2013
comment
@ markitus82 Вы написали для этого какую-нибудь специальную службу информации о пользователях? Я застрял в одной и той же истории. - person GaneshSreeju; 06.05.2019

Да, это возможно. Spring Security (как и большая часть остальной части Spring) управляется интерфейсом, поэтому вы можете выборочно подключать свои собственные реализации для разных частей фреймворка.

Обновление: механизмы авторизации и аутентификации Spring работают вместе - механизм аутентификации аутентифицирует пользователя и вставляет различные GrantedAuthority экземпляры в контекст безопасности. Затем они будут проверены механизмом авторизации, чтобы разрешить / запретить определенные операции.

Для получения подробной информации о том, как использовать уже существующую аутентификацию, используйте ответ «нет». Детали того, как вы получаете детали из своего сеанса (например, роли), конечно, будут зависеть от вашей конкретной настройки. Но если вы добавите GrantedAuthority экземпляры, полученные из ролей, предварительно заполненных в вашем сеансе вашей системой единого входа, вы сможете использовать их в своей логике авторизации.

Из справочной документации (с небольшими изменениями, с моим акцентом):

Вы можете (и многие пользователи) написать свои собственные фильтры или контроллеры MVC для обеспечения взаимодействия с системами аутентификации, которые не основаны на Spring Security. Например, вы можете использовать управляемую аутентификацию контейнера, которая делает текущего пользователя доступным из ThreadLocal или JNDI местоположения. Или вы можете работать в компании, у которой есть устаревшая проприетарная система аутентификации, которая является корпоративным «стандартом», над которым у вас мало контроля. В таких ситуациях довольно легко заставить Spring Security работать и при этом обеспечивать возможности авторизации. Все, что вам нужно сделать, это написать фильтр (или эквивалент), который считывает информацию о сторонних пользователях из местоположения, создать объект Authentication, относящийся к Spring Security, и поместить его в SecurityContextHolder. Это довольно просто сделать, и это полностью поддерживаемый подход к интеграции.

person Vinay Sajip    schedule 24.08.2009
comment
но нужно ли настраивать AuthenticationProvider? - person markitus82; 24.08.2009
comment
Да, но это не обязательно должен быть другой объект, чем провайдер авторизации: вы можете создать класс, который реализует и то, и другое (поскольку ваша система единого входа, похоже, также предоставляет вам оба). - person Aaron Digulla; 24.08.2009
comment
Дело в том, что форма входа (аутентификация) в моем приложении осуществляется внешними системами. все, что у меня есть, это сеанс пользователя, и пользователь уже аутентифицирован. Я хотел бы знать, как я могу получить идентификатор пользователя и роли из сеанса, чтобы использовать авторизацию Spring. - person markitus82; 24.08.2009
comment
Вы должны запросить идентификатор пользователя и роли у внешней системы, которая провела аутентификацию. - person rodrigoap; 24.08.2009

Сервер, который обрабатывает аутентификацию, должен перенаправить пользователя в приложение, передав ему какой-то ключ (токен в CAS SSO). Затем приложение использует ключ, чтобы запросить у сервера аутентификации имя пользователя и связанные роли. С помощью этой информации создайте контекст безопасности, который передается диспетчеру авторизации. Это очень упрощенная версия рабочего процесса входа в систему через систему единого входа.
Ознакомьтесь с системой единого входа в системе CAS и Архитектура CAS 2.
Сообщите мне, если вам нужна дополнительная информация.

person rodrigoap    schedule 24.08.2009

у нас было такое же требование, когда мы должны были использовать Spring безопасность только для целей авторизации. Мы использовали Siteminder для аутентификации. Вы можете найти более подробную информацию о том, как использовать авторизационную часть Spring Security, а не аутентификацию, здесь: http://codersatwork.wordpress.com/2010/02/13/use-spring-security-for-authorization-only-not-for-authentication/ < / а>

Я также добавил исходный код и тестовые примеры по адресу http://code.google.com/p/spring-security-with-authorization-only/source/browse/

person Ben W    schedule 17.02.2010

Я пытаюсь понять аутентификацию CAS с нашей собственной авторизацией и запутался, так как объект User в Spring Security всегда ожидает, что пароль будет заполнен, и нас это не волнует в нашем сценарии. После прочтения сообщения Сураба кажется, что уловка состоит в том, чтобы вернуть пользовательский объект User без введенного пароля. Я попробую это сделать и посмотрю, сработает ли это в моем случае. Надеюсь, никакой другой код в цепочке не будет ожидать пароля в объекте User.

person SinusRhythm    schedule 18.02.2010

Я использую авторизацию по этому:

  1. Внедрить компонент, связанный с авторизацией, в мой собственный компонент:

    @Autowired
    private AccessDecisionManager    accessDecisionManager;
    @Autowired
    FilterSecurityInterceptor        filterSecurityInterceptor;
    
  2. Используйте этот bean-компонент следующим образом:

    FilterInvocation fi = new FilterInvocation(rundata.getRequest(), rundata.getResponse(), new FilterChain() {
    
        public void doFilter(ServletRequest arg0, ServletResponse arg1) throws IOException, ServletException {
            // TODO Auto-generated method stub
    
        }
    });
    FilterInvocationDefinitionSource objectDefinitionSource = filterSecurityInterceptor.getObjectDefinitionSource();
    ConfigAttributeDefinition attr = objectDefinitionSource.getAttributes(fi);
    Authentication authenticated = new Authentication() {
    
        ...........
    
        public GrantedAuthority[] getAuthorities() {
            GrantedAuthority[] result = new GrantedAuthority[1];
            result[0] = new GrantedAuthorityImpl("ROLE_USER");
            return result;
        }
    };
    accessDecisionManager.decide(authenticated, fi, attr);
    
person Aimar    schedule 16.09.2011

Я тоже потратил много часов на изучение того, как реализовать настраиваемую авторизацию без аутентификации.
Процесс аутентификации является внешним по отношению к нашей системе (на основе единого входа). Я сделал это, как указано ниже, и это работает !!! (Я уверен, что есть много других способов сделать это лучше, но этот способ достаточно хорошо подходит для моего сценария)

Сценарий: Пользователь уже аутентифицирован внешней системой, и вся информация, необходимая для авторизации, присутствует в запросе.

1. Необходимо создать конфигурацию безопасности, включающую глобальную безопасность метода, как показано ниже.

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
class SpringWebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(final HttpSecurity http) throws Exception {
    }
}

2.) Реализуйте Spring PermissionEvaluator, чтобы разрешить или отклонить запрос.

@Component
public class CustomPermissionEvaluator implements PermissionEvaluator {

    public boolean authorize(final String groups, final String role) {
        boolean allowed = false;
        System.out.println("Authorizing: " + groups + "...");
        if (groups.contains(role)) {
            allowed = true;
            System.out.println(" authorized!");
        }
        return allowed;
    };

    @Override
    public boolean hasPermission(final Authentication authentication, final Object groups, final Object role) {
        return authorize((String) groups, (String) role);
    };

    @Override
    public boolean hasPermission(final Authentication authentication, final Serializable targetId, final String targetType, final Object permission) {
        return authorize((String) targetId, (String) permission);
    };
}

3.) Добавить MethodSecurityConfig

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {

    @Override
    protected MethodSecurityExpressionHandler createExpressionHandler() {
        DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
        expressionHandler.setPermissionEvaluator(new CustomPermissionEvaluator());
        return expressionHandler;
    }
}

4.) Добавьте @PreAuthorize в свой контроллер, как показано ниже. В этом примере все группы пользователя представлены в заголовке запроса с ключом availableUserGroups. Затем он передается CustomPermissionEvaluator для проверки авторизации. Обратите внимание, что spring автоматически передает объект аутентификации методу hasPermission. Так что в случае, если вы хотите загрузить пользователя и проверить с помощью весеннего метода hasRole, это можно использовать.

@PreAuthorize("hasPermission(#userGroups, 'ADMIN')")
@RequestMapping(value = "/getSomething")
public String getSomething(@RequestHeader(name = "availableUserGroups") final String userGroups) {
    return "resource allowed to access";
}

Обработка других сценариев: 1.) В сценарии, где вы хотите загрузить пользователя, прежде чем вы сможете выполнить авторизацию. Вы можете использовать весеннюю предварительную аутентификацию фильтры, и делаем это аналогичным образом. Пример ссылки: http://www.learningthegoodstuff.com/2014/12/spring-security-pre-authentication-and.html

person tigersagar    schedule 27.11.2018