文章目录
AJAX跨域问题
为什么会发生AJAX跨域
浏览器限制
浏览器禁止检查跨域
- 命令行参数启动:chorme --disable-web-security
跨域
JSONP解决跨域
- 前后台都需要改动
$.ajax({
url:baseUrl,
dataType:"jsonp",
jsonp:"callback",
success:function(json){
result=json;
}
});
- jsonp发出的请求Type为script请求,返回类型是application/javascript
- jsonp中的url加了callback参数,后台检测如果有callback参数(参数可约定,一致就行)就是jsonp请求,所以返回类型不是application/json,而是application/javascript。
- 动态创建js脚本在jquery.js的9800行可以看到
弊端
- 服务器需要改动代码支持
- 只支持GET,因为是动态创建script方法来进行请求的,script只能用get方法
- 发送的不是XHR请求
- 不建议使用
被调用方解决跨域
服务器端实现
- 请求是先执行后判断
- 如果请求是跨域的,会在请求头中加入Origin的url,然后检查响应头中有没有跨域的信息
SpringBoot下的代码
package com.dk.wechat.common.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
/**
* Created by cyj
* on 2018/7/19.
*/
@Configuration
public class CorsConfig {
@Bean
public CorsFilter corsFilter() {
final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
final CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.setAllowCredentials(true);
corsConfiguration.addAllowedOrigin("*");
corsConfiguration.addAllowedHeader("*");
corsConfiguration.addAllowedMethod("*");
urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
return new CorsFilter(urlBasedCorsConfigurationSource);
}
}
简单请求与非简单请求
非简单请求发送前会预先发送OPTION方法的预检命令,通过了之后才会发送非简单请求
-
简单请求
- 方法为:GET,POST,HEAD
- 请求头中无自定义的头
- Content-Type为
- text/plain
- multipart/form-data
- application/x-www-form-urlencoded
-
非简单请求
- 方法为:put,delete
- 带自定义头的ajax请求
- 发送json格式的ajax请求
带Cookie的跨域
Access-Control-Allow-Origin:* 不能满足带cookie的跨域请求,必须指定域名,可以动态配置
Access-Control-Allow-Credentials:true
String origin=request.getHeader("Origin");
if(StringUtil.isEmpty(origin)){
res.addHeader("Access-Control-Allow-Origin",origin)
}
前端代码:
$.ajax({
url:baseUrl,
type:"get",
xhrFields:{
withCredentials:true //发送cookie请求
}
success:function(json){
result=json;
}
});
带自定义头的跨域
同样Access-Control-Allow-Header同样不能是*,可以参考上面的动态配置
前端代码:
$.ajax({
url:baseUrl,
type:"get",
headers:{
"x-header1":"X"
}
beforeSend:function(xhr){
xhr.setRequestHeader("x-header2","XX")
}
success:function(json){
result=json;
}
});
Nginx配置
server {
listen 80; #对外提供的端口
server_name localhost;
location / {
proxy_pass http://localhost:8080;
add_header Access-Control-Allow-Methods *;
add_header Access-Control-Max-Age 3600;
add_header Access-Control-Allow-Credrntials true;
add_header Access-Control-Allow-Origin $http_origin;
add_header Access-Control-Allow-Headers $http_access_control_request_headers;
}
......
}
Apache服务器配置(Apache24)
httpd-vhosts.conf:
<VirtualHost *:80>
ServerName localhost
ErrorLog "logs/localhost-error.log"
CustomLog "logs/localhost-access.log" common
ProxyPass / b.com
Header always set add_header Access-Control-Allow-Methods "*";
Header always set Access-Control-Max-Age "3600";
Header always set Access-Control-Allow-Credrntials "true";
</VirtualHost>
Spring框架解决
- 类,方法上加@CrossOrigin
调用方解决跨域
隐藏跨域
- 反向代理:访问同一个域名下的2个不同URL,会去两个不同的服务器
Nginx配置
server {
listen 80; #对外提供的端口
server_name a.com;
location / {
proxy_pass http://localhost:8081;
}
location /ajax {
proxy_pass http://localhost:8080;
}
....
}
Apache配置
<VirtualHost *:80>
ServerName a.com
ErrorLog "logs/a.com-error.log"
CustomLog "logs/a.com-access.log" common
ProxyPass / b.com
ProxyPass /ajax a.com
Header always set add_header Access-Control-Allow-Methods "*";
Header always set Access-Control-Max-Age "3600";
Header always set Access-Control-Allow-Credrntials "true";
</VirtualHost>
参考资料
慕课网上的免费课程,做了笔记,分享一下
ajax跨域完全讲解