[Ionic] 用 PHP 解决 AngularJS 跨域请求和数据接收问题
以 Ionic 官方的 Sidemenu 例子为例,做如下修改即可:
1、解决 AngularJS 跨域 POST 问题:
修改 controller.js 文件,在:
1 | angular.module('starter.controllers', []) |
下边增加如下配置:
1 2 3 4 5 6 | .config(function ($httpProvider) { $httpProvider.defaults.withCredentials = true; $httpProvider.defaults.useXDomain = true; $httpProvider.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded;charset=utf-8"; // delete $httpProvider.defaults.headers.common['X-Requested-With']; }) |
增加这一配置的原因是PHP服务器端不能接收 AnjularJS 标准的 Content-Type: application/json 请求,因此我们这里改成和 jQuery 一样的 application/x-www-form-urlencoded 类型。
另外 withCredentials 是选项是否允许 Cookies 跨域,useXDomain 是否允许跨域请求。
2、HTML部分,这部分只是对 sidemenu 的 login.html 加了一些用于显示服务器端的调试信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | <ion-modal-view> <ion-header-bar> <h1 class="title">Login</h1> <div class="buttons"> <button class="button button-clear" ng-click="closeLogin()">Close</button> </div> </ion-header-bar> <ion-content> <!-- SHOW ERROR/SUCCESS MESSAGES --> <div id="messages" class="well" ng-show="message">{{ message }}</div> <!-- FORM --> <form ng-submit="doLogin()"> <div class="list"> <label class="item item-input"> <span class="input-label">Username</span> <input type="text" ng-model="loginData.username"> <span class="help-block" ng-show="errorName">{{ errorName }}</span> </label> <label class="item item-input"> <span class="input-label">Password</span> <input type="password" ng-model="loginData.password"> <span class="help-block" ng-show="errorPassword">{{ errorPassword }}</span> </label> <label class="item"> <button class="button button-block button-positive" type="submit">Log in</button> </label> </div> </form> </ion-content> </ion-modal-view> |
3、服务器端PHP文件,采用 CORS 跨域解决方案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | <?php header("Access-Control-Allow-Origin: ".$_SERVER['HTTP_ORIGIN']); header('Access-Control-Allow-Methods: "OPTIONS, GET, POST"'); header('Access-Control-Allow-Credentials: true'); header('Access-Control-Allow-Headers: "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"'); header('Access-Control-Max-Age: "3600"'); // $content_type_args = explode(';', $_SERVER['CONTENT_TYPE']); // if ($content_type_args[0] == 'application/json') // { // $postJson = file_get_contents('php://input'); // $_POST = json_decode($postJson, true); // } $postJson = file_get_contents('php://input'); $_POST = json_decode($postJson, true); $errors = array(); // array to hold validation errors $data = array(); // array to pass back data // validate the variables ====================================================== if (empty($_POST['username'])) $errors['username'] = 'Name is required.'; if (empty($_POST['password'])) $errors['password'] = 'Superhero alias is required.'; // return a response =========================================================== // response if there are errors if ( ! empty($errors)) { // if there are items in our errors array, return those errors $data['success'] = false; $data['errors'] = $errors; } else { // if there are no errors, return a message $data['success'] = true; $data['message'] = 'Login Success!'; } // return all our data to an AJAX call echo json_encode($data); ?> |
这一部分的关键是:
1)header("Access-Control-Allow-Origin: ".$_SERVER['HTTP_ORIGIN']);
这一行指定了服务器端允许跨域请求,并且使用来路域名作为允许的作用域;
2)header('Access-Control-Allow-Credentials: true');
服务器端允许 Cookies 跨域;
另外,由于 PHP 接收的数据是如下类型的:
1 | { username: 'aaa', password : 'bbb'} |
而实际上它可以接收的 $_POST 类型应该是:
1 | username=aaa&password=bbb |
因此我们这里采用
1 | $postJson = file_get_contents('php://input'); |
直接获取原始 input 数据,然后用:
1 | $_POST = json_decode($postJson, true); |
进行解析获得相应数据。
参考文献:
1)https://www.mxp.tw/2014/05/27/%E7%95%B6-angularjs-post%E6%96%B9%E6%B3%95%E7%A2%B0%E4%B8%8Aphp/
2)http://my.oschina.net/tommyfok/blog/287748
3)http://www.oschina.net/translate/submitting-ajax-forms-the-angularjs-way