春节习俗AuthenticationFailureHandler(Spring custom Aut

2019-08-21 20:37发布

我已经尝试了整整一天,让我的定制身份验证失败处理程序与Spring 3.1.3工作。

我认为这是正确配置

<http use-expressions="true" disable-url-rewriting="true">
    <intercept-url pattern="/rest/login" access="permitAll" />
    <intercept-url pattern="/rest/**" access="isAuthenticated()" />
    <intercept-url pattern="/index.html" access="permitAll" />
    <intercept-url pattern="/js/**" access="permitAll" />
    <intercept-url pattern="/**" access="denyAll" />
    <form-login username-parameter="user" password-parameter="pass" login-page="/rest/login"
        authentication-failure-handler-ref="authenticationFailureHandler"  />
</http>
<beans:bean id="authenticationFailureHandler" class="LoginFailureHandler" />

我实现这个

public class LoginFailureHandler implements AuthenticationFailureHandler {
    private static final Logger log = LoggerFactory.getLogger(LoginFailureHandler.class);

    public LoginFailureHandler() {
        log.debug("I am");
    }

    @Autowired
    private ObjectMapper customObjectMapper;

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
            AuthenticationException exception) throws IOException, ServletException {
        log.debug("invalid login");
        User user = new User();
        user.setUsername("invalid");
        try (OutputStream out = response.getOutputStream()) {
            customObjectMapper.writeValue(out, user);
        }
    }

}

在我看到控制台

2013-04-11 14:52:29,478 DEBUG LoginFailureHandler - I am

因此,它被装载。

随着错误的用户名或passwort,当BadCredentialsException被抛出,我没有看到无效的登录。

该方法onAuthenticationFailure是永远不会被调用。

取而代之的是服务到/ REST /登录一次又一次地将浏览器重定向...

编辑

2013-04-11 15:47:26,411 DEBUG de.pentos.spring.LoginController - Incomming login chuck.norris, norris
2013-04-11 15:47:26,412 DEBUG o.s.s.a.ProviderManager - Authentication attempt using org.springframework.security.authentication.dao.DaoAuthenticationProvider
2013-04-11 15:47:26,415 DEBUG o.s.s.a.d.DaoAuthenticationProvider - Authentication failed: password does not match stored value
2013-04-11 15:47:26,416 DEBUG o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver - Resolving exception from handler [public de.pentos.spring.User de.pentos.spring.LoginController.login(de.pentos.spring.User)]: org.springframework.security.authentication.BadCredentialsException: Bad credentials
2013-04-11 15:47:26,419 DEBUG o.s.w.s.m.a.ResponseStatusExceptionResolver - Resolving exception from handler [public de.pentos.spring.User de.pentos.spring.LoginController.login(de.pentos.spring.User)]: org.springframework.security.authentication.BadCredentialsException: Bad credentials
2013-04-11 15:47:26,419 DEBUG o.s.w.s.m.s.DefaultHandlerExceptionResolver - Resolving exception from handler [public de.pentos.spring.User de.pentos.spring.LoginController.login(de.pentos.spring.User)]: org.springframework.security.authentication.BadCredentialsException: Bad credentials
2013-04-11 15:47:26,426 DEBUG o.s.web.servlet.DispatcherServlet - Could not complete request
org.springframework.security.authentication.BadCredentialsException: Bad credentials

这发生在调试模式

哪里是我的错?

Answer 1:

从你连接我想你已经在执行登录过程中犯了一个错误日志判断。 我不能绝对肯定,但我猜你打电话ProviderManager.authenticate()在你LoginController 。 该方法将引发BadCredentialsException导致Spring MVC中的异常处理机制踢,这当然没有关于知识AuthenticationFailureHandler配置为春季安全。

从登录控制器通常应该只是成为一个简单的登录表单action="j_spring_security_check" method="post" 。 当用户提交该形式中,配置的安全过滤器(即UsernamePasswordAuthenticationFilter ),该请求和处理认证截距。 你不必以实现一个控制器的方法自己说的逻辑。


回复您的评论:

你使用ProviderManager (它的自动装配的实现AuthenticationManager接口)。 你犯的错误是,试图重写已经实施和权威性过滤器彻底测试的逻辑。 这是坏的本身,但即使是在一个错误的方式来完成。 您可以选择从复杂的逻辑,短短的几行,而其中你忘记例如调用会话策略,其他的事情(以防止会话固定攻击,以及处理并发会话)。 原来实现调用AuthenticationFailureHandler还有,你也忘了在你的方法,这是你原来的问题是关于这个问题的的真正原因。

