同源与跨域
跨域问题伴随着前后端分离而产生。不想jsp,asp,ejr等嵌入html语言,直接在混入html中就可以操作数据库从而获取数据,前后端分离开发的模式,前后端的通讯是基于Ajax技术,这是也是Javascript最重要的技术之一。
为了维护浏览器的安全,指定了同源策略也就是域名、协议、端口均相同的才能进行访问,当页面在执行一个脚本时会检查访问的资源是否同源,如果非同源,那么在请求数据时,就会被浏览器拦截。
但是在前后端分离开发中可能使用的软件都不一样,就可能造成三个中的不一致。(最常见就是端口)
http://localhost:8080/index.html
http://locahost/user //(默认80)
//端口不同
http://abc.com
http://abd.com/post/
//域名不同
http://abc.com
https://abc.com
//协议不同
跨域就是,请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域。实现跨域访问的技术很多,如JSONP、flash、iframe,跨域资源共享(Cors) ,nginx代理跨域,nodejs中间件代理跨域,WebSocket协议跨域等。
Cors解决跨域问题的原理
CORS定义一种跨域访问的机制,可以让AJAX实现跨域访问。CORS 允许一个域上的网络应用向另一个域提交跨域 AJAX 请求。
如图就是跨域导致请求不成功:
可以看到请求的网址端口收80,响应端口收8080(Origin)
-
http请求头
Origin: 普通的HTTP请求也会带有,在CORS中专门作为Origin信息供后端比对,表明来源域。
Access-Control-Request-Method: 接下来请求的方法,例如PUT, DELETE等等
Access-Control-Request-Headers: 自定义的头部,所有用setRequestHeader方法设置的头部都将会以逗号隔开的形式包含在这个头中。 -
请求头中Access-Control-Request-Method表示请求的方法,例如PUT, DELETE等等
**Access-Control-Request-Headers:**自定义的头部,所有用setRequestHeader方法设置的头部都将会以逗号隔开的形式包含在这个头中。 -
http响应头
响应也是通过http协议封装的,其中origin字段表明跨域请求的来源。然后服务器处理完请求之后,会再返回结果中加上如下控制字段。 -
Access-Control-Allow-Origin: 允许跨域访问的域,可以是一个域的列表,也可以是通配符”*”。这里要注意Origin规则只对域名有效,并不会对子目录有效。即http://foo.example/subdir/ 是无效的。但是不同子域名需要分开设置,这里的规则可以参照同源策略
Access-Control-Allow-Credentials: 是否允许请求带有验证信息,
Access-Control-Expose-Headers: 允许脚本访问的响应头
Access-Control-Max-Age: 缓存此次请求的秒数。在这个时间范围内,所有同类型的请求都将不再发送预检请求而是直接使用此次返回的头作为判断依据,非常有用,大幅优化请求次数
Access-Control-Allow-Methods: 允许使用的请求方法,以逗号隔开
Access-Control-Allow-Headers: 允许自定义的头部,以逗号隔开,大小写不敏感
JavaWeb解决跨域问题
根据cors原理,只需要在Origin中添加上允许访问的域名即可。
- 编写Filter修改Origin:
import javax.servlet.*;
import javax.servlet.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
//自定义
@WebFilter("/*") //这里是注解,习惯web.xml配置的见下
public class allFilter implements Filter {
public void init(FilterConfig config) throws ServletException {
}
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
HttpServletResponse res = (HttpServletResponse)response;
res.setHeader("Access-Control-Allow-Origin", "http://localhost:8080");
res.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
res.setHeader("Access-Control-Max-Age", "3600");
res.setHeader("Access-Control-Allow-Headers", "x-requested-with");
chain.doFilter(request, response); //注意最后一定要放行
}
}
核心:添加上允许访问的域名
```js
res.setHeader("Access-Control-Allow-Origin", "http://localhost:8080");
webxml配置
```java
<filter>
<filter-name>CORSFilter</filter-name> //过滤器名称
<filter-class>com.grain.filter.CORSFilter</filter-class> //过滤器所在项目路径
</filter>
<filter-mapping>
<filter-name>CORSFilter</filter-name>
<url-pattern>/*</url-pattern> //允许那些域名访问 /* 表示所有
</filter-mapping>
- web.xml配置文件解决跨域
下载cors-filter-1.7.jar和java-property-utils-1.9.jar工具包然后在web.xml配置Filter文件,如下:
<filter>
<filter-name>CORS</filter-name>
<filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
<init-param>
<param-name>cors.allowOrigin</param-name>
<param-value>*</param-value>
</init-param>
<init-param>
<param-name>cors.supportedMethods</param-name>
<param-value>GET,POST,HEAD,PUT,DELETE</param-value>
</init-param>
<init-param>
<param-name>cors.supportedHeaders</param-name>
<param-value>Accept,Origin,X-Requested-With,Content-Type,Last-Modified</param-value>
</init-param>
<init-param>
<param-name>cors.exposedHeaders</param-name>
<param-value>Set-Cookie</param-value>
</init-param>
<init-param>
<param-name>cors.supportsCredentials</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CORS</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
都是修改Origin允许跨域访问。
如果学习了Spring框架还会有更高级的方法,所以一起加油把!
Cors官网
其他的跨域问题@Demi讲的很全谢谢作者!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/156320.html