前后端分离下的跨域问题以及CSRF攻击


  前段时间新工程刚开始搞前后端分离,于是使用了一直被传的神乎其神的vue,在使用一段时间后,发现自己再也回不去以前用jquery操作dom的时代了。这个东西确实牛逼,大大简化了开发的工作量,将dom呈现从逻辑剥离出去,使开发人员更专注于注业务实现。但是前后端分离页因此带来了一系列问题,比如典型的跨域问题。于是趁着研究跨域解决方案的机会,我顺带着把session和token之间一直模糊的点也了解了个通透。

一、跨域(源)

  首先我们先来了解一下什么是跨域,当网站不支持跨域时会报如下错误。

  如下图所示,当我们打开一个网页时可以看到在请求头中有个origin字段,这个字段的值就代表着当前窗口所在的域,也叫做源,从字面意思我们就可以理解这个页面的来源。

  而返回头中有个access-control-allow-origin字段表示:你请求的服务端,能接受哪些域过来的请求,该值可以包含多个域,若该值为“*”表示接受任何域。

例如你打开了一个A站的页面,A站页面发送了一个对B站服务端的请求,这个请求头就会在origin字段中带上A站的域名,B站接收请求后将origin与自身后台设置的access-control-allow-origin字段对比,发现没有A站的域,那么根据浏览器同源策略,这个请求将会被拦截(请求还分为简单请求和非简单请求,原理一样,这里就不赘述了),并将返回头消息返回给浏览器。而前后端分离最直接的问题就是两端的域不一样,最简单粗暴的解决办法就是在后端过滤器中设置access-control-allow-origin字段的值,便可解决跨域问题。

二、Session

  基于session的校验方式,流程其实很简单,用户第一次登陆网站的时候,在服务端创立对应的session对象,该session对象通过sessionid来做唯一识别,并将该id返回给浏览器,浏览器拿到id后将其保存在cookies中。之后用户再次访问此域的页面时,浏览器可以随时从cookie中取sessionid,而不需要做额外的校验,只要在发送请求时再次提供id,服务器便能根据id在内存中找到对应用户的身份信息。

  但是session有两个弊端,第一个就是当用户数量越来越多,内存中保存的用户信息也越来越大,十分占据内存;第二个是若该域支持第三方网站发送请求,也就是支持任何其他网站发送跨域请求时,会产生csrf漏洞。

  所谓csrf漏洞其实很好理解,例如有一个支持跨域的银行网站,该网站有一个转账链接:http://xxxx.com?account=alice&count=1000&reciver=jack,当支持跨域时,这个链接可以嵌在任何页面,而且不会因为跨域问题被拦截。此时我们的主人公alice登陆了银行网站,此时session创建成功,并且将sessionid保存在cookies中,但这时候不小心打开了一个恶意网站,这个网站中嵌入了上述的转账链接并且触发了链接,然后浏览器会自动将携带cookie中的信息发送到后台做身份校验,后台校验通过,于是alice的1000块就这样转给jack。

三、Token

  于是我们在想,既然使用cookie中的sesssionID,有风险,那我们能不能不用cookie?于是token就产生了(当然token只是解决csrf攻击的手段之一)。在了解token之前,我们需要先简单了解一下加密算法,一般最常用的加密算法为sha256。该算法有一个密码,我们称之为密钥,用户信息+密钥在经过该算法计算后,会得出token。该算法原理其实和我们以前学过的微分方程有点像,每组三个解,其中有一个是公共解(通解),这个公共解就是密钥(所以sha256也是可以根据多组解计算之后破译的,因此我们需要经常更换密钥)。另外两个解,一个是用户的身份信息,另一个就是token了,后面再次请求后台时都需要带上这两个东西。即便用户在客户端擅自修改了自己的身份信息也不怕,因为修改后的身份信息传送给后台后,后台会再次用sha256计算一次,修改后的用户信息+密钥算出的token与原token不一致,请求不通过。

  token在服务端通过上述算法生成之后,连同其中的用户信息一起发送给浏览器,然后由浏览器将其保存在窗口内存中,每次点击转账链接时只需将token和自己的信息也一起发送给服务端(http://xxxx.com?account=alice&count=1000&reciver=jack&token=123456)这样即使恶意网站内嵌了转账链接触发了也不怕,因为恶意网站无法跨窗口拿到自己的token和用户信息(而之前使用session时,转账链接会自动将cookie中的sessionid发送给后台完成身份校验)。

参考资料:http://www.ruanyifeng.com/blog/2016/04/cors.html

参考资料:https://www.cnblogs.com/wxinyu/p/9154178.html

参考资料:https://www.jianshu.com/p/1ad4358beff7