在单独的域上使用Apache运行Flask api和Angularjs前端正确配置Angularjs和CORS

在单独的域上使用Apache运行Flask api和Angularjs前端正确配置Angularjs和CORS,apache,angularjs,flask,cors,Apache,Angularjs,Flask,Cors,这一点在Stackoverflow中已经讨论过了,但我还没有找到解决方案来实现这一点。我甚至试着遵循本文()中讨论的很多内容,因为它与我的设置密切相关,但我仍然非常迷茫 我有一个本地运行的python flask api服务器。我已将此域命名为bac api。这是vhost的外观 <VirtualHost *:80> ServerName bac-api WSGIDaemonProcess bacapi python-path=/home/lumberjacked/

这一点在Stackoverflow中已经讨论过了,但我还没有找到解决方案来实现这一点。我甚至试着遵循本文()中讨论的很多内容,因为它与我的设置密切相关,但我仍然非常迷茫

我有一个本地运行的python flask api服务器。我已将此域命名为bac api。这是vhost的外观

<VirtualHost *:80>
    ServerName bac-api

    WSGIDaemonProcess bacapi python-path=/home/lumberjacked/workspace/bas/development/lib/python2.7/site-packages
    WSGIScriptAlias / /home/lumberjacked/workspace/bas/development/bac-api/bacapi.wsgi
    Header set Access-Control-Allow-Origin "*"
    Header set Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept, application/json"
    Header set Access-Control-Allow-Methods "POST, GET, OPTIONS"

    <Directory /home/lumberjacked/workspace/bas/development/bac-api>
        WSGIProcessGroup bacapi
        WSGIApplicationGroup %{GLOBAL}
        Order deny,allow
        Allow from all
    </Directory>

#SSLEngine on
#SSLCertificateFile /etc/apache2/ssl/bac_api_ssl.crt
#SSLCertificateKeyFile /etc/apache2/ssl/bac_api_ssl.key
</VirtualHost>
还将管理.bac并放置我的登录凭据email@email.com密码我得到了相同的响应,但我也将其配置为如果您未通过存储会话的身份验证,则返回401

POST http://bac-api/authenticated/ 401 (UNAUTHORIZED) bac-api/authenticated/:1
当我切换到ssl证书和端口443时,问题就开始了。因此,如果在两个域上,我将vhost切换到端口443并取消对ssl证书的注释。在重新启动apache之后,没有任何错误,并且域可以工作到不显示任何类型的错误或类似错误的程度。我可以使用https连接到BACAPI服务器并获得响应

curl -k -X POST -H "Content-Type: application/json" -d '{ "api": "7f3d6d7338b921ae4ca95cecc452ef1790005ec10c2343fabe5a59ea" }' https://bac-api/authenticated/

response -- {"authenticated": false}
但当我转到并重定向到登录页面时,所有的麻烦似乎都开始了

只要我在登录字段中单击,控制台就会抛出这个错误,我不知道它是否相关

Blocked a frame with origin "https://manage.bac" from accessing a frame with origin "chrome-extension://hdokiejnpimakedhajhdlcegeplioahd".  The frame requesting access has a protocol of "https", the frame being accessed has a protocol of "chrome-extension". Protocols must match.
下面是我的angularjs身份验证代码,其中console.log方法输出了一些东西

$http.post('https://bac-api/login/', user)
            .success( function( user ) {
                console.log('success');
                console.log(user);                     
            })
            .error( function( error ) {
                console.log('error');
                console.log(error);
            });

Object {email: "email@email.com", password: "password"} authentication-service.js:36
error authentication-service.js:50
                  authentication-service.js:51
当此错误返回时,响应中根本没有任何内容。我可以在chrome工具的网络选项卡中看到,这个请求被预先触发,因为它正在向服务器发送一个选项

OPTIONS /login/ HTTP/1.1
Host: bac-api
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Origin: https://manage.bac
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type,x-requested-with
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
我还可以在网络选项卡中看到它显示为一个选项,并且它已被取消。我不知道这是什么意思

我已经在angularjs内部配置了这些选项,但似乎对任何事情都没有影响

config(['$httpProvider', function($httpProvider) {
        $httpProvider.defaults.useXDomain = true;
        delete $httpProvider.defaults.headers.common['X-Requested-With'];

    }
]);
在我的flask应用程序中,我还尝试实现这里提到的decorator,以及其他stackoverflow文章中提到的decorator。这似乎也没什么作用。我还假设,因为我在vhost中放入了api服务器的访问头,所以我真的不需要在应用程序中执行相同的操作。虽然我可能完全错了,因为我不知道我在做什么

非常感谢您的帮助。我很抱歉,如果这似乎是一个重复的问题,但到目前为止,我无法让这项工作,我已经尝试了每一个关于stackoverflow的帖子,我可以解决这个问题

---用更新的信息编辑

今天早上,作为一个实验,我将两个vhost切换回端口80,并注释掉了所有Allow access头。重新启动并再次尝试登录,以下是我的结果

Failed to load resource: Origin http://manage.bac is not allowed by Access-Control-Allow-Origin. http://bac-api/authenticated/
XMLHttpRequest cannot load http://bac-api/authenticated/. Origin http://manage.bac is not allowed by Access-Control-Allow-Origin. manage.bac/:1
因此,在这个错误之后,我进入了我的bac api vhost和未注释的标题集Access Control Allow Origin“*”,然后重新启动并尝试登录。以下是显示的新错误

