多个登录页面的 Spring 3.x 配置

Posted

技术标签:

【中文标题】多个登录页面的 Spring 3.x 配置【英文标题】:Spring 3.x configuration for multiple login pages 【发布时间】:2011-11-24 07:00:15 【问题描述】:

我使用 Spring 3.1 进行身份验证。

我的要求:

两个不同的登录页面。一个给客户,另一个给员工。 每次认证成功后,都会转发到各自成功的网址。

我的spring安全配置:

<sec:http pattern="/resources/**" security="none" />
<sec:http auto-config="true">
    <sec:intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
    <sec:intercept-url pattern="/customer/**" access="ROLE_CUSTOMER" />
    <sec:intercept-url pattern="/employee/**" access="ROLE_EMPLOYEE" />
</sec:http>

<bean id="springSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy">
    <sec:filter-chain-map path-type="ant">
        <sec:filter-chain pattern="/**"
            filters="authenticationProcessingFilterForCustomer,authenticationProcessingFilterForEmployee" />
    </sec:filter-chain-map>
</bean>

<bean id="authenticationProcessingFilterForCustomer"
    class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
    <property name="authenticationManager" ref="authenticationManagerForCustomer" />
    <property name="filterProcessesUrl" value="/j_spring_security_check_for_customer" />
    <property name="authenticationSuccessHandler" ref="customerSuccessHandler" />
    <property name="authenticationFailureHandler" ref="customerFailureHandler" />
</bean>
<bean id="customerSuccessHandler"
    class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
    <property name="defaultTargetUrl" value="/customer/index.html" />
</bean>
<bean id="customerFailureHandler"
    class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
    <property name="defaultFailureUrl" value="/customer.html?login_error=1" />
</bean>
<bean id="authenticationManagerForCustomer"
    class="org.springframework.security.authentication.ProviderManager">
    <property name="providers">
        <list>
            <ref bean="customCustomerAuthenticationProvider" />
        </list>
    </property>
</bean>
<bean id="customCustomerAuthenticationProvider" class="com.edu.CustomerCustomAuthenticationProvider">
    <property name="userDetailsService">
        <bean class="com.edu.CustomerUserDetailsService" />
    </property>
</bean>

<bean id="authenticationProcessingFilterForEmployee"
    class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
    <property name="authenticationManager" ref="authenticationManagerForEmployee" />
    <property name="filterProcessesUrl" value="/j_spring_security_check_for_employee" />
    <property name="authenticationSuccessHandler" ref="employeeSuccessHandler" />
    <property name="authenticationFailureHandler" ref="employeeFailureHandler" />
</bean>
<bean id="employeeSuccessHandler"
    class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
    <property name="defaultTargetUrl" value="/employee/index.html" />
</bean>
<bean id="employeeFailureHandler"
    class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
    <property name="defaultFailureUrl" value="/employee.html?login_error=1" />
</bean>
<bean id="authenticationManagerForEmployee"
    class="org.springframework.security.authentication.ProviderManager">
    <property name="providers">
        <list>
            <ref bean="customEmployeeAuthenticationProvider" />
        </list>
    </property>
</bean>
<bean id="customEmployeeAuthenticationProvider" class="com.edu.EmployeeCustomAuthenticationProvider">
    <property name="userDetailsService">
        <bean class="com.edu.EmployeeUserDetailsService" />
    </property>
</bean>

<sec:authentication-manager alias="authenticationManager">
    <sec:authentication-provider ref="customCustomerAuthenticationProvider" />
    <sec:authentication-provider ref="customEmployeeAuthenticationProvider" />
</sec:authentication-manager>

两个 CustomAuthenticationProvider 都实现了 Support 方法如下:

public boolean supports(Class<? extends Object> authentication) 
    return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);

启动应用程序后,在尝试进行身份验证时,登录页面中显示的消息是:

您的登录尝试未成功,请重试。 原因:找不到 org.springframework.security.authentication.UsernamePasswordAuthenticationToken 的 AuthenticationProvider

我正在使用 Spring 3.1。任何帮助表示赞赏。

谢谢

【问题讨论】:

可能与***.com/questions/4783063/…相关或重复? 已解决的“将 Spring Security 3.x 配置为具有多个入口点”的解决方案是为不同类型的用户提供单一入口点和单一成功页面。问题我有多个入口点,每个入口点都有自己的成功页面。 @ManasSahu 您能否在问题中添加自定义身份验证提供程序的“supports()”方法的代码? @Ritesh,我在顶部添加了支持方法的详细信息。在调试时我发现请求命中了支持方法,但它没有命中 authenticate(Authentication authentication) 方法。 【参考方案1】:

您应该将“authenticationProcessingFilterForCustomer”和“authenticationProcessingFilterForEmployee”bean 中的 authenticationManager 引用指向正确的 bean,即具有提供程序的“authenticationManager”。无需定义 'authenticationManagerForCustomer' 和 'authenticationManagerForEmployee' bean。

【讨论】:

【参考方案2】:

从 Spring 3.1 开始,您可以拥有任意数量的配置: https://jira.springsource.org/browse/SEC-1171

【讨论】:

【参考方案3】:

我在grails中做过类似的事情,你需要的是:

    扩展 UsernamePasswordAuthenticationToken,为员工和客户创建两个子类,比如 EmployeeUsernamePasswordAuthenticationToken 和 CustomerUsernamePasswordAuthenticationToken 扩展 UsernamePasswordAuthenticationFilter,根据当前的身份验证请求创建不同的 EmployeeUsernamePasswordAuthenticationToken 或 CustomerUsernamePasswordAuthenticationToken 实例 为员工和客户扩展AuthenticationProvider,创建两个类EmployeeAuthenticationProvider和CustomerAuthenticationProvider,覆盖每个类的supports方法以支持其目标UsernamePasswordAuthenticationToken 你只需要一个 authenticationManager,把两个都注册进去 只需要一个AuthenticationSuccessHandler,你可以决定要进去哪个url 我还创建了一个自己的 AuthenticationEntryPoint 实例来支持多入口点

【讨论】:

以上是关于多个登录页面的 Spring 3.x 配置的主要内容,如果未能解决你的问题,请参考以下文章

配置Spring Security以使用两个不同的登录页面

具有多个登录页面的 Spring 安全性

spring-security 个性化用户认证流程——自定义登录页面(可配置)

Spring Security自定义登录页面

如何在使用 OAuth2 社交登录保护 REST API 的同时配置 Spring Boot 登录页面

尽管我们不提供 Spring Security 配置,为啥 Spring Security 应用程序会重定向到登录页面?