1

我遇到了我以前见过的最奇怪的问题。

我正在开发的应用程序使用 spring security 3.1.3 来提供身份验证支持。有一个自定义登录表单,我为其实现了自定义身份验证管理器/成功处理程序和失败处理程序。

出于某种原因,在 Internet Explorer 上,我总是收到错误消息“请填写所有必填字段”。这是由于将 /login?error=1 附加到我的 url 的末尾,只能通过以下代码(redirectAndAddError 方法)访问该 URL:

public class TideUserNamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

public TideUserNamePasswordAuthenticationFilter() {
    super();
}

@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) {

    String username = request.getParameter(SPRING_SECURITY_FORM_USERNAME_KEY);
    String password = request.getParameter(SPRING_SECURITY_FORM_PASSWORD_KEY);

    if (StringUtils.isBlank(username) || StringUtils.isBlank(password)) {
        redirectAndAddError(response);
        return null;
    }

    return super.attemptAuthentication(request, response);
}

private void redirectAndAddError(HttpServletResponse response) {
    try {
        response.sendRedirect("/tide/login?error=1");
    } catch (IOException e) {
        throw new AuthenticationServiceException(e.getMessage(), e);
    }
}

所以我尝试使用 Fiddler2,一个 Web 调试代理来查看两个参数之一是否实际上为空。奇怪的是,当这个程序运行时,错误不再发生,我可以成功登录。

以前有没有人遇到过类似的问题?我认为这与我的代码无关,因为运行该工具突然“解决”了问题。

这个问题只发生在 Internet Explorer 中,这使得它更加奇怪。

编辑

我使用了另一个工具来查看请求,这就是 IE 中发生的情况:

首先一个 POST 请求被发送到 uri /authenticate,我自己设置了这个:

<beans:property name="filterProcessesUrl" value="/authenticate"/>

该请求的响应具有 http 状态代码 302,临时移动并返回新位置位于 /login?error=1 (我的表单带有必填字段需要错误)。

之后,向 /login?error=1 发出 GET 请求,状态码为 401:未授权。拦截 URL 设置如下:

 <intercept-url pattern="/login**" access="permitAll"/>

下一个请求是对 /login?error=1 的 GET 请求,这次状态码显示:ERROR_INTERNET_CONNECTION_RESET,看起来可能是个问题。

在 Google Chrome 中,发出以下请求:

POST 到 /authenticate,结果是 302: 临时移动到仪表板页面(我在登录后显示)

4

1 回答 1

0

在 chromium bugtracker 中发现这个问题后,我团队中的某个人终于弄清楚了问题所在:

https://code.google.com/p/chromium/issues/detail?id=62687

通过在我们的登录控制器中添加此问题已解决

@RequestMapping(value = "/login", method = RequestMethod.POST)
public String doLogin() throws ServletException, IOException {
    return "forward:/authenticate";
}

并将表单发布到的 url 更改为这个,而不是 spring security 提供的身份验证 url(我们现在手动重定向到它)

于 2013-05-21T07:58:31.243 回答