Spring Security(3.2.5)HTTP POST在身份验证后不转发到原始请求 [英] Spring Security (3.2.5) HTTP POST not forwarding to the original request after authentication

查看:97
本文介绍了Spring Security(3.2.5)HTTP POST在身份验证后不转发到原始请求的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个示例Spring MVC应用程序,由Spring安全保护(Spring版本4.0.1.RELEASE,Spring安全3.2.5.RELEASE。当我作为未经身份验证的用户发送HTTP GET请求时,我被发送到登录page(正如预期的那样)在我进行身份验证后,我被发送到原始GET中请求的页面。

I have a sample Spring MVC application, secured by Spring security (Spring version 4.0.1.RELEASE, Spring security 3.2.5.RELEASE. When I send an HTTP GET request as an unauthenticated user, I am sent to the login page (as expected) where after I authenticate I am sent along to the page that was requested in the original GET.

当我作为未经身份验证的用户发送HTTP POST请求时,我被发送到登录页面(如预期的那样),但是在成功验证后,我被发送到我的default-target-url中指定的页面,而不是我原始POST请求中请求的页面。

When I send an HTTP POST request as an unauthenticated user, I am sent to the login page (as expected), but then after successful authentication I am sent to the page as specified in my "default-target-url" instead of the page as requested in my original POST request.

当我尝试使用与经过身份验证的用户相同的HTTP POST时,它运行正常(如预期的那样)。我已经尝试将always-use-default-target =false设置为以及完全省略该属性并且行为是相同的。

When I try this same HTTP POST as an authenticated user, it works just fine (as expected). I have already tried setting always-use-default-target="false" as well as omitting that property altogether and the behavior is the same.

我是否遗漏了某些内容?Spring是否应该在认证后传递POST请求,或者de不会发生这种情况出于某种原因签名?

Am I missing something? Should Spring pass along the POST request after authentication or does that not happen by design for some reason?

这是我的Spring安全配置:

Here is my Spring security config:

    <beans:beans xmlns="http://www.springframework.org/schema/security"
    xmlns:beans="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security-3.2.xsd">

    <http auto-config="true">
        <intercept-url pattern="/admin/**" access="ROLE_USER" />
        <form-login 
            login-page="/login.htm" 
            default-target-url="/hello.htm" 
            always-use-default-target="false"
            authentication-failure-url="/login.htm?error" 
            username-parameter="username"
            password-parameter="password" />
        <logout logout-success-url="/login.htm?logout" />
        <!-- enable csrf protection -->
        <csrf/>
    </http>

    <authentication-manager>
      <authentication-provider>
        <user-service>
        <user name="admin" password="password" authorities="ROLE_USER" />
        <user name="super" password="man" authorities="ROLE_SUPER_USER" />
        </user-service>
      </authentication-provider>
    </authentication-manager>

</beans:beans>

这是我开始测试的jsp(测试GET的链接和测试的表单) POST):

Here is my jsp to initiate the test (a link to test the GET and a form to test the POST):

<%@ include file="/WEB-INF/jsp/include.jsp" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>

<html>
  <head><title>TEST SECURITY</title></head>
  <body>
        <p><a href="admin/security_landing.htm">GET</a></p>
        <form:form  method="POST" action="admin/security_landing.htm"><input type="submit" value="POST"></form:form>

  </body>
</html>

这是一个安全资源的登陆页面:

Here is the landing page which is a secured resource:

<%@ include file="/WEB-INF/jsp/include.jsp" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>

<html>
  <head><title>TEST SECURITY LANDING PAGE</title></head>
  <body>
        <p>YOU MADE IT!!!!</p>
  </body>
</html>

这是我的测试控制器:

package springapp.web;

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


@Controller
public class TestController {

    /** Logger for this class and subclasses */
    protected final Log logger = LogFactory.getLog(getClass());

    @RequestMapping(value="test", method= RequestMethod.GET)
    public ModelAndView methodGet()
            {

        logger.info("Found it's way to the GET method");

        ModelAndView model = new ModelAndView();

        model.setViewName("security_test");

        return model;

    }

    @RequestMapping(value="/admin/security_landing", method=RequestMethod.POST)
    public ModelAndView sendToLandingPOST()
            {

        logger.info("Found it's way to the GET method");

        ModelAndView model = new ModelAndView();

        model.setViewName("/admin/security_landing");

        return model;

    }

    @RequestMapping(value="/admin/security_landing", method= RequestMethod.GET)
    public ModelAndView sendToLandingGET()
            {

        logger.info("Found it's way to the GET method");

        ModelAndView model = new ModelAndView();

        model.setViewName("/admin/security_landing");

        return model;

    }
}

我可以包含更多的春天配置,如果它是相关的,但应用程序正常工作与GET,但行为不端(在我看来)与POST,我认为它是孤立的我在这里显示的部分。

I can include more of the Spring configuration if it's relevant, but where the app is working fine with a GET but misbehaving (in my opinion) with a POST, I'm thinking it's isolated to the pieces I've shown here.

在我看来,Spring安全应该能够拦截POST并在身份验证后传递POST,就像GET一样。

It seems to me that Spring security should be able to intercept a POST and pass along the POST after authentication, just like a GET.

任何提示或者帮助将不胜感激。
谢谢,
Rob

Any hints or help would be appreciated. Thanks, Rob

推荐答案

正如所指出的,当启用CSRF时,Spring Security将只保存GET要求。原因是一旦用户进行认证就改变CSRF令牌以防止恶意用户在用户认证之前(即在公共设置中)找到CSRF。如果我们缓存了请求,那么它将使用旧的CSRF重放并且无论如何都会失败CSRF验证。

As pointed out, when CSRF is enabled Spring Security will only save GET requests. The reason is that the CSRF token is changed as soon as a user authenticates to prevent a malicious user from finding out the CSRF before a user authenticates (i.e. in a public setting). If we cached the request, then it would be replayed with the old CSRF and fail CSRF validation anyways.

通常,保存POST请求并自动处理它似乎是有点危险考虑一种公共计算机包含对常用站点的访问的情况。恶意用户对未经身份验证的应用程序执行POST,该应用程序将资金从当前经过身份验证的用户转移到其银行帐户。应用程序缓存POST,然后调出登录表单。恶意用户走开,受害者看到登录页面已经存在。此外,浏览器中的URL通过HTTPS正确显示。受害者登录并重播最初请求的POST请求,并自动将资金从受害者转移给恶意用户。

In general, saving a POST request and automatically processing it seems to be a bit dangerous. Consider a situation where a public computer contains access to a commonly used site. A malicious user performs a POST to the unauthenticated application that transfers funds from the currently authenticated user to their bank account. The application caches the POST and then brings up the log in form. The malicious user walks away and a victim sees that the log in page is already present. Furthermore the URL in the browser is correctly displayed and over HTTPS. The victim logs in and the originally requested POST request is replayed and automatically transfers funds from the victim to the malicious user.

相反,我们应该确保中间页面将要重播POST时显示。

Instead, we should probably be ensuring that an intermediate page is displayed when a POST is going to be replayed.

这篇关于Spring Security(3.2.5)HTTP POST在身份验证后不转发到原始请求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