【问题标题】:Spring Security 4 - CredentialsExpiredException not redirecting to reset password - XML configSpring Security 4 - CredentialsExpiredException 未重定向到重置密码 - XML 配置
【发布时间】:2017-05-20 01:51:18
【问题描述】:

我正在使用 Spring-Security 4 XML 配置在 spring-mvc webapp 中成功实现密码验证。

我遇到的问题是,当 DaoAuthenticationProvider 抛出 CredentialsExpiredException 时,系统会重定向到登录表单,而不是重置密码。

我的上下文安全 xml 配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<b:beans xmlns="http://www.springframework.org/schema/security"
xmlns:b="http://www.springframework.org/schema/beans" 
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans     http://www.springframework.org/schema/beans/spring-beans.xsd 
                    http://www.springframework.org/schema/security  http://www.springframework.org/schema/security/spring-security.xsd">

<b:bean id="authenticationEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
    <b:constructor-arg value="/index/form" />
</b:bean>

<http auto-config="true" use-expressions="true" disable-url-rewriting="true" entry-point-ref="authenticationEntryPoint" >
    <intercept-url pattern="/" access="permitAll" requires-channel="https"/>
    <intercept-url pattern="/index" access="permitAll" requires-channel="https"/>
    <intercept-url pattern="/index/*" access="permitAll" requires-channel="https"/>
    <intercept-url pattern="/**" access="hasAnyRole('USER','SYS_ADMIN' )" requires-channel="https"/>
    <form-login   
            login-page="/index/form"
                default-target-url="/dashboard"
                login-processing-url="/index"
                username-parameter="username"
                password-parameter="password"
                authentication-failure-handler-ref="exceptionTranslationFilter"
                always-use-default-target="true"/>
    <logout logout-url="/logout" logout-success-url="/index/logout"/>

    <session-management>
        <concurrency-control max-sessions="1" error-if-maximum-exceeded="true" />
    </session-management>
</http>

 <!-- password expiry functionality starts  -->
<b:bean id="exceptionTranslationFilter" class="org.springframework.security.web.authentication.ExceptionMappingAuthenticationFailureHandler">
    <b:property name="exceptionMappings">
        <b:props>
            <b:prop key="org.springframework.security.authentication.CredentialsExpiredException">/resetpassword</b:prop>
        </b:props>
    </b:property>
    <b:property name="defaultFailureUrl" value="/index/error"/>
</b:bean>


 <b:bean id="authenticationManager" class="org.springframework.security.authentication.ProviderManager">
    <b:constructor-arg name="providers">
        <b:list>
            <b:ref bean="daoAuthenticationProvider"/>
        </b:list>
    </b:constructor-arg>
</b:bean> 

<b:bean id="daoAuthenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider ">
    <b:property name="userDetailsService" ref="customUserDetailsService" />
    <b:property name="passwordEncoder" ref="passwordEncoder" />
</b:bean>



<authentication-manager alias="authenticationManager">
    <authentication-provider user-service-ref="customUserDetailsService" />
    <authentication-provider ref="daoAuthenticationProvider" /> 
</authentication-manager>


<b:bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" >
</b:bean>

鉴于上述配置,当我输入凭据已过期的用户的正确用户名和密码时,我会被重定向到 url = "/index/form"

我已经运行了调试器(我使用的是Eclipse),代码执行如下(所有类都属于Spring Security 4):

AbstractUserDetailsAuthenticationProvider.authenticate() 在执行 postAuthenticationChecks.check(user) 时抛出 CredentialsExpiredException

ExceptionMappingAuthenticationFailureHandler.onAuthenticationFailure() 在调用 getRedirectStrategy().sendRedirect(request, response, url); 之前获取 url 为 /resetpassword >

DefaultRedirectStrategy.sendRedirect() 获取重定向 url 为“/myapp/resetpassword”

问题出现在LoginUrlAuthenticationEntryPoint.commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException)上。

因为useForward设置为false,所以调用redirectUrl = buildRedirectUrlToLoginPage(request, response, authException);

redirectUrl 最终成为“/index/form”。

即使我将 useForward 设置为 true 并将 LoginUrlAuthenticationEntryPoint 子类化以覆盖 determineUrlToUseForThisRequest,我得到的 AuthenticationException 也是 InsufficientAuthenticationException 类型。 p>

有趣的是,我浏览器上的网址是https://localhost:8443/myapp/resetpassword,但它显示的是登录表单。

你以前遇到过这个问题吗?如果是这样,你是如何让 spring 重定向到重置密码的?

我从https://stackoverflow.com/a/14383194/158499得到的大部分配置

提前致谢,卢卡斯

【问题讨论】:

    标签: spring-mvc spring-security thymeleaf reset-password


    【解决方案1】:
     <intercept-url pattern="/**" access="hasAnyRole('USER','SYS_ADMIN' )" requires-channel="https"/>
    

    当重定向到/resetpassword 时将重定向到登录页面。请允许此网址无需身份验证即可访问。

    <intercept-url pattern="/resetpassword" access="permitAll" requires-channel="https"/>
    

    【讨论】:

    • 谢谢@chaoluo。这实际上起到了作用。我花了 2 天时间试图解决这个问题!但是如果我想将用户名保留在 Authentication 对象中,以便用户只需要输入旧密码和新密码呢?再次感谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-24
    • 2017-03-03
    • 2016-10-24
    • 2014-02-25
    • 2018-09-11
    • 1970-01-01
    相关资源
    最近更新 更多