spring-security: авторизация без аутентификации - PullRequest
20 голосов
/ 24 августа 2009

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

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

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

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

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

Ответы [ 7 ]

22 голосов
/ 24 августа 2009

Если ваша аутентификация уже выполнена с использованием службы единого входа, вам следует использовать один из фильтров предварительной аутентификации 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);
}
3 голосов
/ 24 августа 2009

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

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

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

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

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

2 голосов
/ 24 августа 2009

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

1 голос
/ 16 сентября 2011

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

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

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

    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);
    
1 голос
/ 18 февраля 2010

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

1 голос
/ 17 февраля 2010

у нас было такое же требование, когда мы должны были использовать пружинную защиту только для авторизации. Мы использовали 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/

0 голосов
/ 27 ноября 2018

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

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

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

...