具有不同UsernamePasswordAuthToken的多个AuthenticationProvider可以对不同的登录表单进行身份验证,而无需回退身份验证 [英] Multiple AuthenticationProvider with different UsernamePasswordAuthToken to authenticate different login forms without fallback authentication

查看:394
本文介绍了具有不同UsernamePasswordAuthToken的多个AuthenticationProvider可以对不同的登录表单进行身份验证,而无需回退身份验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在使用Spring Security时,我研究了stackoverflow中一个有趣的线程,但需要针对不同的身份验证提供程序两组用户进行身份验证, LDAP和客户反对DATABASE. Thread提出了一种公认的解决方案,即具有一个带有单选按钮的登录表单,以区分员工和客户,并具有自定义身份验证过滤器,该过滤器根据userType区分登录请求并设置不同的authenticationToken( customerAuthToken / employeeAuthToken ),然后进行身份验证请求.将有两个AuthenticationProvider实现,并且身份验证是通过支持令牌来完成和确定的. 通过这种方式,线程能够提供有趣的解决方案,从而避免默认情况下Spring Security提供的回退身份验证.

While working with spring security I had a look at interesting thread in stackoverflow, there it was requirement to have authenticating two set of users against different authentication provider say employees against LDAP and customer against DATABASE. Thread came up with accepted solution to have a single login form with a radio button to distinguish employee from customer and to have custom authentication filter which differentiate login request based on userType and sets different authenticationToken(customerAuthToken/employeeAuthToken) and request is proceeded for authentication. There will be two AuthenticationProvider implementation and authentication is done and decided by supporting token. In this way thread was able to provide interesting solution to avoid fallback authentication which spring security provides by default.

看看线程配置Spring Security 3 .x具有多个入口点

因为答案完全在xml配置中.我只是想让解决方案在Java配置中可用.我将在答复中发布.

Since answer is completely in xml configuration. I just wanted to have the solution be available in java configuration. I will be posting that in answer.

现在我的问题随着春季版本的发展,除了我的答案以外,是否有可能通过任何新功能/最低配置拥有相同的功能?

Now my question, with evolution of spring version, is it possible to have the same functionality by any new features/ minimal configurations apart from my answer?

推荐答案

由于

Since this thread given complete information, i am just posting codes for java configuration reference.

我在这里假设以下事情
1.用户和管理员为两组用户.
2.为简单起见,在两者中都使用内存身份验证.
-如果userType为用户",则仅用户凭据应起作用.
-如果userType为Admin,则仅管理员凭据应起作用. -并且应该能够向不同的权限提供相同的应用程序界面.

Here i am assuming following things
1. User's and Admin's as two set of users.
2. For simplicity using in memory authentication for both.
- If userType is User only user credential should work.
- If userType is Admin only admin credential should work. - And should be able to provide same application interface with different authorities.

和代码
您可以从我的github存储库下载工作代码


CustomAuthenticationFilter

And the codes
You can download working code from my github repository


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");
    }
}

希望它将有助于您了解如何配置没有后备身份验证的多重身份验证.

Hope it will help to understand configuring multiple authentication without fallback authentication.

这篇关于具有不同UsernamePasswordAuthToken的多个AuthenticationProvider可以对不同的登录表单进行身份验证,而无需回退身份验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