对 HTTPS 的 Ajax 调用失败

Posted

技术标签:

【中文标题】对 HTTPS 的 Ajax 调用失败【英文标题】:Ajax call to HTTPS failing 【发布时间】:2012-06-17 08:50:13 【问题描述】:

我正在尝试调用我的 Spring-MVC 控制器,该控制器将负责使用 Spring 安全性继续使用登录/授权机制。

这里是要求

    Spring 安全需要来自 HTTPS 的请求,否则会抛出错误。

我按照以下教程完成了这个/implementing_ajax_authentication_using_jquery。

这是我的一段 Jquery 代码

jQuery("#loginForm").submit(function(e) 
        e.preventDefault();
        jQuery.ajax(
            url: "https://localhost:9002/myApp/springSecurity/login.json",
            beforeSend: function(xhr) 
                xhr.withCredentials = true;
            ,
            type: "POST",
            data: jQuery("#loginForm").serialize(),
            dataType: 'application/json',

            success: function(data, status) 

                if (data.loggedIn) 
                   // location.href = getHost() + '$ctx/users';
                    //login_pannel
                    alert("jai ho");
                 else 
                    loginFailed(data);
                
            ,
            error: loginFailed
        );

    );

为了处理跨域问题,我创建了一个过滤器并将其放在我的 web.xml 中,并带有以下条目

response.setHeader("Access-Control-Allow-Origin", "http://" + req.getServerName());
response.setHeader("Access-Control-Allow-Methods", "GET,POST");
response.setHeader("Access-Control-Max-Age", "360");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
response.setHeader("Access-Control-Allow-Credentials", "true"); 

弹簧控制器

@RequestMapping(method = RequestMethod.POST)
@ResponseBody
public SpringSecurityLoginStatus login(@RequestParam("j_username") final String username,
            @RequestParam("j_password") final String password, final HttpServletRequest request, final HttpServletResponse response)
    

        LOG.info("Starting login process");
        return springSecurityLoginService.login(username, password, request, response);
    

但是我遇到了一个奇怪的问题,当我点击提交按钮时,浏览器正在向安全 URL 发送请求,例如 https://localhost:9002/myApp/springSecurity/login.json 但我的控制器方法从未被调用,实际上这是我在 Mozilla 中看到的错误错误控制台

查看控制台后,浏览器似乎再次使用 GET 方法调用,这似乎是一个重定向。

我不确定为什么会发生这种情况,以及为什么浏览器使用 GET 请求静默地从 HTTPS 重定向到 HTTP

这是 Mozila 网络面板的输出

响应头视图源

Access-Control-Allow-Cred...    true
Access-Control-Allow-Head...    x-requested-with
Access-Control-Allow-Meth...    GET,POST
Access-Control-Allow-Orig...    https://localhost
Access-Control-Max-Age  360
Content-Length  0
Date    Thu, 14 Jun 2012 11:12:36 GMT
Location    http://localhost:9001/myapp/springSecurity/login.json
Server  Apache-Coyote/1.1
Set-Cookie  _system.tenantID_=""; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/
Request Headersview source
Accept  text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding gzip, deflate
Accept-Language en-us,en;q=0.5
Connection  keep-alive
Cookie  JSESSIONID=26BEEB7DC056D2A5F08D107E3D4BCDDB; __atuvc=4|22; secureGUID=60be684d748027c1f567eadead08f28771ab7d25; JSESSIONID=4E2300220697C799AF4539ABCB9108DD
Host    localhost:9002
Referer http://localhost:9001/myapp/
User-Agent  Mozilla/5.0 (Windows NT 6.1; WOW64; rv:12.0) Gecko/20100101 Firefox/12.0

来自缓存的响应标头

Access-Control-Allow-Cred...    true
Access-Control-Allow-Head...    x-requested-with
Access-Control-Allow-Meth...    GET,POST
Access-Control-Allow-Orig...    https://localhost
Access-Control-Max-Age  360
Content-Length  0
Date    Thu, 14 Jun 2012 11:12:36 GMT
Location    http://localhost:9001/myapp/springSecurity/login.json
Server  Apache-Coyote/1.1
Set-Cookie  _system.tenantID_=""; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/

附带说明,如果我将 URL http://localhost:9001/myapp/springSecurity/login.json 更改为 HTTP 协议,它能够调用我的控制器。

响应类

public class SpringSecurityLoginStatus


    private final boolean loggedIn;
    private final String username;

    public SpringSecurityLoginStatus(final boolean loggedIn, final String username)
    
        this.loggedIn = loggedIn;
        this.username = username;
    

    public boolean isLoggedIn()
    
        return loggedIn;
    

    public String getUsername()
    
        return username;
    

【问题讨论】:

【参考方案1】:

您似乎还没有为 url 'login.json' 实现 'GET' 方法。

如果您查看控制器,它仅实现 POST 请求方法,但您的请求类型是 GET,这就是您收到此错误的原因。

你能分享一下你的login方法的返回值吗?

您的登录方法似乎返回了302 moved temporarily 状态。

【讨论】:

我不知道为什么我需要一个 GET 方法,因为我的想法是触发 spring 安全认证过程并返回状态。我不确定请求类型为 GET,因为我有提到它为POST。这是我的登录方法@RequestMapping(method = RequestMethod.POST) @ResponseBody public SpringSecurityLoginStatus login(@RequestParam("j_username") final String username,@RequestParam("j_password") final String password, final HttpServletRequest request, final HttpServletResponse response)/impl的签名。好吧,我没有从我的控制器返回302,它永远不会调用 问题看起来像您的 login 方法返回的值。你能解释一下返回值吗?并且还共享响应标头。登录成功后你想做什么? 返回类型是一个简单的POJO,有2个字段,1是布尔值,其他是字符串 你能分享返回值和响应头吗?你能告诉我springSecurityLoginService.login()里面发生了什么吗,你在那个方法里面设置了任何响应状态吗? 我已经更新了问题并且在springSecurityLoginService.login()里面我只是使用Spring Security登录机制。我最大的惊喜是当从HTTPS发送请求时我的控制器永远不会被调用并且它要求@ 987654333@ 方法在使用 HTTP 时工作正常,但在 spring 安全性中失败

以上是关于对 HTTPS 的 Ajax 调用失败的主要内容,如果未能解决你的问题,请参考以下文章

对 ASP.NET Web 服务的 jQuery ajax POST 调用随机失败

对同一 URL 的第二次 AJAX 调用失败 - 但随机且很少工作

ASP.NET Core 2:使用 [Authorize] 对 API 的 Ajax 调用使预检请求失败

在 jQuery 中,如何在 ajax 调用失败时恢复可拖动对象?

确定ajax调用是不是由于不安全的响应或连接被拒绝而失败

AJAX:当函数调用失败/错误时,是不是可以从服务器端返回自定义错误消息? [复制]