Как получить подробную информацию о пользователях, прошедших аутентификацию с помощью Waffle?

Я использую Spring Security в сочетании с Waffle для аутентификации пользователей моего веб-приложения. Я настроил Spring Security со следующей конфигурацией:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

import waffle.servlet.spi.BasicSecurityFilterProvider;
import waffle.servlet.spi.NegotiateSecurityFilterProvider;
import waffle.servlet.spi.SecurityFilterProvider;
import waffle.servlet.spi.SecurityFilterProviderCollection;
import waffle.spring.NegotiateSecurityFilter;
import waffle.spring.NegotiateSecurityFilterEntryPoint;
import waffle.windows.auth.impl.WindowsAuthProviderImpl;

@Configuration
@EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private NegotiateSecurityFilterEntryPoint entryPoint;

    @Autowired
    private NegotiateSecurityFilter filter;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.exceptionHandling().authenticationEntryPoint(entryPoint);
        http.addFilterBefore(filter, BasicAuthenticationFilter.class).authorizeRequests().anyRequest()
                .fullyAuthenticated();
    }

    @Bean
    public WindowsAuthProviderImpl windowsAuthProviderImpl() {
        return new WindowsAuthProviderImpl();
    }

    @Bean
    public NegotiateSecurityFilterProvider negotiateSecurityFilterProvider(final WindowsAuthProviderImpl authProvider) {
        return new NegotiateSecurityFilterProvider(authProvider);
    }

    @Bean
    public BasicSecurityFilterProvider basicSecurityFilterProvider(final WindowsAuthProviderImpl authProvider) {
        return new BasicSecurityFilterProvider(authProvider);
    }

    @Bean
    public SecurityFilterProviderCollection securityFilterProviderCollection(
            final NegotiateSecurityFilterProvider negotiateSecurityFilterProvider,
            final BasicSecurityFilterProvider basicSecurityFilterProvider) {
        return new SecurityFilterProviderCollection(new SecurityFilterProvider[] { negotiateSecurityFilterProvider,
                basicSecurityFilterProvider });
    }

    @Bean
    public NegotiateSecurityFilterEntryPoint negotiateSecurityFilterEntryPoint(
            final SecurityFilterProviderCollection securityFilterProviderCollection) {
        final NegotiateSecurityFilterEntryPoint entryPoint = new NegotiateSecurityFilterEntryPoint();

        entryPoint.setProvider(securityFilterProviderCollection);

        return entryPoint;
    }

    @Bean
    public NegotiateSecurityFilter negotiateSecurityFilter(
            final SecurityFilterProviderCollection securityFilterProviderCollection) {
        final NegotiateSecurityFilter filter = new NegotiateSecurityFilter();

        filter.setProvider(securityFilterProviderCollection);

        return filter;
    }

}

Процесс аутентификации работает, как и ожидалось, но я могу только прочитать имя текущего пользователя, вошедшего в систему, в контроллере следующим образом:

@RequestMapping("/")
public @ResponseBody String index(final Principal user) {
    return String.format("Welcome to the home page, %s!", user.getName());
}

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


person stevecross    schedule 24.02.2015    source источник


Ответы (1)


Я создал еще один фильтр, который запускается после запуска фильтра Waffle. Он проверяет, аутентифицировал ли Waffle пользователя. Если это так, я создаю свой собственный объект Authentication с информацией из объекта Waffle.

Обновить

Тем временем я вернулся к логину на основе формы. Но я думаю, что сделал это так:

Пользовательский класс UserDetails:

@Data
public class User implements UserDetails {

    private static final long serialVersionUID = -302856598965676658L;

    private String username;

    private Set<Role> authorities;

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return authorities;
    }

    @Override
    public String getPassword() {
        return "";
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }

}

Пользовательский класс GrantedAuthority:

@Data
public class Role implements GrantedAuthority {

    private static final long serialVersionUID = -7912276892872811638L;

    private String authority;

    @Override
    public String getAuthority() {
        return authority;
    }

}

Пользовательский класс проверки подлинности:

public class CustomAuthentication implements Authentication {

    private static final long serialVersionUID = -1723253799961522167L;

    private User user;

    public CustomAuthentication(final User user) {
        this.user = user;
    }

    @Override
    public String getName() {
        return user.getUsername();
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return user.getAuthorities();
    }

    @Override
    public Object getCredentials() {
        return null;
    }

    @Override
    public Object getDetails() {
        return null;
    }

    @Override
    public Object getPrincipal() {
        return user;
    }

    @Override
    public boolean isAuthenticated() {
        return user != null;
    }

    @Override
    public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
    }

}

Пользовательский фильтр:

@Component
public class CustomFilter extends GenericFilterBean {

    @Autowired
    private UserService userService;

    @Override
    public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
            throws IOException, ServletException {
        final SecurityContext securityContext = SecurityContextHolder.getContext();
        final Authentication authentication = securityContext.getAuthentication();

        if (authentication != null) {
            final String username = authentication.getName();
            final User user = userService.getUserByUsername(username);
            final CustomAuthentication customAuthentication = new CustomAuthentication(user);

            securityContext.setAuthentication(customAuthentication);
        }

        chain.doFilter(request, response);
    }

}

Регистрация фильтров:

@Configuration
@EnableWebMvcSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    private NegotiateSecurityFilter waffleFilter;

    @Autowired
    private CustomFilter customFilter;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.addFilterBefore(waffleFilter, BasicAuthenticationFilter.class);
        http.addFilterAfter(customFilter, NegotiateSecurityFilter.class);
    }

}
person stevecross    schedule 24.06.2015
comment
@dataCore Я обновил свой ответ. Обратите внимание, что я не тестировал код. - person stevecross; 24.09.2015
comment
@SteffenKreutz - Спасибо за ответ. Не могли бы вы помочь мне с еще одним заданием? Я хочу аутентифицировать и авторизовать (проверить в БД) некоторые конечные точки, но аутентифицировать только другие. Есть ли способ? - person JHS; 02.09.2016
comment
@JHS Пожалуйста, задайте новый вопрос по этой теме. - person stevecross; 03.09.2016