Angular和CORS一劳永逸

时间:2015-08-06 11:09:58

标签: angularjs .htaccess mediawiki

我一直在努力解决这个问题已经有一段时间了,除了决定我热情地讨厌CORS之外,我还可以确认互联网上充满了各种想法,但很少有人能够解决这个问题,所以我想会试着一劳永逸地得到答案。

目标是编写可以执行以下操作的角度代码。 1.设置标头以允许CORS。 2.登录到启用CORS的应用程序(在本例中为media wiki) 3.进行api调用以接收一些JSON数据。

我甚至会设置一个测试mediawiki服务器(使用语义媒体wiki)并为此设置一个测试用户。谁知道,如果人们对此感兴趣,我甚至会尝试使用答案为Angular编写世界上最简单的CORS模块。

在服务器上我会做三件事。 安装mediawiki和语义媒体wiki 更改设置(在LocalSettings.php中)

$wgEnableAPI = true;
$wgCrossSiteAJAXdomains = array( 'http://127.0.0.1:30004' );
$wgAPIRequestLog = "$IP/log/wgAPIRequestLog.log"; 

并更改.htaccess以设置标题。

# CORS Headers (add this)
<ifModule mod_headers.c>
    Header always set Access-Control-Allow-Origin: "*"
    Header always set Access-Control-Allow-Methods "POST, GET, PUT, DELETE, OPTIONS"
    Header always set Access-Control-Allow-Headers "X-Requested-With, content-type"
</ifModule>

# BEGIN WordPress (you should have this in your original WP .htaccess)
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /

# CORS OPTIONS (add this too)
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ $1 [R=200,L]

我认为这就是我需要做的所有事情,因为我只能在使用chome扩展来转换原始标题后才能以角度形式发出CORS请求,我不知道这是否会起作用。

同时,如果有人对此有任何想法或好资源。请发帖。

======================现在设置=====================

现在为此目的设置了一个mediawiki Mediawiki网址'http://v-ghost.port0.org:8081/apiwiki'
用户'whowillhelp'
密码'InternetWill'

如果您想尝试API调用: http://v-ghost.port0.org:8081/apiwiki/api.php?action=ask&query=[[Msgtype::1]]|%3FMenuName&format=jsonfm

如果您尚未登录,则会返回:

{
    "error": {
        "code": "readapidenied",
        "info": "You need read permission to use this module",
        "*": "See http://v-ghost.port0.org:8081/apiwiki/api.php for API usage"
    }
}

多数好吧。 如果你以角度运行相同的http.get('http://v-ghost.port0.org:8081/apiwiki/api.php?action=ask&query=[[Msgtype::1]]|%3FMenuName&format=json',你会得到一个

XMLHttpRequest cannot load http://v-ghost.port0.org:8081/apiwiki/api.php?action=ask&query=[[MsgType::1]][[Parent::Support%20Functions]]|%3FMenuName&format=jsonfm. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://127.0.0.1:30004' is therefore not allowed access.

2 个答案:

答案 0 :(得分:0)

谢谢Quentin。

经过大量的讨论之后,事实证明CORS完全由服务器控制,而Web服务器则不是应用程序。

所需的一切(一旦API开启)就是将内容添加到.htaccess文件中。配置Apache以读取它(http.conf)。 您还需要确保加载mod_headers(在httpd -t -D DUMP_MODULES时称为headers_module),但它应该是Apache 2的默认值。

如果有疑问,有一个测试服务:) http://client.cors-api.appspot.com/

=================似乎现在正在工作===================

当我试图成为一个善良的人回馈。这是我写的工厂。从技术上讲,如果您只想运行查询,则需要三次调用(如果需要登录)。希望它可以帮助某人

我们可能值得一提,Mediawiki(可能还有所有CORS实现)要求您登录两次,一次用于身份验证,一次使用之前发送的令牌。猜测这与构建cookie有关。

.factory('CORSconnectFactory', function($http, $q){
    //To call any of the http calls just do 
    //    CORSconnectFactory.login(options )
    //          .then(function(data)
    var CORSconnectFactory = {};
    var CORScredentials = {};
    var urlInit;
    var deferred = $q.defer();
    var datareq = {
        method: 'POST',
        //url: 'http://v-ghost.port0.org:8081/dbfswiki/api.php?action=login&format=json',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8' //Set the coding, otherwise the server can't read you're request
        }
        //withCredentials: true,
        /*
         If you set Credentials your server gets rather picky oc CORS, more specifically Header always set Access-Control-Allow-Origin: needs to be set to exact address.
         */
        //data: "lgname=APIread&lgpassword=apiread01"
    }
    CORSconnectFactory.initSettings = function(url, withCredentials) {
        urlInit = url;
        datareq.withCredentials= withCredentials;

    }
    CORSconnectFactory.login = function(id, password){
        datareq.url = urlInit + "?action=login&format=json";
        datareq.data= "lgname=" + id +  "&lgpassword=" + password;
        return $http(datareq)//You don't have to return this request, but it helps as it lets you use .login's promise in your code
            .success(function(data) {
                var results = data.login; //You might have to work around to find the right part of the structure
                if ( results.result === "NoName"){
                    console.log("New request for Token")
                } else if ( results.result === "NeedToken" ) {
                    console.log("Need a token this time") //Mediawiki API requires login then login with token to accept the connection.
                    CORScredentials = data.login
                    return results.result;
                }
            });
    }
    CORSconnectFactory.tokenReq = function(){
        datareq.data = datareq.data = datareq.data + "&lgtoken=" + CORScredentials.token;
        return $http(datareq)
            .success(function (data) {
                results= data.login;
                CORScredentials=data.login;
                console.log("And I am now " + results.result);
            })

    }
    CORSconnectFactory.query = function(queryString) {
        datareq.url = urlInit + "?action=ask&query="+ queryString + "&format=json";
        datareq.data = ""; //Don't send data, it confuses the poor query (and your login details is in the token
        return $http(datareq)
            .success(function(data) {
                var results = data.query.results;
                return results;
            });
    }
    return CORSconnectFactory;
});

答案 1 :(得分:0)

在许多层面上出现了错误:

  • 首先,在任何甚至远程公开的服务上启用CORS都是非常不安全的。
  • 第二,您需要为CORS实际有用的任何内容设置Access-Control-Allow-Credentials标头(如果它是公共API,只需使用JSONP)。正确配置后,MediaWiki会为您执行此操作。
  • 第三,$wgCrossSiteAJAXdomains将域名作为其参数,而不是URL前缀,因此应为$wgCrossSiteAJAXdomains = array( '127.0.0.1:30004' );
  • 第四,您need to set示例中的origin参数,即。正确的网址为'http://v-ghost.port0.org:8081/apiwiki/api.php?action=ask&query=[[Msgtype::1]]|%3FMenuName&format=json&origin=http://127.0.0.1:30004