12

我正在构建基于 Spring MVC 和 Spring Security 的基于 Web 的应用程序。

我已经实现了重置密码功能。系统管理员将重置任何用户的密码。随机生成的密码将通过电子邮件发送给用户,并将在数据库中更新。

现在我想每当用户使用随机生成的密码登录时,我想强制用户更改其密码。

请看一下我的用户表。

userid bigint(20)
username varchar(20)
password varchar(65)
email varchar(50)
firstname varchar(20)
lastname varchar(20)
groupname varchar(50)
启用 tinyint(1)
credentialsNonExpired tinyint(1)

我的身份验证提供商

    <!--
        Configuring Authentication Provider to make use of spring security
        provided Jdbc user management service
    -->
    <authentication-provider user-service-ref="jdbcUserService">
        <!--
            Configuring SHA-1 Password Encoding scheme to secure user credential
        -->
        <password-encoder ref="sha1PasswordEncoder" />
    </authentication-provider>
</authentication-manager>

我使用JDBCUserDetailsS​​ervice将JDBCDaoImpl扩展为jdbcUserService

当我重置密码时,我想将credentialNonExpired设置为我的用户表的 false 列。

我能够做到这一点。

但是当我登录时,spring security JDBCuserdetailsservice loadUserbyUsername只获取用户名、密码、启用的列和其余所有字段设置为 true。

protected List<UserDetails> loadUsersByUsername(String username) {
    return getJdbcTemplate().query(usersByUsernameQuery, new String[] {username}, new RowMapper<UserDetails>() {
        public UserDetails mapRow(ResultSet rs, int rowNum) throws SQLException {
            String username = rs.getString(1);
            String password = rs.getString(2);
            boolean enabled = rs.getBoolean(3);
            return new User(username, password, enabled, true, true, true, AuthorityUtils.NO_AUTHORITIES);
        }

    });
}

但我想要由重置密码设置的实际credentialNonExpired字段,以便 Spring Security 将抛出 CREDENTIALEXPIREDEXCEPTION。

我通过加载上述方法来实现这一点,但是当用户使用过期密码登录时,有没有其他方法可以重定向用户以更改密码页面。

请告诉我我该怎么做?

4

2 回答 2

15

很晚的答案,我不知道您使用的是 Spring 2 还是 Spring 3。但是在 Spring 3 中,您可以这样做。

在 Spring 安全上下文中包含以下内容:

<bean id="securityExceptionTranslationHandler" class="org.springframework.security.web.authentication.ExceptionMappingAuthenticationFailureHandler">
    <property name="exceptionMappings">
        <props>
            <prop key="org.springframework.security.authentication.CredentialsExpiredException">/change_password_page</prop>
        </props>
    </property>
    <property name="defaultFailureUrl" value="/login_generic_error_page"/>
</bean>

当然,您可以将其他特定的身份验证异常映射到其他页面。

如果您使用 form-login 元素,则必须指定authentication-failure-handler-ref属性(authentication-failure-url如果使用则删除)

<security:form-login ... authentication-failure-handler-ref="securityExceptionTranslationHandler">

最后一步是创建更改密码页面。

请记住,用户在重定向到更改密码页面时未经过身份验证。

于 2013-01-17T16:06:49.793 回答
1

您可以尝试子类化SimpleUrlAuthenticationSuccessHandler并实现自定义逻辑来检查密码到期。对此的引用SimpleUrlAuthenticationSuccessHandler可以传递给应用程序上下文中的 form-login 元素。

于 2012-01-12T12:15:07.480 回答