OPTIONS http://bac-api/authenticated/ Request header field Content-Type is not allowed  by Access-Control-Allow-Headers. angular.js:9312
(anonymous function) angular.js:9312
sendReq angular.js:9146
$http angular.js:8937
Authenticator.isLoggedIn authentication-service.js:13
RouteConfig.login.resolve.Auth state-service-provider.js:16
invoke angular.js:2902
(anonymous function) angular-ui-router.js:801
forEach angular.js:137
resolve angular-ui-router.js:797
resolveState angular-ui-router.js:813
transitionTo angular-ui-router.js:704
(anonymous function) angular-ui-router.js:615
invoke angular.js:2902
handleIfMatch angular-ui-router.js:433
rule angular-ui-router.js:452
update angular-ui-router.js:487
Scope.$broadcast angular.js:8307
afterLocationChange angular.js:5649
(anonymous function) angular.js:5637
Scope.$eval angular.js:8057
Scope.$digest angular.js:7922
Scope.$apply angular.js:8143
(anonymous function) angular.js:981
invoke angular.js:2895
resumeBootstrapInternal angular.js:979
bootstrap angular.js:993
angularInit angular.js:954
(anonymous function) angular.js:14843
c jquery-1.10.1.min.js:4
p.fireWith jquery-1.10.1.min.js:4
x.extend.ready jquery-1.10.1.min.js:4
q jquery-1.10.1.min.js:4
XMLHttpRequest cannot load http://bac-api/authenticated/. Request header field Content- Type is not allowed by Access-Control-Allow-Headers. manage.bac/:1
因此,为了解决此错误并允许内容类型通过,我返回到我的bac api vhost,并添加回标题集访问控制允许标题“内容类型”。在页面加载时重新启动浏览以管理.bac之后,以下是这些结果

POST http://bac-api/authenticated/ 401 (UNAUTHORIZED) bac-api/authenticated/:1
Object {email: "email@email.com", password: "password"} authentication-service.js:36
success authentication-service.js:40
Object {login: false} authentication-service.js:41
这很好,因为这意味着我收到了一个{“authenticated”:false}响应,它返回了一个未经授权的401。如果我继续并尝试登录,我会得到这些结果

POST http://bac-api/authenticated/ 401 (UNAUTHORIZED) bac-api/authenticated/:1
Object {email: "email@email.com", password: "password"} authentication-service.js:36
success authentication-service.js:40
Object {login: false} authentication-service.js:41
这也在起作用。下面是生成此输出的angularjs代码

$http.post('http://bac-api/login/', user)
            .success( function( user ) {
                console.log('success');
                console.log(user);                    
            })
            .error( function( error ) {
                console.log('error');
                console.log(error);
            });
现在我的想法是可怕的,如果它在80端口工作,我可以切换到443端口现在,并继续滚动。因此,我将vhost切换到端口443,并再次浏览manage.bac以登录。在页面加载时,甚至在尝试登录之前,我都会得到这些结果

POST http://bac-api/authenticated/ 401 (UNAUTHORIZED) bac-api/authenticated/:1
Object {email: "email@email.com", password: "password"} authentication-service.js:36
success authentication-service.js:40
Object {login: false} authentication-service.js:41

当我再次尝试登录并提交表单时,我也会得到这些结果

Object {email: "email@email.com", password: "password"} authentication-service.js:36
error authentication-service.js:50
         authentication-service.js:51
也在网络选项卡上

这只是试图给每个人更多的信息,帮助我找到这个问题的原因

-----请使用更多信息再次编辑

今晚,我开始尝试用curl测试这一点,看看有哪些标题返回了选项请求

这是curl请求,我直接从Network选项卡复制了它,假设这是angularjs发送的同一个OPTIONS请求。首先,我将从“网络”选项卡中输入选项请求,然后输入我的curl请求

OPTIONS https://bac-api/login/ HTTP/1.1
Access-Control-Request-Method: POST
Origin: https://manage.bac
Referer: https://manage.bac/
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko)    Chrome/29.0.1547.76 Safari/537.36
Access-Control-Request-Headers: accept, origin, x-requested-with, content-type

curl -i -k -X OPTIONS -H "Access-Control-Request-Method: POST" -H "Origin: https://manage.bac" -H "Referer: https://manage.bac/" -H "Access-Control-Request-Headers: accept, origin, content-type" https://bac-api/login/
下面是curl的回应

HTTP/1.1 200 OK
Date: Tue, 01 Oct 2013 02:51:17 GMT
Server: Apache/2.2.22 (Ubuntu)
Allow: POST, OPTIONS
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, OPTIONS
Access-Control-Max-Age: 21600
Content-Length: 0
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept
Access-Control-Allow-Methods: POST, GET, OPTIONS
Vary: Accept-Encoding
Content-Type: text/html; charset=utf-8 

这似乎表明服务器配置正确,并使用正确的头响应选项请求。但是,正如我在上面的图片中所发布的,当我在浏览器中运行这个程序时,仍然在“网络”选项卡上,它被取消,错误响应中没有返回任何内容。

我能够解决这个问题,这是最愚蠢的事情。我将挖掘其他帮助我找到解决方案的stackoverflow帖子。但基本上在测试过程中,我生成了自签名证书以在本地使用。显然,如果firefox和chrome在跨域发布时不信任证书,它们会自动取消您的请求。在chrome和firefox停止取消请求之前,我必须进入chrome和firefox添加证书并将它们标记为可信。现在一切都很好

curl -k -X POST -H "Content-Type: application/json" -d '{ "api": "7f3d6d7338b921ae4ca95cecc452ef1790005ec10c2343fabe5a59ea" }' https://bac-api/authenticated/

response -- {"authenticated": false}
在本次调查中,我还发现,您不需要将请求助手添加到Flask中,就可以将头添加到响应和Apache配置中。如果你把它们都放在这两个地方,它会同时添加标题。在我的配置中,我选择将它添加到我的Apache配置中,因为它使我的python代码更加干净