2013-12-19 40 views
29

我正在使用AngularJS v1.2.4。

我有角发送预检OPTIONS调用的问题(Chrome的显示OPTIONS调用为“取消”),并解决它:

$httpProvider.defaults.useXDomain = true; 
delete $httpProvider.defaults.headers.common['X-Requested-With']; 

,对我所有的$的资源调用的工作,一切都很好。

现在我正在尝试实现身份验证,并使用用户凭据向我的服务器发送POST请求的登录页面。我看到我以前面临的问题,但$资源调用仍然正常工作。

真正令人沮丧的是,问题是间歇性地发生的;我将更改头部的一些选项,然后它会工作一段时间,并在没有任何代码更改的情况下再次停止工作。

我的服务器配置为CORS,并且可以很好地处理curl和其他REST客户端。这里有一个例子:

curl -X OPTIONS -ik 'https://localhost:3001/authenticate' -H "Origin: https://localhost:8001" 
HTTP/1.1 200 OK 
content-type: application/json; charset=utf-8 
content-length: 2 
cache-control: no-cache 
access-control-allow-origin: * 
access-control-max-age: 86400 
access-control-allow-methods: GET, HEAD, POST, PUT, DELETE, OPTIONS 
access-control-allow-headers: Authorization, Content-Type, If-None-Match, Access-Control-Allow-Headers, Content-Type 
access-control-expose-headers: WWW-Authenticate, Server-Authorization 
set-cookie: session=Fe26.2**94705d49717d1273197ae86ce6661775627d7c6066547b757118c90c056e393b*2KYqhATojPoQhpB2OwhDwg*W9GsJjK-F-UPqIIHTBHHZx1RXipo0zvr97_LtTLMscRkKqLqr8H6WiGd2kczVwL5M25FBlB1su0JZllq2QB-9w**5510263d744a9d5dc879a89b314f6379d17a39610d70017d60acef01fa63ec10*pkC9zEOJTY_skGhb4corYRGkUNGJUr8m5O1US2YhaRE; Secure; Path=/ 
Date: Wed, 18 Dec 2013 23:35:56 GMT 
Connection: keep-alive 

这里的$ http.post电话:

var authRequest = $http.post('https://' + $location.host() + ':3001/authenticate', {email: email, password: password}); 

当从我的应用程序工作的号召,这是OPTIONS请求的样子:

enter image description here

当它不起作用时,这是OPTIONS请求:

enter image description here

它看起来像一大堆的标题属性丢失。有没有人遇到类似的问题?

编辑:

只是为了澄清,当它不工作,从来没有要求它向服务器 - 它在浏览器立即中止。

enter image description here

在Firebug中,请求头是:

OPTIONS /authenticate HTTP/1.1 
Host: localhost:3001 
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:25.0) Gecko/20100101 Firefox/25.0 
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 
Accept-Language: en-US,en;q=0.91,en-GB;q=0.82,fr-FR;q=0.73,fr;q=0.64,utf-8;q=0.55,utf;q=0.45,de-DE;q=0.36,de;q=0.27,en-sg;q=0.18,en-ca;q=0.09 
Accept-Encoding: gzip, deflate 
Origin: https://localhost:8001 
Access-Control-Request-Method: POST 
Access-Control-Request-Headers: content-type 
Proxy-Authorization: Basic cGF0cmljZUB6b25nLmNvbTpjaGFuZ2VtZQ== 
Connection: keep-alive 
Pragma: no-cache 
Cache-Control: no-cache 

enter image description here

更新:

我已经与服务器消除了可能的问题,我觉得通过将主机更改为不存在的服务器。仍然看到相同的行为。

下面是一些代码:

App.services.factory('AuthService', function ($http, $location, $q) { 

    var currentUser; 

    return { 
     authenticate: function (email, password) { 

      //promise to return 
      var deferred = $q.defer(); 

      var authRequest = $http.post('https://this.does.not.exist.com:3001/authenticate', {email: email, password: password}); 

      authRequest.success(function (data, status, header, config) { 
       currentUser = data; 
       console.log('currentUser in service set to:'); 
       console.log(currentUser); 
       //resolve promise 
       deferred.resolve(); 
      }); 

      authRequest.error(function (data, status, header, config) { 
       console.log('authentication error'); 
       console.log(status); 
       console.log(data); 
       console.log(header); 
       console.log(config); 

       //reject promise 
       deferred.reject('authentication failed..'); 
      }); 

      return deferred.promise; 
     }, 
     isAuthenticated: function() { 
      return currentUser !== undefined; 
     } 
    }; 
}); 

和HTTP配置:

App.config(['$httpProvider', function ($httpProvider) { 

    $httpProvider.defaults.useXDomain = true; 
    //$httpProvider.defaults.headers.common = {}; 

    console.log('logging out headers'); 
    console.log($httpProvider.defaults); 
    console.log($httpProvider.defaults.headers.common); 
    console.log($httpProvider.defaults.headers.post); 
    console.log($httpProvider.defaults.headers.put); 
    console.log($httpProvider.defaults.headers.patch); 
    console.log('end logging out headers'); 

    $httpProvider.defaults.headers.common = {Accept: "application/json, text/plain, */*"}; 
    $httpProvider.defaults.headers.post = {"Content-Type": "application/json;charset=utf-8"}; 

    console.log('after: logging out headers'); 
    console.log($httpProvider.defaults.headers.common); 
    console.log($httpProvider.defaults.headers.post); 
    console.log($httpProvider.defaults.headers.put); 
    console.log($httpProvider.defaults.headers.patch); 
    console.log('after: end logging out headers'); 

    $httpProvider.interceptors.push(function ($location, $injector) { 
     return { 
      'request': function (config) { 

       console.log('in request interceptor!'); 

       var path = $location.path(); 
       console.log('request: ' + path); 

       //injected manually to get around circular dependency problem. 
       var AuthService = $injector.get('AuthService'); 
       console.log(AuthService); 
       console.log(config); 

       if (!AuthService.isAuthenticated() && $location.path() != '/login') { 
        console.log('user is not logged in.'); 
        $location.path('/login'); 
       } 

       //add headers 
       console.log(config.headers); 
       return config; 
      } 
     }; 
    }); 
}]); 
+1

你确定你的脚本/应用程序没有发送双重请求吗?同步(表单提交)+异步请求到相同的网址? – asumaran

+0

@asumaran你能澄清吗?我很确定这只是一个单一的请求。 – shaunlim

+0

使用Firebug来调试CORS问题。 Chrome有一个已知的问题,并不会显示所有可用的信息。 https://code.google.com/p/chromium/issues/detail?id=269192&q=CORS&colspec=ID%20Pri%20M%20Iteration%20ReleaseBlock%20Cr%20Status%20Owner%20Summary%20OS%20Modified – TheSharpieOne

回答

13

这感觉就像它可能与你正在打在你的本地主机的https端点的事实。这意味着您可能正在使用某种自签名SSL证书,这可能意味着Chrome认为它不受信任。

我想先尝试直接转到/ authenticate端点,看看Chrome是否会给您一个关于不可信证书的警告。看看是否接受该警告的作品。

否则,当您在本地测试时,您可能只需要点击一个http端点并查看是否解决了问题?

+0

嘿迈克尔,谢谢你的回应! HTTPS问题可能是一种可能性,但我也在我的应用程序的其他部分使用$ resource对象访问HTTPS端点(在同一服务器上),并且在那里一切似乎都没问题。无论如何,明天早上我会提出你的建议。 – shaunlim

+0

我访问了Chrome中的'/ authenticate'端点,并且没有关于不受信任的证书的警告;当我第一次开始开发应用程序时,我可能在此之前接受了它。 – shaunlim

+0

而且,当我更改为调用$ http.get并且在服务器上有相应的GET /身份验证端点时,它似乎可以正常工作。 – shaunlim

9

非常感谢Michael Cox for pointing me in the right direction。我接受了他的答案,因为它使我的解决方案,但这里有更多的细节:

展望https的问题,我发现:

我的问题虽然略有不同。在我遵循上述链接中的说明后,它仍然无法工作。我仔细阅读了Chrome的“不可信”消息,它就像“你试图访问mylocalhost.com,但服务器代表自己是”。

事实证明,我匆匆创建自签名证书为“server.crt这”时,它应该是“mylocalhost.crt”

7

你不能Access-Control-Allow-Origin: *allow-credentials在一起。

重要注意事项:当响应有证书请求时,服务器必须指定一个域,并且不能使用通配。

关于GET请求,如果它们没有特殊标题,它们不需要预检等。

来源:Mozilla Developer Network。 (网络上最好的CORS链接!)

相关问题