跨域和cookie

本文以前端的视角来探讨浏览器的跨域和cookie问题。

一、跨域

跨域简介:

为什么会出现跨域?

  • 出于浏览器的同源策略限制,浏览器会拒绝跨域请求。

什么情况下出现跨域?

  • 不同源就会跨域。同源即:协议、域名、端口号都相同。任意一项不同就会跨域。
  • 例如 https://127.0.0.1:8000

为什么会有跨域需求?

  • 项目工程服务化后,不同职责的服务分散在不同的工程中,往往这些工程的域名是不同的,但一个需求可能需要对应到多个服务,这时便需要调用不同服务的接口,因此会出现跨域。

跨域只是浏览器的限制,服务器没有跨域问题。

跨域和cookie_第1张图片

跨域的解决方式:

跨域的解决最常见的三种方式:jsonp、CORS、反向代理

1、jsonp

实现原理:

  • 通过script标签的src属性可以访问跨域的资源,在这方面浏览器没有做限制。
    简略步骤:
  • 前端注册一个方法,通过script的src属性指向后端接口,并将该方法传参给后端
  • 后端将该方法名和处理后的数据以方法调用的方式拼接起来
  • 前端接受到响应后自动调用方法,在方法体内接收数据做处理。

示例代码:

  • js
<script type="text/javascript">
    function dosomething(data){
        //处理获得的数据
    }
</script>
<script src="http://example.com/data.php?callback=dosomething"></script>
  • php
$callback = $_GET['callback'];//得到回调函数名
$data = array('a','b','c');//要返回的数据
echo $callback.'('.json_encode($data).')';//输出

缺点:

  • 只支持get请求
  • 异常处理不方便

jsonp是jquery时代常用的跨域解决方式,现在几乎不用了。

2、CORS
  • CORS 即 跨域资源共享,CORS方式也叫白名单方式,是W3C 推荐的一种新的官方方案,能使服务器支持 ajax 的跨域请求。CORS 实现起来非常方便,只需要增加一些 HTTP 头,让服务器能声明允许的访问来源。
    实现方式:
  • 通过在服务端配置响应头 Access-Control-Allow-Origin 实现,值为允许跨域访问的域名白名单。
    跨域和cookie_第2张图片
3、反向代理
  • 通过在服务器配置请求代理来实现跨域,因为跨域是浏览器端的限制,而在服务器端没有这一限制。
    实现方式:
  • 前端请求使用的接口地址和浏览器页面地址同源,避免跨域
  • 服务端拦截接口请求,转发到真实的接口地址,拿到响应数据后再返回给前端。

代码示例:

server {
	# 监听端口80 即当访问服务器的端口是80时,进入这个server块处理
	listen 80;
	# location后面代表访问路径 当是/ 请求时 代理到实际的地址
    location / {
		# 使用 proxy_pass(固定写法)后面跟要代理服务器地址            
        proxy_pass http://xxx.xxx.xxx.xxx:8080;
    }
}    

二、cookie

客户端请求服务器时,如果服务器需要记录该用户状态,就使用response向客户端浏览器颁发一个Cookie。
而客户端浏览器会把Cookie保存起来。
当浏览器再请求服务器时,浏览器把请求的网址连同该Cookie一同提交给服务器。
服务器通过检查该Cookie来获取用户状态。

cookie属性:

  • name cookie的名字,Cookie一旦创建,名称便不可更改
  • value cookie值
  • comment 该Cookie的用处说明。浏览器显示Cookie信息的时候显示该说明
  • domain 可以访问该Cookie的域名。如果设置为“.alipay.com”,则所有以“baidu.com”结尾的子域名都可以访问该Cookie;第一个字符必须为“.”
  • maxAge Cookie失效的时间,单位秒。
    • 正数,则超过maxAge秒之后失效。
    • 负数,该Cookie为临时Cookie,关闭浏览器即失效,浏览器也不会以任何形式保存该Cookie。
    • 为0,表示删除该Cookie。
  • path 该Cookie的使用路径。例如:path设置时,其以“/”结尾.
    • path=/,说明本域名下contextPath都可以访问该Cookie。
    • path=/app/,则只有路径为“/app”的程序可以访问该Cookie
  • secure 该Cookie是否仅被使用安全协议传输。这里的安全协议包括HTTPS,SSL等。默认为false。
  • version 该Cookie使用的版本号。在servlet规范中默认是0;
    • 0 表示遵循Netscape的Cookie规范,目前大多数用的都是这种规范;
    • 1 表示遵循W3C的RFC2109规范;规范过于严格,实施起来很难。
  • isHttpOnly HttpOnly属性是用来限制非HTTP协议程序接口对客户端Cookie进行访问;也就是说如果想要在客户端取到httponly的Cookie的唯一方法就是使用AJAX,将取Cookie的操作放到服务端,接收客户端发送的ajax请求后将取值结果通过HTTP返回客户端。
  • sameSite 是为了防止csrf攻击而产生的属性
    上述的这些属性,除了name与value属性会被提交外,其他的属性对于客户端来说都是不可读的,也是不可被提交的。

内网统一登录:

实现方式:

  • 用户在内网登录后,后端在登录接口的响应头里配置set-cookie,将cookie字段写入浏览器里
  • 一般会将cookie的domain设置为二级域名,有多个二级域名就设多个cookie,子域名页面里的请求能携带父级域名的cookie
  • 后端获取前端请求里的cookie字段判断用户是否登录

三、跨域携带cookie

有些场景是需要跨域ajax请求时也要携带cookie,默认情况下是不会携带的。

满足条件:

很多人知道需要在 ajax 里配置 withCredentials 为 true,但光有这个不够,需要满足的条件如下:

  • withCredentials
    • ajax里配置 withCredentials 为 true
  • 响应头
    • 服务端需配置响应头字段:Access-Control-Allow-Origin,值为允许跨域的域名,不能为星号*
    • 还需要服务端配置另一响应头字段:Access-Control-Allow-Credentials,值为true
  • 跨站
    • 请求是否跨站,在非同一父域名下的就是跨站,跨站的情况需要cookie的属性满足以下条件:
      • cookie字段的 samesite 需要设置 none
      • 将samesite设为none时,有一个要求,就是cookie的 secure 属性需要设置为 true
      • 当secure设为true时,只允许https请求携带cookie,所以请求地址需要是 https 协议

你可能感兴趣的:(其他,前端,javascript,跨域,cookie,内网)