Несколько AuthenticationProvider с разными UsernamePasswordAuthToken для аутентификации различных форм входа без резервной аутентификации

Во время работы с Spring Security я взглянул на интересный поток в stackru, там требовалось аутентифицировать два набора пользователей против другого поставщика аутентификации, говорят сотрудники противLDAP и клиент против DATABASE. В потоке появилось принятое решение: иметь единую форму входа с переключателем, чтобы отличать сотрудника от клиента, и иметь настраиваемый фильтр аутентификации, который различает запрос входа в систему на основе userType и устанавливает разные authenticationToken(customerAuthToken/employeeAuthToken), и запрос обрабатывается для аутентификации. Будет дваAuthenticationProviderреализация и аутентификация выполняются и определяются поддерживающим токеном. Таким образом, поток смог предоставить интересное решение, позволяющее избежать резервной аутентификации, которую Spring Security обеспечивает по умолчанию.

Взгляните на поток Настройка Spring Security 3.x, чтобы иметь несколько точек входа

Поскольку ответ полностью находится в конфигурации xml. Я просто хотел, чтобы решение было доступно в конфигурации java. Я отправлю это в ответ.

Теперь мой вопрос, с развитием весенней версии, возможно ли иметь такую ​​же функциональность с помощью каких-либо новых функций / минимальных конфигураций, кроме моего ответа?

1 ответ

Решение

Поскольку этот поток дал полную информацию, я просто публикую коды для справки по конфигурации Java.

Здесь я предполагаю следующее:
1. Пользователь и администратор как две группы пользователей.
2. Для простоты использования аутентификации в памяти для обоих.
- Если userType - User, должны работать только учетные данные пользователя.
- Если userType - Admin, должны работать только учетные данные администратора. - И должен иметь возможность предоставлять один и тот же интерфейс приложения с разными полномочиями.

И коды
Вы можете скачать рабочий код из моего репозитория на github


CustomAuthenticationFilter

@Component
public class MyAuthenticationFilter extends UsernamePasswordAuthenticationFilter
{
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException
    {
        UsernamePasswordAuthenticationToken authToken = null;

        if ("user".equals(request.getParameter("userType"))) 
        {
            authToken = new UserUsernamePasswordAuthenticationToken(request.getParameter("userName"), request.getParameter("password"));
        }
        else 
        {
            authToken = new AdminUsernamePasswordAuthenticationToken(request.getParameter("userName"), request.getParameter("password"));
        }

        setDetails(request, authToken);

        return super.getAuthenticationManager().authenticate(authToken);
    }
}

CustomAuthentictionTokens

public class AdminUsernamePasswordAuthenticationToken extends UsernamePasswordAuthenticationToken
{   
    public AdminUsernamePasswordAuthenticationToken(Object principal, Object credentials)
    {
        super(principal, credentials);
    }

    public AdminUsernamePasswordAuthenticationToken(Object principal, Object credentials,
            Collection<? extends GrantedAuthority> authorities)
    {
        super(principal, credentials, authorities);
    }
}

public class UserUsernamePasswordAuthenticationToken extends UsernamePasswordAuthenticationToken
{
    public UserUsernamePasswordAuthenticationToken(Object principal, Object credentials)
    {
        super(principal, credentials);
    }

    public UserUsernamePasswordAuthenticationToken(Object principal, Object credentials,
            Collection<? extends GrantedAuthority> authorities)
    {
        super(principal, credentials, authorities);
    }}

CustomAuthentictionProvider - For Admin

@Component
public class AdminCustomAuthenticationProvider implements AuthenticationProvider
{
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException
    {
        String username = authentication.getName();
        String password = authentication.getCredentials().toString();

        if (username.equals("admin") && password.equals("admin@123#"))
        {
            List<GrantedAuthority> authorityList = new ArrayList<>();
            GrantedAuthority authority = new SimpleGrantedAuthority("ROLE_ADMIN");
            authorityList.add(authority);

            return new UserUsernamePasswordAuthenticationToken(username, password, authorityList);
        }
        return null;
    }

    @Override
    public boolean supports(Class<?> authentication)
    {
        return authentication.equals(AdminUsernamePasswordAuthenticationToken.class);
    }
}

CustomAuthentictionProvider - For User

@Component
public class UserCustomAuthenticationProvider implements AuthenticationProvider
{
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException
    {

        String username = authentication.getName();
        String password = authentication.getCredentials().toString();

        if (username.equals("user") && password.equals("user@123#"))
        {
            List<GrantedAuthority> authorityList = new ArrayList<>();
            GrantedAuthority authority = new SimpleGrantedAuthority("ROLE_USER");
            authorityList.add(authority);

            return new UserUsernamePasswordAuthenticationToken(username, password, authorityList);
        }
        return null;
    }

    @Override
    public boolean supports(Class<?> authentication)
    {
        return authentication.equals(UserUsernamePasswordAuthenticationToken.class);
    }
}

CustomHandlers required for CustomFilter

@Component
public class CustomAuthenticationFailureHandler implements AuthenticationFailureHandler
{
    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException
    {
        response.sendRedirect(request.getContextPath() + "/login?error=true");
    }   
}

@Component
public class CustomAuthenticationSuccessHandler implements AuthenticationSuccessHandler
{
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException
    {
        HttpSession session = request.getSession();
        if (session != null)
        {
            session.removeAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
        }
        response.sendRedirect(request.getContextPath() + "/app/user/dashboard");
    }
}

И наконец SpringSecurityConfiguration

@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter 
{
    @Autowired
    DataSource dataSource;

    @Autowired
    private AdminCustomAuthenticationProvider adminCustomAuthenticationProvider;

    @Autowired
    private UserCustomAuthenticationProvider userCustomAuthenticationProvider;

    @Autowired
    private CustomAuthenticationSuccessHandler customAuthenticationSuccessHandler;

    @Autowired
    private CustomAuthenticationFailureHandler customAuthenticationFailureHandler;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception
    {
        auth.authenticationProvider(adminCustomAuthenticationProvider);
        auth.authenticationProvider(userCustomAuthenticationProvider);
    }

    @Bean
    public MyAuthenticationFilter myAuthenticationFilter() throws Exception
    {
        MyAuthenticationFilter authenticationFilter = new MyAuthenticationFilter();

        authenticationFilter.setAuthenticationSuccessHandler(customAuthenticationSuccessHandler);
        authenticationFilter.setAuthenticationFailureHandler(customAuthenticationFailureHandler);
        authenticationFilter.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/login", "POST"));
        authenticationFilter.setAuthenticationManager(authenticationManagerBean());

        return authenticationFilter;
    }

    @Override
    protected void configure(final HttpSecurity http) throws Exception
    {
        http
        .addFilterBefore(myAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
        .csrf().disable()
        .authorizeRequests()
            .antMatchers("/resources/**", "/", "/login")
                .permitAll()
            .antMatchers("/config/*", "/app/admin/*")
                .hasRole("ADMIN")
            .antMatchers("/app/user/*")
                .hasAnyRole("ADMIN", "USER")
            .antMatchers("/api/**")
                .hasRole("APIUSER")
        .and().exceptionHandling()
            .accessDeniedPage("/403")
        .and().logout()
            .logoutSuccessHandler(new CustomLogoutSuccessHandler())
            .invalidateHttpSession(true);

        http.sessionManagement().maximumSessions(1).expiredUrl("/login?expired=true");
    }
}

Надеюсь, это поможет понять настройку множественной аутентификации без резервной аутентификации.

Другие вопросы по тегам