跨域问题的描述和解决(JAVA)上

it2022-05-05  238

一、什么是跨域

在解决跨域问题之前,我们要搞清楚什么是跨域。 具体的解释是一个请求url的协议、域名、端口三者之间任意一个与当前页面 url 不同即为跨域。通俗的说就是你在某个 url 下发起对另外一个 url 的请求,这两个 url 必须是协议、域名、端口都相同才不算跨域。 举个例子:

当前 url请求 url是否跨域原因http://www.a.com/http://www.a.com/index.html否协议(http)、域名(www.a.com)、端口(80)都相同。http://www.a.com/https://www.a.com/是协议不同(http、https)http://www.a.com/http://www.b.com/是域名不同(www.a.com、www.b.com)http://www.a.com/http://www.a.com:8080/是端口不同(80、8080)

那么是什么原因导致跨域问题的出现呢? 跨域起因于浏览器的同源策略 。 同源策略是浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源。

同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。

根据官方的说法来看这似乎是一个安全策略,那么它主要是想要解决什么样的问题呢?

二、同源策略是为了防止什么

据我所知,浏览器的同源策略主要为了防止两类问题。一个对接口的访问,一个是对 Dom 的访问。 先说对接口的访问,众所周知,Cookie 一般用来处理用户登录的场景,如果你请求了接口进行登录,服务端验证通过后会在响应头加入 Set-Cookie 字段,然后下次再发请求的时候,浏览器会自动将 cookie 附加在请求头的 Cookie 中,服务端就能知道这个用户已经登录过了。

那么是不是有这个可能,当用户浏览我们设置钓鱼网站时,我们拿到用户先前登录的网站 cookie,由于没有同源策略,我们就可以拿着这个 cookie 去登录之前用户登陆过的网站了。 这就是 CSRF 攻击。详细的解释大家可以看这篇文章:浅谈CSRF攻击方式。

至于对 Dom 节点的访问,举个例子:我写了一个钓鱼网站,由于没有同源策略,我直接在页面里镶嵌了银行的登录的 Dom 节点,这样用户可以直接在这个网站登录银行,而且的确是能登录成功的。而我只需要做一点监听事件就可以轻易的获取用户的信息。

从上面我们可以看出,同源策略还是可以帮助我们规避一些风险的。尽管看不来不是那么强力,但是还是能提高一些攻击成本的。

三、跨域问题的解决

相信很多人对于上面的叙述其实不感兴趣,只是想知道如何去解决这个问题。 我们先需要声明一个基本的概念,跨域问题在服务器端解决是比在客户端解决要简单的。 所以博主在这里优先推荐服务器端进行解决。 百度上有很多各种情况下解决跨域问题的办法,博主这里只展示一种,毕竟一法通,万法通嘛。 博主要展示的场景是前端采用 ajax 携带 cookie 对后端 java 接口进行访问。 服务器端可以新建一个过滤器用来处理每一个请求,代码如下(只展示 doFilter 代码):

@Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; //设置允许跨域访问 response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin")); response.setHeader("Access-Control-Allow-Methods", "*"); response.setHeader("Access-Control-Max-Age", "3600"); response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Authorization," + " Content-Type, Accept, Connection, User-Agent, Cookie,token"); response.setHeader("Access-Control-Allow-Credentials", "true"); chain.doFilter(request, response); }

客户端的话,在使用 ajax 对接口进行请求的情况下,只需要在 ajax 中添加一句

xhrFields: { withCredentials: true }

这样跨域问题在使用 ajax 请求 java 后台接口的这种模式下就完美的解决了。 具体的代码原理的话,博主会在 跨域问题的描述和解决(JAVA)下中详细解释。


最新回复(0)