验证码校验的玩法,从单台、集群到分布式

您所在的位置:网站首页 我的世界服务器验证码是多少 验证码校验的玩法,从单台、集群到分布式

验证码校验的玩法,从单台、集群到分布式

2024-07-09 11:43| 来源: 网络整理| 查看: 265

验证码的校验原理其实很简单:

客户端请求验证码;服务端生成校验码(code_key-code_value),code_key是一次验证码请求和校验的标识(也有称会话id),会返回给客户端;code_value表示正确的验证码(通常以字符串表示);如果是图片这类的验证码,则需要将图片输出到客户端。用户输入验证码(input_code_value);客户端会将code_key和输入的验证码(input_code_value)发送至服务器进行校验,如果input_code_value=code_value则表示校验通过。

而我们下面要探讨的是,在不同场景下,处理校验码的一些方案;主要包括验证码存在哪里、由谁来校验、怎么校验这几个方面。

1. 单台服务器验证码校验(session)

相信大家都有了解session的原理,客户端访问服务器后,服务端给客户端返回一个叫JSessionId的cookie,服务器可以根据这个值来标识本次会话。单台服务器下,session是一个不错的验证码存储的地方,我们不用担心各个会话间的验证码存在冲突。 以 用户登录+图片验证码+session 为例,其流程主要为:

用户登录+图片验证码+session

 

这里code_key可以理解成JSessionId+session.attribute中的key(这里是"code")

2. 服务器集群下的服务器校验(MySQL/Redis)

当单个服务(如用户中心)使用多台服务器部署后,因为需要做负载均衡,一般情况下(暂不考虑IP-hash那样的策略),用户每次发起的请求有可能会去到不同的服务器,这时候session就会失效了,因为JSessionId这个标志去到别的服务器是找不到对应的session的(事实上,传统的session已经慢慢退出江湖)。 这时候,我们需要自己掌控code_key的生成和存储,关系型数据库(如MySQL)或高性能的NoSQL数据库(如Redis)都是不错的选择。以 用户登录+图片验证码+redis 为例:

用户登录+图片验证码+redis

 

可以看到,与单台服务器主要差距在:

自己生成code_key(为了防止不同用户间验证码的冲突,生成规则通常与用户标识有关,比如用户id+随机数的组合转换),不再依赖JSessionId;验证码的存储的地方从session转移至redis。 3. 各司其职,分布式下的验证码校验(验证中心)

在上面两种方式,我们发现验证码的生成、存储、校验、业务处理等动作均是在业务方完成的,验证码逻辑和业务的耦合可能会导致一些问题:

验证码的风险(比如机器识别难度低、验证接口被攻击等)将由业务方来承担,而业务方往往不愿意投入过多的精力在上面;当我们需要升级验证码方式时(比如图片文字识别 -> 文字点击顺序/拖动/手机验证码等),往往需要服务器做出不小改动和发版,成本较高。

为了解决上面的这些问题,我们可以建立一个专门搞验证的服务——验证中心:

验证中心负责各种类型的验证码校验和存储(如采用MySQL/redis,校验方案与集群的那种一致),并提供足够安全的验证码类型供业务方选择;输出验证码(code_key)和第一次校验由客户端和验证中心完成,业务方不参与该阶段验证;验证中心第一次校验成功后生成对应的ticket(比如uuid)给客户端,业务方需要根据code_key和ticket到验证中心进行二次校验,确保验证结果有效。

仍以用户登录为例,我们现在来看看初步的方案:

 

验证中心初步流程

我们需要明白的是,客户端一共发起三次请求:(1)请求验证中心输出验证码(2)请求验证中心校验验证码(3)请求业务方二次校验并处理业务。 这个初步的方案并不完美,因为在第(3)个请求,也就是二次校验时,只要code_key-ticket相互对应都会通过,这会导致:

不同的业务系统间的code_key-ticket混用;本来是业务A系统接口下(比如社区的回贴)所需的图形验证码,经过验证中心首次校验后,产生的code_key-ticket,直接拿到业务B系统接口下(比如支付系统的转账)依然适用(攻击者便可以轻松跳过转账接口的较为严格的首次校验);同一个业务系统,不同接口间的code_key-ticket混用;本来是业务A系统【接口1】下产生的code_key-ticket,拿到A系统的【接口2】上依然适用;

为了解决以上问题,针对每个业务方,验证中心需要分配一个的账号(也就是我们常见的app_id和app_secret); 针对某个业务方下的每个需要验证码的业务接口,需要分配一个的id(姑且叫business_id),它标识了对应的业务和接口,以及使用什么类型的验证码(当然这个类型应该支持动态配置),其关系如下:

app_id和business_id的关系

加入这些元素后,我们的流程基本不变,只不过多了一些参数校验而已,最终的流程:

 

验证中心完整流程

也有一些方案是没有business_id这个东西的,他们的business_id等同于app_id,一个业务方中也就只有一个。像我司的验证中心就是一个app_id,客户端、业务方均使用这个。这个主要看大家的细粒度需要分成什么程度了

4.总结 验证码实现方式实现成本优缺点session低只适用于单机;安全性依赖于业务团队水平业务方+MySQL/Redis中实现相对简单,能满足大部分使用场景 ;不够灵活,变动成本相对较高;安全性依赖于业务团队水平;各个业务系统需要自己搞一套,总的性价比不高。验证中心+MySQL/Redis高给业务方提供足够的安全性以及便利性(客户端/服务端对接验证中心提供插件支持,对接成本低);验证码类型的升级/变更,服务端不需要进行代码变更;前提验证中心的搭建投入成本较高,需要保证足够的tps支持业务需求,但一旦项目成熟,后期回报可观。

 

 



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3