Spring security 在spring security中强制用户更改过期密码

Spring security 在spring security中强制用户更改过期密码,spring-security,change-password,Spring Security,Change Password,我正在构建基于SpringMVC和SpringSecurity的web应用程序 我已经实现了重置密码功能。系统管理员将重置任何用户的密码。随机生成的密码将通过电子邮件发送给用户,并在数据库中更新 现在,每当用户使用随机生成的密码登录时,我想强制用户更改其密码 请查看我的用户表 用户ID bigint(20) 用户名varchar(20) 密码varchar(65) 电子邮件varchar(50) firstname varchar(20) 姓氏varchar(20) groupname varc

我正在构建基于SpringMVC和SpringSecurity的web应用程序

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

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

请查看我的用户表

用户ID bigint(20)
用户名varchar(20)
密码varchar(65)
电子邮件varchar(50)
firstname varchar(20)
姓氏varchar(20)
groupname varchar(50)
已启用的tinyint(1)
证书非Expired tinyint(1)

我的身份验证提供商


我使用了JDBCUserDetailsService扩展JDBCDaoImpl作为jdbcUserService

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

我能做到

但是,当我登录时,spring securityJDBCUserDetails服务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);
        }

    });
}
受保护列表loadUsersByUsername(字符串用户名){
返回getJdbcTemplate().query(usersByUsernameQuery,新字符串[]{username},新行映射器(){
public UserDetails映射行(ResultSet rs,int rowNum)抛出SQLException{
字符串用户名=rs.getString(1);
字符串密码=rs.getString(2);
布尔启用=rs.getBoolean(3);
返回新用户(用户名、密码、已启用、true、true、true、AuthorityUtils.无权限);
}
});
}
但我需要实际的credentialNonExpired字段,该字段由重置密码设置,这样spring security将抛出CREDENTIALEXPIREDEXCEPTION

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


请告诉我怎么做?

您可以尝试子类化
SimpleRuThenticationSuccessHandler
,并实现用于检查密码到期的自定义逻辑。对这个
SimpleRuThenticationSuccessHandler
的引用可以传递给应用程序上下文中的表单登录元素。

回答得很晚,我不知道您使用的是Spring 2还是Spring 3。 但是在春季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>
最后一步是创建更改密码页面


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

我正在处理一个非常类似的问题,并且正在沿着这条路径前进。。。是否有关于如何最好地处理更改密码逻辑的建议?似乎试图复制所有正常的“登录”功能(检查密码、填写SecurityContextHolder、返回错误代码)可能会变得很棘手……我正在使用JPA和模型,我正在直接更新这些功能,而不必经历整个Spring安全周期。在我看来,这是最快的方法。当然,在更改密码后,我会将用户重定向到登录页面。是的,我认为您的方式会更快:)以下是我最后所做的操作-*
UsernamePasswordResetAuthentication
使用用户名、密码,和new password*登录页面,在适当时带有new/confirm password字段*登录过滤器,根据请求创建正确的身份验证对象*自定义身份验证提供程序(由于不同原因已存在),扩展为1)使用现有密码进行身份验证,2)更新存储的密码,3)使用新密码重新进行身份验证。该自定义身份验证提供程序是最大的一部分。但是如果你因为其他原因已经有了它。。。
<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>
<security:form-login ... authentication-failure-handler-ref="securityExceptionTranslationHandler">