背景
在项目中我们经常用rest 方式调用第三方的服务,对于公司内部的服务可以不进行认证。
在这里我仅讨论根据不同场景如何逐步提升其借口访问的安全性。
本文整体以 clientA 访问 server B 为场景讨论。
最基本情况:不做任何鉴权
server B 只把服务暴露给内网ip,即只有内网客户端能够访问。所以对于内网的所有有效报文请求都信任不会做任何控制。
base Auth:做身份鉴权
client A 要与server B通信前 需要获取身份,比如token(也可以说是会话),以后每次会话都需要带上该该token,用于server B进行身份校验。
其具体请求逻辑为:
第一次请求:
A ------获取token (带上用户名和密码)------> B
A <-----返回token ---------------------------------B
第二次请求:
A ------正式请求携带token --------------------------> B
A <---------如果token失效,则A需要根据B返回错误码提示 重新获取token---------------B
往后请求:
A -------------携带token-------------------->B
从这里看出这里的交互模式与浏览器请求网站服务,用户在浏览器输入用户名和密码后进行登录获取一个cookie,随后该cookie存放在浏览器中(相当于浏览器缓存)。以后用户每次请求都带上该cookie,服务器通过该cookie进行身份验证。
而如果A,B同为服务器,那么存放在A服务器上的(用户名/密码)应该存放在一个私密的地方。
且获取的token应该存放在缓存中(如果是分布式系统就应该存放在分布式缓存中),必便下次A请求的时候携带。
防止篡改
base Auth 解决了身份认证的问题,即知道了该包是来源于信任的地方。但是如果来源于信任地方的包如果在网络上被篡改了数据怎么办?
此时大部分的办法就是通过md5加密验签, 双方开发者协商一个salt。
其具体模式为:
[client A:md5(原串+salt)] ==[ server B md5(原串+salt)]
server B自己对A传过来的数据进行md5验签,如果验签正确表示数据没有被串改。
这种方式解决了身份认证问题和确认数据是否被篡改。由于双方都要对同样的数据+双方约定的salt进行加签名 这就表明了对方是我们线下协商信任的(salt是不会再网络上传输防止了在网络上被截取)。
防止被查看
前面的方式中数据都是以明文的形式在传输,如果有一些隐秘的字段我们不想让它被别人看到的话怎么办呢。
第一种办法:不要传输隐秘字段,比如java序列化中的transient关键字修饰的字段就不会被传输。
第二种办法:对数据进行加密,但是需要对方能够解密。现有大多数方案都是在 client A通过RSA 公钥加密 sever端通过私钥解密。
网友评论