摘要
用户用浏览器打开网站,DNS会根据域名找到相应的服务器IP给到浏览器,仅接着用户的浏览器会与服务器建立连接,通过网路上的各个设备(交换机、路由器、基站、光纤等),将服务器上的数据发送到用户的电脑上,在浏览器里呈现出来。在其通信链路上,只要任何一个设备被监听了,那么信息就有可能泄漏,信息若还不加密的话,那么监听信息的人就能直接看到用户的信息了,这就变成了用户信息泄漏。
为了杜绝这种情况,我们肯定要对信息加密,毕竟通信链路上的物理硬件等我们是没法控制的,只能提升信息的加密等级。当然,针对信息加密,国际安全组织也有解决办法:HTTPS,我们也不能只依赖HTTPS,自身也需要做好对信息的加密,比如对敏感数据进行加密,另外,避免网站被非法访问,可以进行登录认证。HTTPS就不讲了,只需申请证书再集成相应的组件即可,这里说下登录认证以及数据加密。
登录认证
假如我们不希望网站的信息直接展示在网上,只希望注册了的用户使用,我们可以加入登录认证模块,即只有输入了正确的账号密码的用户才能查看网站的信息,使用网站的功能。一般各模块属于同一系统的使用单点登录认证即可,若各模块功能属于不同系统则需要用到auto2或按对接方的要求对接认证了。
1、单点登录(SSO)
一般由用户模块或认证模块提供登录接口,该接口的参数基本是账号密码,返回值一般是token以及授权菜单或数据权限等信息。token对应的凭证由后端生成,token一般是UUID,有过期时间,保存在redis中,前端获取到token后缓存在浏览器中,发请求接口时带上这个token,一般是在请求头中。后端收到请求后,拦截验证token,若该token能在redis中找到,则验证通过继续处理返回数据,找不到则认证不通过,返回登录失败状态码让前端跳转登录页。
可以看到,单点登录认证成功的前提如下:
(1)使用统一拦截逻辑即验证的token要和登录的token对上。
(2)各模块连接的redis是同一个,保证能找到token。
安全性:依赖密码的强度、token的过期时间、密码错误的账户锁定时间。
2、Oauth2
一般的系统用SSO就足够了,毕竟用户信息和需要使用的数据全在一个系统。但随着互联网发展,各类系统和APP层出不穷,用户不希望每个系统或APP都建个账号,希望一个账号能授权登录各个系统,比如授权微信登录第三方云盘、第三方论坛、第三方游戏等。这个时候,单点登录就不够用了,毕竟微信不可能开放redis给别的公司,这样的话微信的数据库就暴露了,也不可能在第三方应用上输入微信的账号密码,让第三方应用调用微信的登录接口,这样的话微信的账号密码就暴露给第三方了。因此Oauth协议出世了,它规定了第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权。
目前Oauth1已被官方弃用,2012年就强烈建议使用Oauth2,Oauth2的官方网址:https://oauth.net/2/。可以看到Oauth2有4种认证模式:授权码模式(Authorization Code)、简化模式(Implicit)、账号密码模式(Resource Owner Password Credentials)、客户端模式(Client Credentials)。这4种模式,一般用到授权码模式,具体流程如下:
其中 资源拥有者就是用户、客户端是应用,授权服务器是第三方的授权服务模块,受保护资源是第三方的资源服务。
该方式主要原理就是第三方服务生成了用户的唯一标识以及授权码,不需要在应用里传第三方账号密码。比如二号店用微信扫码登录(网站集成微信登录官方文档:https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419316505&token=&lang=zh_CN):
(1)二号店是用微信开放平台链接传appid和redirect_uri等参数生成微信登录二维码。
(2)微信APP扫码识别出appid以及redirect_uri等信息,微信APP将当前登录人以及appid等信息发送给微信的鉴权服务器。
(3)微信鉴权服务器确认登录信息和应用信息无误后,将会把浏览器的微信开放平台链接重定向到二号店传的redirect_uri,并带上code等参数。
(4)二号店根据redirect_uri的页面或接口获取code参数,带上appid以及appsecret等参数,通过调用微信接口获取access_token。
(5)二号店通过access_token进行调用微信接口,获取用户基本数据资源或帮助用户实现基本操作。
在这个过程中,二号店和微信的视角分别如下:
对于二号店来说,用户信息不可见,无需提供登录页面,无论是微信登录二维码生成还是微信的登录认证对于二号店不可见,给到二号店的最终授权码access_token,二号店只能根据access_token查询微信里用户的信息。
对于微信(第三方)来说,需要提供 登录二维码和APP 或 公共登录页面,使客户能用APP扫码登录或通过公共登录页(不允许嵌套)登录,还需要提供注册应用的应用中心以及回调机制,便于后续认证code或会话标识返回给注册应用。还需提供根据会话标识相关的资源接口,便于注册应用调用。
安全性:依靠第三方应用与APP的安全性,与客户端应用没有太大关系。
数据加密
像一些重要数据,比如用登录的账号密码、金钱、订单等数据用https传输时,依旧有可能被拦截监听,甚至https可能被解密,若其中的数据不加密的话,那就泄漏用户数据了,因此,有必要对这些重要数据进行加密传输。
对于浏览器,若第一次加载的话,本地是一片空白,网站的所有数据都要下载,即,若有对称加密的密钥,也有可能会被监听到。因此,一般加密传输采用对称加密AES和非对称加密RSA组合的方式来传输信息,AES加密表单信息,RSA加密AES的密钥。
请求加密:对于表单有重要信息提交的,比如登录或注册等表单。建议做法如下:
(1)接口参数建议直接用前端随机生成的AES密钥加密。
(2)AES的密钥再经过后端接口返回的RSA公钥加密(RSA密钥对更新周期看情况而定)。
(3)将加密的参数以及AES密钥发送到服务器。
(4)服务器先用RSA私钥解密出AES密钥,再用AES密钥解密出参数。
响应加密:对于有重要信息返回的,比如金额订单等。建议做法如下:
(1)响应数据直接使用随机生成的AES密钥加密。
(2)AES密钥用服务器的私钥加密。
(3)服务器将RSA公钥返回给前端,将AES密钥以及响应数据返回给前端。
(4)前端收到请求后,用公钥解密出AES密钥,再解密出响应数据。
响应加密的安全性比请求加密的安全性弱很多。主要受制于浏览器的数据没法私有保存,浏览器B端只能存RSA公钥,该公钥可以被监听到,因此窃听者也可能获取RSA公钥并对AES密钥解密进而对数据解密。
对于公钥,前后端可以通过对公钥按字典表置换数据或调换位置等操作来使公钥更安全。