同源策略/SOP(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSFR等攻击。
SOP要求两个通讯地址的:
必须相同,否则两个地址的通讯将被浏览器视为不安全的,并被block下来
正常将web项目放置到服务端项目的静态文件所在目录即可
缺陷:
同域安全策略CORS(Cross-Origin Resource Sharing)
它要求请求的服务器在响应的报头(Response Header)添加 Access-Control-Allow-Origin标签,从而允许此标签所对应域访问此服务器的资源,调用此服务器的接口。
缺陷:
Access-Control-Allow-Credentials: true
如果发送的是带凭据的请求,但服务器的相应中没有包含这个头部,那么浏览器就不会把相应交给JavaScript,请求就无法得到结果的数据(浏览器得到了,但是我们请求的方法得不到,因为被浏览器拦截了),因此在需要传Cookie等时,服务端的Access-Control-Allow-Origin必须配置具体的具体的域名。并且还需要设置其他的请求头:
Access-Control-Allow-Origin; //request.getHeader("Origin")||www.xxx.com
Access-Control-Allow-Methods; //POST, GET, OPTIONS, DELETE
Access-Control-Allow-Credentials;//是否支持cookie跨域
Access-Control-Allow-Headers;//x-requested-with,content-type
Java可以参照:
public void CORSMethod(ServletRequest request, ServletResponse response) throws IOException,ServletException {
HttpServletResponse res = (HttpServletResponse) response;
res.setContentType("text/html;charset=UTF-8");
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
res.setHeader("Access-Control-Max-Age", "0");
res.setHeader("Access-Control-Allow-Headers", "Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With,userId,token");
res.setHeader("Access-Control-Allow-Credentials", "true");
res.setHeader("XDomainRequestAllowed","1");
}
javaScript可以参考:
$.ajax({
url: 'http://b.fdipzone.com/server.php', // 跨域
xhrFields:{withCredentials: true}, // 发送凭据
dataType: 'json',
type: 'post',
data: {'name':'fdipzone'},
success:function(ret){
if(ret['success']==true){
alert('cookie:' + ret['cookie'])
}
}
});
然后JavaScript请求的时候加上此标志:withCredentials: true。
angular可以百度:“withCredentials angularJS”
angular可以参考:
<script>
var app = angular.module("app", []);
app.controller("ctrl", function ($scope, $http) {
$scope.jsonpAction = function () {
$http.jsonp('http://localhost/Cross_Access/JsonP.php?callback=JSON_CALLBACK')
.success(function (data) {
console.log(data + '---');
});
};
});
script>
php可以参考:
/**
* Created by PhpStorm.
* User: Shadow
* Date: 2017/3/2
* Time: 09:21
*/
//服务端返回JSON数据
$arr = array('a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5);
$result = json_encode($arr);
//动态执行回调函数
$callback = $_GET['callback'];
echo $callback . "($result)";
工作方式介绍:
<script type="text/javascript" src="http://localhost/Cross_Access/JsonP.php?callback= angular.callbacks._1" async="">script>
其中 JSON_CALLBACK
被Angular自动替换为了angular.callbacks._x
_x
为Angular定义的请求序列,angular会自动生成一个_x的同名方法存放到angular.callbacks
中去
当标签生效http://localhost/Cross_Access/JsonP.php
被下载回来时,会被当成javascript直接执行,因为我们的php端设置了返回的内容是 callback与实际数据拼接起来的一个方法,故下载的内容实际是angular.callbacks._1(xxxxxx)
其会被直接执行,故若在_1(data)
方法中直接将参数通过jsonp.success(function(data){})
回调,那么便能直接取到相应的值
移除当前网页中插入的script标签,并移除angular.callbacks中的_1(data)方法,一个完整的jsonp请求便已成功
前面几种方式或多或少都需要服务端人员配合,代理服务器方式可以完全不需要服务端人员配合
安装方式请百度,并确认浏览器能正常访问到 本地nginx首页:http://localhost 或 http://localhost:8080(不同的系统可能nginx的默认端口号不同)
第二步: 配置nginx环境
打开nginx对应的目录,找到nginx.conf文件,以mac为例:
cd /usr/local/etc/nginx
cat nginx.conf
对于我们只需关注其中server的配置项,现将server中的注释项目全部删掉(不用担心,因为此文件还有一个nginx.conf.default的文件为默认配置的备份)
vim nginx.conf
server {
listen 8080;#监听端口号对应localhost:8080
#listen 80;#默认端口号对应localhost:80即localhost,80端口号可以省略不写
server_name localhost;#服务名称
location / { #匹配 ‘/’时对应的配置
root html; # 根目录对应为 相对目录 mac上为 /usr/local/opt/nginx/html
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
其中 location /中配置的root为我们的web页面需要放置的目录,在mac上默认为 /usr/local/opt/nginx/html
cd /usr/local/opt/nginx/html
进入此目录可以看到里面有个index.html的文件,就是本地nginx首页:http://localhost 或 http://localhost:8080所对应的原文件,我们改了其内容,然后在浏览器刷新后能看到变化。
可以将 root 后面的 html默认的相对位置改为我们自己的目录,比如:
location / {
root /Users/Shadow/Sites;
}
然后进入对应目录:
cd /Users/Shadow/Sites
touch index.html
echo Hello nginx > index.html
保存nginx.conf并重新加载nginx配置文件:
nginx -s reload
在此之前还可以使用
nginx -t
命令检查nginx.conf文件的有效性 刷新http://localhost页面,可以看到
到此为止,nginx的环境已经配置好了
步骤三 部署项目
以testNGINX 项目为例 在/Users/Shadow/Sites/目录下新建项目,新建文件 testNginx.html文件输入以下内容:
https://m.douban.com/rexxar/api/v2/community_center?for_mobile=true
<html lang="en" ng-app="app">
<head>
<meta charset="UTF-8">
<title>Titletitle>
<script src="angular.js">script>
head>
<body ng-controller="myCtrl">
<input type="button" value="开始请求" ng-click="action()">
body>
<script>
var url = "https://m.douban.com/rexxar/api/v2/community_center?for_mobile=true";
var app = angular.module("app", []).controller("myCtrl", function ($scope, $http) {
$scope.action = function () {
$http.get(url).success(function (data) {
console.log(data);
}).error(function (e) {
console.log(e);
});
}
})
script>
html>
在浏览器打开
http://localhost/testNGINX/testNGINX.html
并点击开始请求按钮,然后查看日志,发生跨域问题 No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘http://localhost’ is therefore not allowed access. 解决这个问题,需要修改nginx的配置文件:
cd /usr/local/etc/nginx
vim nginx.conf
在 server中添加如下内容:
location /douban/{
proxy_pass https://m.douban.com/;
proxy_cookie_path / /douban;
}
修改 testNGINX.html的请求地址为:
var url = “https://localhost/douban/rexxar/api/v2/community_center?for_mobile=true“;
重新加载nginx配置文件
nginx -s reload
浏览器刷新
http://localhost/testNGINX/testNGINX.html
点击开始请求,查看日志可以看见请求成功了。
上面 location的配置的意思如下:
nginx截获路径为https://localhost/douban/的请求,并将请求转发到 https://m.douban.com/替换为proxy_pass配置的域名。
完整的Server配置:
server {
listen 80;
server_name localhost;
location / {
root /Users/Shadow/Sites;
}
error_page 500 502 503 504 /50x.html;
#relative path
location = /50x.html {
root html;
}
#absolute path
location /douban/{
proxy_pass https://m.douban.com/;
proxy_cookie_path / /douban;
}
}
代理配置后完整的js请求方法
<html lang="en" ng-app="app">
<head>
<meta charset="UTF-8">
<title>Titletitle>
<script src="angular.js">script>
head>
<body ng-controller="myCtrl">
<input type="button" value="开始请求" ng-click="action()">
body>
<script>
var url = "http://localhost/douban/rexxar/api/v2/community_center?for_mobile=true";
var app = angular.module("app", []).controller("myCtrl", function ($scope, $http) {
$scope.action = function () {
$http.get(url).success(function (data) {
console.log(data);
}).error(function (e) {
console.log(e);
});
}
})
script>
html>
配置前后请求地址对比:
前
https://m.douban.com/rexxar/api/v2/community_center?for_mobile=true
后
http://localhost/douban/rexxar/api/v2/community_center?for_mobile=true
若配置不成功,可以优先检查如下几点: