Принуждение пользователя к изменению пароля с истекшим сроком в spring безопасности

Я создаю веб-приложение spring mvc и spring на основе безопасности.

Я реализовал функциональность Reset Password.System Administrator будет Reset пароль любого пользователя. Сгенерированный случайный пароль будет отправлен пользователю по электронной почте, и он будет обновлен в базе данных.

Теперь я хочу, чтобы всякий раз, когда пользователь входил со случайным сгенерированным паролем, я хочу заставить пользователя изменить его пароль.

Пожалуйста, посмотрите на мой пользователь TABLE.

userid bigint (20)
имя пользователя varchar (20) | пароль varchar (65)
email varchar (50), firstname varchar (20), lastname varchar (20)
groupname varchar (50)
enabled 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>

Я использовал JDBCUserDetailsService расширение 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, которое устанавливается паролем Reset, так что безопасность spring будет выдавать CREDENTIALEXPIREDEXCEPTION.

Я достигаю этого путем загрузки выше метода, но есть ли другой способ перенаправить пользователя на страницу с паролем при входе с истекшим паролем.

Скажите, пожалуйста, как я могу это сделать?

Ответ 1

Довольно поздний ответ, и я не знаю, используете ли вы Spring 2 или 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">

И последний шаг - создать страницу смены пароля.

Имейте в виду, что пользователь не аутентифицируется при перенаправлении на страницу смены пароля.

Ответ 2

Вы можете попробовать подклассом SimpleUrlAuthenticationSuccessHandler и реализовать пользовательскую логику для проверки срока действия пароля. Ссылка на этот SimpleUrlAuthenticationSuccessHandler может быть передана элементу form-login в контексте приложения.