原文地址:http://chenkangxian.iteye.com/blog/1819885
--转载自己的文章,原文发表在《程序员》2013年第2期上,感谢《程序员》授权转载
前言:随着移动互联网的兴起以及restful和web service的大规模使用,http协议因其使用方便以及跨平台的特性,在web开发以及SOA领域得到了广泛使用。但其所涵盖的信息,大都是未经加密的明文,信息获取门槛的降低,也为应用架构的安全性及稳定性带来了挑战。
对于常规的web攻击手段,如xss、crsf、sql注入等等,防范措施相对来说也比较容易,比如xss的防范需要转义掉输入的尖括号,防止crsf需要将cookie设置为httponly以及增加session相关的hash token码, sql注入的防范需要将分号转义等等,做起来虽然简单,但却容易被忽视,更多的是需要从开发流程上来予以保障,以免因人为的疏忽而造成损失。
本篇更多的是从平台架构的安全性及稳定性方面着笔,希望能通过些许文字的分析和介绍,来窥探http平台搭建所涉及的一些技术细节,给读者以启发。
协议的安全性
http协议其所涵盖的信息都是未经加密的明文,包括请求参数,返回值,cookie,head等等,因此,外界通过对通信的监听,轻而易举便可模拟出请求和响应双方的格式,伪造请求与响应,修改和窃取各种信息。相对于tcp协议层面的socket传输方式,针对http协议攻击门槛更低。因此,基于http协议的web及SOA架构,在应用的安全性方面,需要更加的重视。
1.摘要签名
对于普通的非敏感数据,我们更多的关注其真实性和准确性,因此,如何在通信过程中保证数据不被篡改,便成为首当其冲需要考虑的问题。鉴于使用https性能上的成本以及需要额外申请CA证书,这种情况下,一般采用参数摘要的方式即能够满足需求。每次请求和响应生成对应的sign,以此来保障请求及响应不被第三方篡改。
请求的参数经过排序,将参数名称和值经过一定的策略组织起来,加上一个密钥secret,然后通过摘要算法生成sign。常见的摘要算法包括MD5、SHA等等,由于摘要算法的不可逆性,以及请求参数值的多变性,能够在一定程度上保证通信的安全性。
图1 签名的构造
服务端接收到请求后,以同样的顺序将参数排序,加上相同的secret,以相同的摘要算法生成签名,然后与请求传过来的sign进行比较,如果参数在中途被篡改,传过来的sign与服务端生成的sign则存在差异,以此来判断请求的合法性。
图2 签名的校验
服务端校验完成后,生成响应,同样的,响应的内容也需要以类似的方式进行签名,客户端收到响应后,根据接收到的sign来验证签名的正确性。
举例来说,某个请求的url可能是这样,www.xxx.com/api.do?userid=12345678&page=1&pagesize=10&signtype=MD5&charset=gbk&method=com.chenkangxian.getname&sign=aef503e0ae7c27b04c2fe1cc95ce1d,userid、page、pagesize是常规参数,signtype表示加密类型,charset表示编码,method表示接口名称,sign为生成的签名串,为了互联网传输方便,一般对其进行16进制或者base64编码,服务端将接收到的参数拼接成字符串userid=12345678&page=1&pagesize=10&signtype=MD5&charset=gbk&method=com.chenkangxian.getname,采用MD5算法生成sign,与传递过来的sign(当然,需16进制或者base64解码)比较,如果一致,表示参数未被篡改。
2.公私钥签名
上述方法能较好的解决数据合法性校验问题,但是secret相对固定,如果多客户端调用,容易导致secret泄露。
因此,可以给每个客户端分配一对公私钥,请求时,客户端将参数按与前面类似的方式排好序,拼成一个字符串,md5后,通过私钥加密,生成sign。
图3 客户端用私钥生成sign
服务端采用同样的方式将参数编排,拼成字符串,md5,通过客户端公钥解密sign,与其md5生成的值进行比较,便可得出数据是否合法。
图4 服务端用公钥校验sign
当然,客户端也可以采用相同的方法,使用服务端的公钥,对服务端进行校验,这里就不一一枚举了。
3.https
上面的两种方法能较好解决数据合法性问题,但对于一些较为敏感的信息,如隐私数据,用户名密码等等,这些信息如以明文的形式传递,会带来较大风险,服务端secret或者公私钥相对固定,一旦密钥泄露,也会有很大的安全风险,并且,通信过程中,客户端与服务端的身份,特别是服务端的身份难以得到保障,第三方可以通过域名劫持的方式来伪造身份,欺骗客户端向伪造的服务端发送数据,这样一来,损失将不可估量。因此,有必要采用更加严格的加密手段来保障信息的安全。
依托SSL(Secure Socket Layer)协议,https能够确保整个通信过程加密,密钥随机产生,并且能够通过数字证书验证通信双方的身份,以此来保障信息安全。
图5 服务端单向身份认证https通信过程
SSL协议握手的过程是这样的,客户端向服务端发送SSL协议的版本号,支持的加密算法类型,产生的随机数以及其他客户端与服务端通信所需要的信息,服务端收到这些信息后,会将它自己的SSL协议版本,支持的加密算法类型,以及产生的随机数等等内容,加上它的数字证书,一起回复给客户端。
证书以证书链的形式组织,客户端会逐级校验证书的合法性,包括服务器域名是否与证书所声明的域名一致,证书是否过期,证书颁发机构是否是可信赖的等等。这个过程对于用户来说一般是透明的,操作系统会内置一些知名的CA机构的根证书,免去用户的安装步骤,开发者或机构只需要向相关的CA机构以付费的方式申请证书即可。当然,也有个别例外的奇葩,如12306,直接将根证书挂在主页上供用户下载。
校验完证书过后,客户端将产生一个预主密码,并用服务端的公钥加密传送给服务端,服务端会根据预主密码来生成通信密码,与此同时,客户端也通过相同的方式生成通信密码,这样,一次通信握手基本完成。
通过SSL协议能够完成对服务端的认证,加密数据,防止在传输过程中信息的泄露和篡改,能够在相当的程度上保障通信的安全性。
4.应用授权
以上的场景其实是在通信双方相对信任的基础下完成的,客户端直接访问服务端完成数据交互。还有一种场景是平台商将数据有限开放给第三方软件厂商(ISV),第三方软件厂商再利用这些数据来给用户提供服务,当然,前提是用户必须对ISV授权。对于平台厂商来说,用户形形色色的需求,很难以一己之力来予以充分满足,因此,将数据以接口的形式下放给众多的第三方开发者,便成了必然的趋势,也正是由此引发了近几年的“开放平台热”。这样,如何保障对用户数据的访问均是经过授权的,且不会对第三方泄露用户的用户名密码,便成了首当其冲的问题。
OAuth协议为用户资源的授权提供了一个安全、开放的标准,与以往的授权方式不同,OAuth不需触及到用户账户信息(用户名密码),即可完成第三方对用户信息访问的授权。
图6 开放应用平台授权
OAuth协议的出现,使得用户在不泄露自己用户名密码的情况下,能够完成对第三方应用的授权,第三方应用得到用户授权后,便可以在一定时间内访问到用户授权的数据。
图7 Oauth协议的授权过程
一次OAuth协议的授权过程如上图所示,用户先对ISV发起请求,ISV向平台商请求request token,带上其申请的app id,平台返回request token,其后ISV应用将用户引导到平台的授权页面,带上自己的app id、request token以及回调地址,用户在平台的页面上完成授权(这样便不会将用户名密码泄露给第三方),然后平台通过ISV提供的回调链接,返回给ISV应用access token,ISV应用通过access token取到用户授权的数据,进行加工后返回给用户,授权完成。
为了确保通信安全,一般会让ISV使用其私钥对参数进行签名,平台使用ISV的公钥进行签名验证,来校验ISV的资质,具体过程前面详细介绍过,此处不再赘述。
OAuth协议得到了国内外互联网公司的广泛认可,包括Facebook,Google,Window Live,以及国内的腾讯、新浪、淘宝、人人等,都对其提供了良好的支持。不同的厂商有不同的OAuth版本,但不论是OAuth1还是OAuth2,其核心思想都是将资源做权限分级和隔离,ISV引导用户在平台端登陆,完成授权,获得授权后ISV可以在一定时间段内访问用户的私有数据,用户完全把控这一过程,且授权可取消。这样,第三方ISV能够利用平台商所拥有的一些数据,来服务用户,为用户创造价值,形成了一个生态系统的闭环。
OAuth授权其实是一个相对较复杂的体系,涵盖系统的方方面面,包括之前所说的通信加解密,以及权限划分,token生成和校验,公私钥的管理,还有后面将要提到的分布式session机制等等。相对于前几年来说,由于开源社区的发展,为其的实现降低了不少门槛,目前已有很多开源的解决方案,详情请参照OAuth网站(http://oauth.net)。
session的安全性
对于互联网应用来说,为了应对高并发访问的压力,支撑其业务的往往不止是单台服务器,而是一个分布式集群,http请求在不同的服务器间跳转,这样集群间session的同步便成了不得不考虑的问题。
对于一般web应用来说,采用cookie能解决一部分问题,但随着应用规模的不断扩大,cookie会不断的膨胀,而浏览器对于每个域名下的cookie的个数以及每个cookie的长度会有所限制,不能满足持续性增长的需要,并且,客户端的cookie数据会存在一定的安全性隐患。对于服务端调用来说,请求不经过浏览器,cookie显然无法满足需求,随着移动互联网的发展,基于http的SOA架构还将兼容无线客户端的请求,因此,基于cookie的session同步方案已无法满足需求。
图8 基于cache的分布式session结构
如上图,基于cache的分布式的session同步机制,能较好的解决上述问题。客户端通过login登陆,如果客户端为浏览器,则通过cookie回写的方式,设置sessionid,如果是在移动端或者服务端调用,则直接返回sessionid,这样,不管用户如何跳转,不同的客户端和应用都可以通过sessionid到cache集群中取到session,避免了session丢失。
而使用一致性hash算法,能够确保当某台cache server宕机后,不至于整个的key都重新hash一遍,导致所有的用户都需要重新登录,这样不仅提升了用户体验,也降低了对于login的压力,不会有大量的用户像雪崩一样同时发来大量的登录请求(这对于像淘宝双11双12这样大流量的活动来说,十分重要)。使用cache来存储session会话,即表示会话是可以丢失的,对于系统设计者来说,对这一点须有清楚的认识。
分布式session也会跟普通单机session一样,存在session失效以及cookie防盗用等等问题。
为提高cache的利用率以及提高session的安全性,须针对cache设置一定时长的失效时间,避免在用户在离开位置后session被其他人盗用,但是,对于用户连续性的操作,又必须对session的到期时间进行不断更新,否则,可能会影响到用户的体验。
对于sessionid来说,最好是将其设置为httponly,避免跨站脚本对cookie进行盗用,当然,采用分布式session后,任何人都已经很难从cookie本身提取到有价值的攻击信息,但是,如果通过窃取sessionid来伪造用户登陆,则不得不防,尤其是交易相关的业务,可能会造成相当大的危害,因此,需将session的状态与客户端的ip地址或者mac地址挂钩。如果用户从ip1登陆,通过ip2来访问用户信息,即便ip2访问的时候带上了sessionid,也需要重新进行登陆,这样的话,则相当程度避免了会话劫持的发生。
平台的稳定性
对于生产环境的应用集群来说,故障是很难完全避免的,建立完善的监控预警机制,能够提高遇到问题时的响应速度,帮助快速发现问题,及时通知相关技术人员对故障进行修复,有效的避免或者降低损失。与此同时,也必须做好流量控制,防止突发的大流量将服务器压垮。
1.集群监控
生产环境的情况往往复杂多变,用户的行为不可预测,有效的监控措施不仅能够提高遇到问题时的响应速度,也为应用的扩容,性能的优化提供了参考依据,对我们及时了解应用的水位,评估和设置警戒线提供了十分重要的帮助。
常规的监控可以包括如下方面,机器的load,cpu使用率,内存使用率,网络traffic,pv以及uv信息,IO繁忙程度,磁盘使用率,异常catch等等,如果是java应用,应该包括堆栈的使用情况,fullgc的频率等等,如果是mysql DB,需要包括select/ps,update/ps,thread running等等,这些指标信息能够基本反映机器运行的健康状态。一旦某个指标出现异常,比如受攻击导致流量激增,可以发短信或者邮件通知相关应用负责人,进行及时的处理。
对于采用http协议的应用来说,能做的不仅仅只有这些,还可以采取包括接口数据校验,部分线上回归测试,页面状态检测等等措施,更加全面的对应用进行健康检查和监控。
举例来说,对于异步返回json、jsonp、xml格式数据的接口来说,可以事先造好一部分固定数据,覆盖接口代码的各个分支路径,然后通过shell脚本定时执行(crontab部署定时任务)的方式,验证返回的数据是否完整是否正确,以此完成接口的扫描与检查。
- $CURL_BIN -s -m 100 "${HOSTNAME}${URL}" > $TMP_FILE
- if [ "$CHECK_TXT" != "" ]; then
- check_result=`fgrep $CHECK_TXT $TMP_FILE`
- if [[ "$check_result" = "" ]]; then
- CHECK_STATUS="1"
- echo -e "check failure!\t${URL}\n"
- fi
- fi
code1 接口检查shell片段
脚本通过curl来请求相关接口url,将返回值与check_txt(预定义文本)通过fgrep比对,如果与预计的不符,则输出check failure,程序检测到该输出,则发送短信报警。
对于页面来说,返回的数据量大,整体校验相对来说代价较大,可以针对一些核心流程,比如接口的调用,后端数据的返回,定义一些状态码,塞到http的header请求头中返回,这样,通过监控header中对应的状态值,来完成页面的监控。
- $CURL_BIN -s -I -m 100 "${HOSTNAME}${URL}" > $TMP_FILE
- status=` awk -F ":" '{if($1 == "Server_Status"){print $2}}' $TMP_FILE `
- status=${status//}
- if [ "$status" = "ok" ]; then
- CHECK_STATUS="0"
- else
- CHECK_STATUS="1"
- echo -e "check failure!\t$URL\n"
- fi
code2 一段页面监控的shell片段
脚本通过curl来访问相关页面,通过awk过滤出header中的Server_Status值(该值在应用端事先约定好),判断其是否为ok状态,如果ok,则忽略,否则,输出check failure,程序检测到该状态,则发送报警短信。
2.并发与流量控制
任何应用都有一个设计指标和能承载的峰值,当它的压力超过了它设计的峰值以后,就好比一座为行人设计的独木桥,即使它再坚固,也无法让一辆坦克行驶通过,在这个时候,为了让机器能够正常运行,不至于完全瘫痪,需要对应用进行流量控制。
控制的策略有多种,可以直接丢弃掉那部分超出峰值的用户请求,这样虽然比较粗暴,但也是最简单最有效的方法,还有一种便是削峰填谷,将一部分暂时来不及处理的请求放入等待队列中,待资源空闲时再逐步消化,具体使用哪种策略,与应用的场景相关。
当然,要进行流控,首先得有一个进行流控阀值,这可不是拍拍脑袋或者仅凭经验就能够得出来的,不同的应用,不同种类的接口,不同的机器配置,其所面临的情况也不尽相同,阀值必定是有差异的,必须经过几轮的压力测试下来,才能够得到一个比较靠谱的值。
流控可以从多个维度来进行,比如针对qps(每秒查询数),并发线程数,黑白名单,服务加权分级等等,最典型最直观的,便是通过对qps或者是并发线程数的控制,来达到限流的目的。
从具体实施的角度来说,可以在应用的负载均衡端(如nginx)完成,这一层可以进行整体的比较粗粒度的控制,比如客户端的并发请求数,请求的频率等等,这样可以过滤掉大部分攻击请求,提高ddos的组织难度,当然,更加复杂的策略,如验证码防刷,黑名单,ip封锁等等,可以通过编写nginx模块来进行定制。
Nginx从0.7版开始提供2个限制用户连接的模块HttpLimitZone Module和HttpLimitReq Module,可以用来限制用户请求的频率和并发连接数:
- limit_zone zone_session_state $binary_remote_addr 10m;
- limit_req_zone $binary_remote_addr zone=req_session_state:10m rate=1r/s;
- location /
- {
- limit_conn zone_session_state 1;
- limit_req zone=req_session_state burst=5 nodelay;
- … …
- }
code3 nginx配置限流
负载均衡端作为应用总的流量入口,采取的限流措施可以挡掉大部分的恶意流量,但缺乏灵活性,难以响应后端的变化,并且受调度策略的影响,并不能保证落到每一台服务器的流量都是均衡的,因此,一般的策略是将入口阀值适当调高,然后结合应用端协同来进行流控。
应用端流控的好处便是能够更细粒度的划分流控的单位(能精确到接口层面),更加方便的调节流控阀值,动态的修改服务权重、调用的黑白名单,以及进行服务分级,优先保障核心流程的稳定,这在应对大流量高并发的压力 (如淘宝双11,双12)时,显得尤为重要。
关于应用端流控的实施,涉及众多细节,限于篇幅,笔者将在个人博客做详细介绍,此处便不再赘述。
小结
本文从协议的安全性,session的安全性以及平台的稳定性三个方面,介绍了http平台搭建过程中所面临的一些问题以及解决办法。http协议因其明文传输的特性,使得在系统设计阶段,不得不对安全性作充分考量。而对于生产环的境应用来说,完善的监控预警措施,能确保在第一时间发现问题,及时采取恰当的措施,避免损失;合适的流控机制,能保障在流量突增的情况下,机器能顶住压力,不至于宕机。
相关推荐
【产品设计思考:浅析平台化架构】 在电商领域,产品设计的核心挑战在于应对业务需求的多样性和紧迫性。由于消费者忠诚度低和行业竞争激烈,电商平台必须不断迭代和创新,这往往导致开发团队陷入频繁的紧急需求之中...
3. 灵活的会议室架构:ZOOM支持多种会议模式,如一对一视频通话、多人会议、大型研讨会等,满足不同规模和类型的会议需求。 4. 安全保障:ZOOM提供了端到端加密、会议密码保护、等候室等功能,确保会议数据的安全。 ...
4. **安全性与稳定性**: - 考虑网络安全、系统成本等因素 - PHP + MySQL + Apache on Linux 组合提供了良好的稳定性和安全性 ### 结论 OA系统的引入和发展极大地提升了企业的信息管理水平。通过对OA系统的基本...
FTP文件传输协议被推荐用于主站和子站之间的数据传输,因为它具有稳定性、可靠性和广泛适用性,可以实现文件的上传和下载,进一步确保了通信的标准化和效率。 总之,这篇论文深入剖析了电网继电保护与故障录波器...
"浅析网络安全风险和信息系统安全监测响应平台的设计" 网络安全风险已成为网络稳定可靠运行的重要威胁。为了确保信息网络系统的安全,我们需要有效的安全风险防范措施,建立具备识别和响应联动、规范与措施统一的安全...
### 浅析融媒云平台安全风险及保障措施 #### 一、引言 随着信息技术的飞速发展,媒体行业正经历着前所未有的变革。新兴媒体与传统媒体的融合不仅推动了媒体行业的创新发展,同时也对媒体机构的技术架构提出了更高...
曾在程序员上发表过《漫谈基于http协议的SOA架构》《浅析HTTP平台的安全稳定性架构》两篇文章,对基于HTTP协议的SOA架构有深入研究,在排查解决线上问题和故障方面有丰富的实践经验,擅于利用数据分析解决实际问题,...
- **稳定性和效率**:纯软件架构,减少专用硬件的使用,降低了系统的故障率,减少了耗电量和发热量,提高了整体的稳定性和效率。 - **兼容性与扩展性**:采用成熟的硬件平台,如品牌图形工作站,并对IO卡进行模块化...
【标题】:“浅析中大型企业网的互联网架构” 【描述】:本文主要探讨了中大型企业网络在面临公网IP地址短缺问题时,如何利用NAT(网络地址转换)技术来构建互联网架构,以满足大量用户同时上网的需求,同时考虑...
Android内核是基于Linux内核开发的,它在继承了Linux内核稳定性和可靠性的同时,增加了一些定制化的功能和优化。Android内核具有以下特点:安全性、可靠性、可扩展性和高性能等。Android内核采用了强制访问控制的...
#### 六、MTK平台CAMERA驱动架构: MTK平台的摄像头驱动架构主要涉及以下几个方面: - **硬件接口层**:直接与硬件交互,负责数据采集和控制。 - **中间件层**:提供高级功能支持,如图像处理和控制接口。 - **...
大量的网络服务器因病毒侵袭导致瘫痪,数据丢失,严重影响信息系统的稳定性和安全性。现有的防病毒措施往往无法跟上病毒的演变速度,尤其是服务器防护能力的不足,给病毒制造者提供了可乘之机。 为了应对这些挑战,...
为了应对传统架构中的单点故障和数据无副本的问题,“中国蓝云”云平台构建了高安全性的数据库系统。其特点包括: - 多节点容器集群并行计算机制,实现自动负载均衡和故障切换。 - 后台业务系统至少拥有三个数据副本...
内存管理对于保证系统的稳定性和性能至关重要。 ##### 2. 程序库与Android Runtime Android系统中的程序库包括了一系列的核心库和框架,这些库为开发者提供了丰富的API接口,用于开发应用程序。其中比较重要的有:...
通过实时监控、分析和响应,该平台能有效地预防、检测和应对网络攻击,提高电力系统的安全性和稳定性。随着网络攻击技术的不断演进,持续研究和优化这样的监测技术对于电力行业的网络安全至关重要。
Android嵌入式系统架构及内核浅析的知识点 一、Android系统概述 Android是Google公司推出的基于Linux平台的开源手机操作系统,它不仅包括操作系统本身,还整合了中间件、用户界面和应用程序,旨在消除移动产业创新...
安全平台的设计原则应包括可靠性、稳定性、可扩展性和内容交互的安全性。具体来说,需要保证系统操作管理的安全合理性,防止功能权限滥用,并实施有效的日志管理功能。同时,考虑到未来高清、超高清视频的应用,必须...
通过这些功能,信息安全运维体系可以提升对网络安全的监控和响应能力,确保重要信息系统的稳定运行,降低安全风险,保障企业或组织的业务连续性和数据安全性。同时,通过审计和评估,持续优化运维流程,积累经验,以...