Spring Security自定义过滤器(更改密码)

Dre*_*ter 15 spring spring-security

我正在使用Spring Security保护对网站的HTTP请求.主要用途是保护页面,以便在尝试访问这些页面时将用户重定向到登录页面.

但是,我还有一个要求.在我的模型中,我可以将用户的密码标记为临时密码,这样当他们成功登录时,应该自动强制他们更改密码.更改密码后,应将其转发到最初尝试访问的页面.

有没有人为此目的使用Spring Security?我是否需要创建自己的自定义过滤器?

谢谢,

安德鲁

axt*_*avt 19

在Spring Security 3.0中,您可以实现自定义AuthenticationSuccessHandler.

在此处理程序中,您可以使用临时密码将用户重定向到密码更改页面,而不是最初请求的页面.更改密码后,您可以使用SavedRequestAwareAuthenticationSuccessHandler,这是默认的处理程序实现,将用户重定向到最初请求的页面.

public class MyHandler implements AuthenticationSuccessHandler {
    private AuthenticationSuccessHandler target = new SavedRequestAwareAuthenticationSuccessHandler();

    public void onAuthenticationSuccess(HttpServletRequest request,
        HttpServletResponse response, Authentication auth) {
        if (hasTemporaryPassword(auth)) {
            response.sendRedirect("/changePassword");
        } else {
            target.onAuthenticationSuccess(request, response, auth);
        }
    }

    public void proceed(HttpServletRequest request, 
        HttpServletResponse response, Authentication auth) {
        target.onAuthenticationSuccess(request, response, auth);
    }
}

@Controller("/changePassword")
public class ChangePasswordController {

    @Autowired
    private MyHandler handler;

    @RequestMapping(method = POST)
    public void changePassword(HttpServletRequest request, 
        HttpServletResponse response,
        @RequestParam(name = "newPassword") String newPassword) {

        // handle password change
        ...

        // proceed to the secured page
        handler.proceed(request, response, auth);        
    }

    // form display method, etc
    ...
}
Run Code Online (Sandbox Code Playgroud)

  • 该解决方案的缺点是,用户在被重定向到changePassword页面后可以自由地继续到应用程序的其他页面,并且从不实际更改他/她的密码.他最终成功通过认证,并没有阻止他这样做. (5认同)
  • 实际上,在身份验证成功处理程序中检查密码到期是违反直觉的,不是吗?如果密码已过期,您应该无法进行身份验证.检查@jyore提供的答案. (3认同)
  • 对不起,因为使用这种技术非常不安全,因为Ondrej指出.用户可以绕过密码重置要求. (3认同)

jyo*_*ore 14

有点晚了,但希望这可以帮助其他人找到这个链接.如果使用自定义UserDetailsS​​ervice,则可以将User对象的credentialsNonExpired设置为false,例如,在该字段设置回true之前不允许访问任何安全内容.

基本上,当您有密码过期时,您将在用户模型中设置一个字段(可能是passwordExpired),当UserDetailsS​​ervice拉取用户时,您的UserDetailsS​​ervice将使用该值来设置credentialsNonExpired.

然后,您需要做的就是在applicationContext-security.xml中添加一些配置来设置身份验证异常映射.这将允许您捕获使用过期凭据抛出的异常并强制用户重置密码页面.您还可以使用类似的方法捕获锁定和禁用的帐户.配置示例如下所示:

的applicationContext-security.xml文件

<beans:bean id="exceptionTranslationFilter" class="org.springframework.security.web.authentication.ExceptionMappingAuthenticationFailureHandler">
    <beans:property name="exceptionMappings">
        <beans:props>           
            <beans:prop key="org.springframework.security.authentication.BadCredentialsException">/login_error</beans:prop>
            <beans:prop key="org.springframework.security.authentication.CredentialsExpiredException">/password_expired</beans:prop>
            <beans:prop key="org.springframework.security.authentication.LockedException">/locked</beans:prop>
            <beans:prop key="org.springframework.secuirty.authentication.DisabledException">/disabled</beans:prop>
        </beans:props>
        </beans:property>
</beans:bean>

<http use-expressions="true">
    <!-- ADD BLACKLIST/WHITELIST URL MAPPING -->
    <form-login login-page="/login" default-target-url="/" authentication-failure-handler-ref="exceptionTranslationFilter" />
</http>
Run Code Online (Sandbox Code Playgroud)

然后,只需确保您的控制器设置为具有适当内容的链接提供服务.

  • 此解决方案的缺点是在用户通过身份验证之前会检查用户credentialsNonExpired,因此您会向未经过身份验证的用户(例如,攻击者)显示用户凭据已过期.我想这样的信息不是那么重要,但我仍然发现带有过滤器的rodrigoap解决方案更好. (3认同)

rod*_*oap 6

是的,我用过滤器ForceChangePasswordFilter做了这个.因为如果用户手动键入url,他们可以绕过更改密码表单.使用过滤器,请求始终被截获.