所以,你最终用一个未经考验的,脆弱的解决方案,而不是与框架很好地整合利用其roboustness和满负荷生产。 正如我所说的,你在你的答案张贴的配置是一个明确的改善,因为它使用的身份验证框架提供的过滤器。 记住,配置和删除LoginController.login()它不会被通过反正发送到信息请求调用/rest/login

一个更根本的问题是,如果它真的如果实现RESTful服务使用会话和基于表单的登录机制,一个好的解决方案。 (在基于表单登录我的意思是客户端的任何格式发送一次其凭据,然后被用在后续请求中有状态会话认证)。通过REST服务它更普遍把一切都无状态,并重新验证每个新的请求由HTTP头中携带的信息。



Answer 2:

这是与在安全应用-context.xml中的顺序有问题。

如果我先定义所有的豆子,然后所有其余它的工作原理。 我尝试了很多,所以不要怀疑,它现在看起来有点不同,那么在这个问题

<beans:bean id="authenticationProcessingFilterEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
    <beans:property name="loginFormUrl" value="/rest/login" />
</beans:bean>

<beans:bean id="authenticationFilter" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
    <beans:property name="authenticationManager" ref="authenticationManager" />
    <beans:property name="filterProcessesUrl" value="/rest/login" />
    <beans:property name="authenticationSuccessHandler" ref="authenticationSuccessHandler" />
    <beans:property name="authenticationFailureHandler" ref="authenticationFailureHandler" />
</beans:bean>

<beans:bean id="authenticationSuccessHandler" class="de.pentos.spring.LoginSuccessHandler" />
<beans:bean id="authenticationFailureHandler" class="de.pentos.spring.LoginFailureHandler" />

<http use-expressions="true" disable-url-rewriting="true" entry-point-ref="authenticationProcessingFilterEntryPoint"
    create-session="ifRequired">
    <intercept-url pattern="/rest/login" access="permitAll" />
    <intercept-url pattern="/rest/**" access="isAuthenticated()" />
    <intercept-url pattern="/index.html" access="permitAll" />
    <intercept-url pattern="/js/**" access="permitAll" />
    <intercept-url pattern="/**" access="denyAll" />
    <custom-filter position="FORM_LOGIN_FILTER" ref="authenticationFilter" />
</http>

<authentication-manager alias="authenticationManager">
    <authentication-provider>
        <user-service>
            <user name="chuck.norris" password="cnorris" authorities="ROLE_ADMIN" />
            <user name="user" password="user" authorities="ROLE_USER" />
        </user-service>
    </authentication-provider>
</authentication-manager>


Answer 3:

不看对我不好。 你尝试用你的IDE的调试模式?

你有没有看到这样的事情在你的日志:

Authentication request failed: ...
Updated SecurityContextHolder to contain null Authentication
Delegating to authentication failure handler ...

通常在你的情况UsernamePasswordAuthenticationFilter:只有在认证在认证过滤器的一个完成的AuthenticationFailureHandler将自动被调用。



Answer 4:

(在你的要求看),你不需要自定义AuthenticationFailureHandler作为春天的默认SimpleUrlAuthenticationFailureHandler和正确实施的AuthenticationProvider应该服务宗旨。

 <form-login login-page="/login" login-processing-url="/do/login" authentication-  failure-url ="/login?authfailed=true" authentication-success-handler-ref ="customAuthenticationSuccessHandler"/>

如果你已经处理好了在身份验证提供例外:

采样逻辑:

    String loginUsername = (String) authentication.getPrincipal();
    if (loginUsername == null)
        throw new UsernameNotFoundException("User not found");

    String loginPassword = (String) authentication.getCredentials();

    User user = getUserByUsername(loginUsername);
    UserPassword password = getPassword(user.getId());

    if (!password.matches(loginPassword)) {
        throw new BadCredentialsException("Invalid password.");
    }

如果我们想扔在客户端界面中反映出来的异常,在JSP中添加以下scriplet响应认证失败-URL =“/登录?authfailed =真”

    <%                      
                    Exception error = (Exception) request.getSession().getAttribute("SPRING_SECURITY_LAST_EXCEPTION");
                   if (error != null)
                    out.write(error.getMessage());
     %>


文章来源: Spring custom AuthenticationFailureHandler