React:快速上手(8)——前后端分离的跨域访问与会话保持

React:快速上手(8)——前后端分离的跨域访问与会话保持

跨域访问

  跨域是指从一个域名的网页去请求另一个域名的资源。比如从http://www.baidu.com/ 页面去请求 的资源。跨域的严格一点的定义是:只要 协议,域名,端口有任何一个的不同,就被当作是跨域。 

  如下,域名相同的情况下,3000端口的应用无法直接访问8080端口的服务。

  

跨域资源共享CORS

  它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。CORS需要浏览器与服务器的双向支持。整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信

  在简单的跨域Ajax请求中,会在头部信息中添加Origin参数用于表面这个请求来自哪里,如下

  

  如果Origin指定的源,不在许可范围内,服务器会返回一个正常的HTTP回应。浏览器发现,这个回应的头信息没有包含Access-Control-Allow-Origin字段(详见下文),就知道出错了,从而抛出一个错误,被XMLHttpRequestonerror回调函数捕获。注意,这种错误无法通过状态码识别,因为HTTP回应的状态码有可能是200。

  如果Origin指定的域名在许可范围内,服务器返回的响应,会多出几个头信息字段,如下:

  

  其中,几个重要的头信息如下:

  • Access-Control-Allow-Origin:该字段是必须的。它的值要么是请求时Origin字段的值,要么是一个*,表示接受任意域名的请求。
  • Access-Control-Allow-Credentials:该字段可选。它的值是一个布尔值,表示是否允许发送Cookie。默认情况下,Cookie不包括在CORS请求之中。设为true,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器。这个值也只能设为true,如果服务器不要浏览器发送Cookie,删除该字段即可。

服务器端的处理

  如上所述,CORS请求的关键是在后端,即将Origin添加到服务器的许可范围内。在SpringBoot应用中,我们可以编写一个拦截器,来实现:

@Component
public class CorsInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception {
        response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
        response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, If-Modified-Since");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.addHeader("Access-Control-Allow-Credentials", "true");
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {

    }
}

  这里直接允许了所有源,在实际开发中,必须指定可信范围的源。

客户端处理

  对于使用creat-react-app构建的项目,可以直接在package.json下配置,具体如下  

{
  "name": "recommender",
  "version": "0.1.0",
  "private": true,
  "proxy": "http://代理地址",
  "dependencies": {
    "antd": "^3.23.3",
   ...  
  },
}

 

 

会话保持

  CORS请求默认不发送Cookie和HTTP认证信息。如果要把Cookie发到服务器,一方面要服务器同意,指定Access-Control-Allow-Credentials为true。另一方面,开发者必须在AJAX请求中打开withCredentials属性

  在Axios中,可以简单设置如下:

import axios from 'axios'
//方法1
axios.defaults.withCredentials =true;

//方法2
let config = {headers: {'Content-Type': 'multipart-/form-data'},withCredentials: true};

axios.post("http://127.0.0.1:8080/get.do", null, config).then((response) => {alert(response.data)})
   

  服务端的处理,我们已经在上述代码中实现了,即

response.addHeader("Access-Control-Allow-Credentials", "true");

  至此,前后端分离项目即可完成跨域访问与会话保持!

 

参考链接

posted @ 2019-07-17 17:19  子烁爱学习  阅读(1788)  评论(0编辑  收藏  举报