2014-01-30 108 views
86

因为在AngularJS中使用CORS和http身份验证可能会非常棘手,所以我编辑了这个问题以分享一个有用的课程。首先我要感谢igorzg。他的回答帮了我很多。该方案如下:您想通过AngularJS $ http服务将POST请求发送到其他域。在获取AngularJS和服务器设置时需要注意几件棘手的事情。

第一: 在你的应用程序配置,你必须允许跨域调用

/** 
* Cors usage example. 
* @author Georgi Naumov 
* [email protected] for contacts and 
* suggestions. 
**/ 
app.config(function($httpProvider) { 
    //Enable cross domain calls 
    $httpProvider.defaults.useXDomain = true; 
}); 

二: 您必须指定withCredentials:真实的用户名和密码 请求。

/** 
    * Cors usage example. 
    * @author Georgi Naumov 
    * [email protected] for contacts and 
    * suggestions. 
    **/ 
    $http({ 
     url: 'url of remote service', 
     method: "POST", 
     data: JSON.stringify(requestData), 
     withCredentials: true, 
     headers: { 
      'Authorization': 'Basic bashe64usename:password' 
     } 
    }); 

第三方: 服务器设置。您必须提供:

/** 
* Cors usage example. 
* @author Georgi Naumov 
* [email protected] for contacts and 
* suggestions. 
**/ 
header("Access-Control-Allow-Credentials: true"); 
header("Access-Control-Allow-Origin: http://url.com:8080"); 
header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS"); 
header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization"); 

对于每个请求。当您收到选项,则必须通过:

/** 
* Cors usage example. 
* @author Georgi Naumov 
* [email protected] for contacts and 
* suggestions. 
**/ 
if($_SERVER['REQUEST_METHOD'] == 'OPTIONS') { 
    header("HTTP/1.1 200 OK"); 
    exit(); 
} 

HTTP认证和其他一切来之后。

这是服务器端使用php的完整示例。

<?php 
/** 
* Cors usage example. 
* @author Georgi Naumov 
* [email protected] for contacts and 
* suggestions. 
**/ 
header("Access-Control-Allow-Credentials: true"); 
header("Access-Control-Allow-Origin: http://url:8080"); 
header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS"); 
header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization"); 

if($_SERVER['REQUEST_METHOD'] == 'OPTIONS') { 
    header("HTTP/1.1 200 OK"); 
    exit(); 
} 


$realm = 'Restricted area'; 

$password = 'somepassword'; 

$users = array('someusername' => $password); 


if (isset($_SERVER['PHP_AUTH_USER']) == false || isset($_SERVER['PHP_AUTH_PW']) == false) { 
    header('WWW-Authenticate: Basic realm="My Realm"'); 

    die('Not authorised'); 
} 

if (isset($users[$_SERVER['PHP_AUTH_USER']]) && $users[$_SERVER['PHP_AUTH_USER']] == $password) 
{ 
    header("HTTP/1.1 200 OK"); 
    echo 'You are logged in!' ; 
    exit(); 
} 
?> 

在我的博客上有关于这个问题的文章,可以看到here

+0

的问题是编辑。 –

+2

我有点困惑,它的angularjs,但你有它包裹在PHP标签....我错过了什么? – onaclov2000

+0

这只是服务器端逻辑的一个例子。 “Тhird:服务器设置”下面的文本是服务器端逻辑。 –

回答

42

不,你不必把凭证,你必须把对客户端如标题:

$http({ 
     url: 'url of service', 
     method: "POST", 
     data: {test : name }, 
     withCredentials: true, 
     headers: { 
        'Content-Type': 'application/json; charset=utf-8' 
     } 
    }); 

而且和在服务器端,你必须把报头到这是为例子的NodeJS:

/** 
* On all requests add headers 
*/ 
app.all('*', function(req, res,next) { 


    /** 
    * Response settings 
    * @type {Object} 
    */ 
    var responseSettings = { 
     "AccessControlAllowOrigin": req.headers.origin, 
     "AccessControlAllowHeaders": "Content-Type,X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Date, X-Api-Version, X-File-Name", 
     "AccessControlAllowMethods": "POST, GET, PUT, DELETE, OPTIONS", 
     "AccessControlAllowCredentials": true 
    }; 

    /** 
    * Headers 
    */ 
    res.header("Access-Control-Allow-Credentials", responseSettings.AccessControlAllowCredentials); 
    res.header("Access-Control-Allow-Origin", responseSettings.AccessControlAllowOrigin); 
    res.header("Access-Control-Allow-Headers", (req.headers['access-control-request-headers']) ? req.headers['access-control-request-headers'] : "x-requested-with"); 
    res.header("Access-Control-Allow-Methods", (req.headers['access-control-request-method']) ? req.headers['access-control-request-method'] : responseSettings.AccessControlAllowMethods); 

    if ('OPTIONS' == req.method) { 
     res.send(200); 
    } 
    else { 
     next(); 
    } 


}); 
+1

我的工作示例是:http://www.igorivanovic.info/ 你可以在github上看到完整的代码: https://github.com/igorzg/js_cms/ – igorzg

+0

with CORS一般来说,服务器是否必须允许所有的**头(Content,Content-Length,Referer等等)出现在真实的非OPTIONS请求中? –

+0

@KevinMeredith不,你不需要允许所有的标题,你可以只允许你需要的,你甚至可以限制到一个域。 – igorzg

3

为了创建一个CORS请求,必须在请求中添加标题,并且需要检查在Apache中启用的mode_header。

对于在Ubuntu使头:

sudo a2enmod headers 

为PHP服务器接受来自不同来源的使用请求:

Header set Access-Control-Allow-Origin * 
Header set Access-Control-Allow-Methods "GET, POST, PUT, DELETE" 
Header always set Access-Control-Allow-Headers "x-requested-with, Content-Type, origin, authorization, accept, client-security-token"