用国外网站 图片做自媒体,北京计算机编程培训学校,苏州高端网站制作公司,用织梦做网站还要不要服务器为什么会出现跨域问题
存在浏览器同源策略#xff0c;所以才会有跨域问题。那么浏览器是出于何种原因会有跨域的限制呢。其实不难想到#xff0c;跨域限制主要的目的就是为了用户的上网安全。
同源策略导致的跨域是浏览器单方面拒绝响应数据#xff0c;服务器端是处理完毕…为什么会出现跨域问题
存在浏览器同源策略所以才会有跨域问题。那么浏览器是出于何种原因会有跨域的限制呢。其实不难想到跨域限制主要的目的就是为了用户的上网安全。
同源策略导致的跨域是浏览器单方面拒绝响应数据服务器端是处理完毕并做出了响应的。
什么是同源策略
一个url由三部分组成:协议域名ip地址端口。
只有当协议域名端口都一致的时候才被称为同源。
而同源策略规定只有发送请求的那一边和接受请求的那一边处于同源的情况下浏览器才会接受响应。
常见的跨域场景 而当我们的请求不符合同源策略的时候。往往会出现以下错误 跨域的常见解决方案
jsonp
jq的ajax自带解决跨域的方法。底层原理采用的JSONP的跨域解决方案。如下
function callback(){console.log(这是打印日志)
}$.ajax({url: http://www.domain2.com:8080/login,type: get,dataType: jsonp, // 请求方式为jsonp 设置跨域的重点jsonpCallback: callBack, // 回调函数
});jsonp跨解实现流程 添加响应头解决
CORS简介
CORS是一个W3C标准全称是跨域资源共享”Cross-origin resource sharing。它允许浏览器向跨源(协议 域名 端口)服务器发出XMLHttpRequest请求从而克服了AJAX只能同源使用的限制。CORS需要浏览器和服务器同时支持。它的通信过程都是浏览器自动完成不需要用户参与。
对于开发者来说CORS通信与同源的AJAX/Fetch通信没有差别代码完全一样。浏览器一旦发现请求跨源就会自动添加一些附加的头信息有时还会多出一次附加的请求但用户不会有感觉。因此实现CORS通信的关键是服务器。只要服务器实现了CORS接口就可以跨源通信。 浏览器发出CORS简单请求只需要在头信息之中增加一个Origin字段。 浏览器发出CORS非简单请求会在正式通信之前增加一次OPTIONS查询请求称为预检请求preflight。浏览器先询问服务器当前网页所在的域名是否在服务器的许可名单之中以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复浏览器才会发出正式的XMLHttpRequest请求否则就报错。 简单请求就是HEAD、GET、POST请求并且HTTP的头信息不超出以下几种字段 Accept、Accept-Language、Content-Language、Last-Event-ID、Content-Type 注Content-Type只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
反之就是非简单请求。
其实实现CORS很简单就是在服务端加一些响应头并且这样做对前端来说是无感知的很方便。
详解响应头
Access-Control-Allow-Origin 该字段必填。它的值要么是请求时Origin字段的具体值要么是一个*表示接受任意域名的请求。Access-Control-Allow-Methods 该字段必填。它的值是逗号分隔的一个具体的字符串或者*表明服务器支持的所有跨域请求的方法。注意返回的是所有支持的方法而不单是浏览器请求的那个方法。这是为了避免多次预检请求。Access-Control-Expose-Headers 该字段可选。CORS请求时XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段就必须在Access-Control-Expose-Headers里面指定。Access-Control-Allow-Credentials 该字段可选。它的值是一个布尔值表示是否允许发送Cookie.默认情况下不发生Cookie即false。对服务器有特殊要求的请求比如请求方法是PUT或DELETE或者Content-Type字段的类型是application/json这个值只能设为true。如果服务器不要浏览器发送Cookie删除该字段即可。Access-Control-Max-Age 该字段可选用来指定本次预检请求的有效期单位为秒。在有效期间不用发出另一条预检请求。
顺便提一下如果在开发中发现每次发起请求都是两条一次OPTIONS一次正常请求注意是每次那么就需要配置Access-Control-Max-Age避免每次都发出预检请求。
Access-Control-Allow-Origin响应头的意思是安全同行的请求。
举个例子 http://192.168.0.103:8080 向http://192.168.0.102:8080 发送了请求结果因为域名不一样在返回信息的时候因为IP地址不一致被拦截。
但是如果http://192.168.0.102:8080 在响应头中的 Access-Control-Allow-Origin 字段中携带上属性值http://192.168.0.103:8080 如下
//响应头
Access-Control-Allow-Origin:http://192.168.0.103:8080
这就等于告诉浏览器http://192.168.0.102:8080 这个地址是安全的请不要拦截。
这样http://192.168.0.103:8080 就可以接受来自 http://192.168.0.102:8080 返回的信息。
当然我们也可以进行所有域名均不拦截的设置如下
//响应头
// * 代表所有域名均不拦截
Access-Control-Allow-Origin:*
过滤器解决跨域
import org.springframework.context.annotation.Configuration;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
WebFilter(filterName CorsFilter )
Configuration
public class CorsFilter implements Filter {Overridepublic void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {HttpServletResponse response (HttpServletResponse) res;response.setHeader(Access-Control-Allow-Origin,*);response.setHeader(Access-Control-Allow-Credentials, true);response.setHeader(Access-Control-Allow-Methods, POST, GET, PATCH, DELETE, PUT);response.setHeader(Access-Control-Max-Age, 3600);response.setHeader(Access-Control-Allow-Headers, Origin, X-Requested-With, Content-Type, Accept);chain.doFilter(req, res);}
}使用CrossOrigin注解
public class GoodsController {
CrossOrigin(origins http://localhost:4000)
GetMapping(goods-url)
public Response queryGoodsWithGoodsUrl(RequestParam String goodsUrl) throws Exception {}
} Nginx代理跨域
location / { add_header Access-Control-Allow-Origin *;add_header Access-Control-Allow-Methods GET, POST, OPTIONS;add_header Access-Control-Allow-Headers DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization;if ($request_method OPTIONS) {return 204;}proxy_pass http://192.168.12.12:8081;
}
给OPTIONS 添加 204的返回原因是为了处理在发送POST请求时Nginx依然拒绝访问的错误,发送预检请求时需要用到方法 OPTIONS ,所以服务器需要允许该方法。
预检请求preflight request
跨域资源共享(CORS)标准新增了一组 HTTP 首部字段允许服务器声明哪些源站有权限访问哪些资源。另外规范要求对那些可能对服务器数据产生副作用的HTTP 请求方法特别是 GET 以外的 HTTP 请求或者搭配某些 MIME 类型的 POST 请求浏览器必须首先使用 OPTIONS 方法发起一个预检请求preflight request从而获知服务端是否允许该跨域请求。服务器确认允许之后才发起实际的 HTTP 请求。在预检请求的返回中服务器端也可以通知客户端是否需要携带身份凭证包括 Cookies 和 HTTP 认证相关数据。
其实Content-Type字段的类型为application/json的请求就是上面所说的搭配某些 MIME 类型的 POST 请求,CORS规定Content-Type不属于以下MIME类型的都属于预检请求。
网关解决跨域
Configuration
public class GlobalCorsConfig {Beanpublic CorsWebFilter corsWebFilter() {CorsConfiguration config new CorsConfiguration();// 这里仅为了说明问题配置为放行所有域名生产环境请对此进行修改config.addAllowedOrigin(*);// 放行的请求头config.addAllowedHeader(*);// 放行的请求方式主要有GET, POST, PUT, DELETE, OPTIONSconfig.addAllowedMethod(*); // 暴露头部信息config.addExposedHeader(*); // 是否发送cookieconfig.setAllowCredentials(true); UrlBasedCorsConfigurationSource source new UrlBasedCorsConfigurationSource();source.registerCorsConfiguration(/**, config);return new CorsWebFilter(source);}
}
总结
跨域全称为Cross-Origin Resource Sharing意为跨域资源共享是一种允许当前域domain的资源被其他域domain的脚本请求访问的机制通常由于同源安全策略浏览器会禁止这种跨域请求。 本文由博客一文多发平台 OpenWrite 发布