验证码服务recaptcha和vidoop

某人已经发展到上班时间写blog了。

继续说验证码服务,找到两个比较典型的。recaptcha非常著名,是twitter和facebook使用的验证码服务(不知道现在的情况。。。),vidoop提供了一种很有特点的验证码机制。

两个服务都提供了python的接口封装便于接入,通过api接口可以管中窥豹,大致了解这两个验证服务的机制。

recaptcha

下面是一段结合了web.py的简单调用

public_key = "******"
private_key = "********"
class Recaptcha(object):
    def GET(self):
        r = recaptcha.displayhtml(public_key)
        return render.recapt(r)

    def POST(self):
        params = web.input()
        recaptcha_challenge_field, recaptcha_response_field = params.recaptcha_challenge_field, params.recaptcha_response_field
        remote_ip = web.ctx.ip
        result = recaptcha.submit(recaptcha_challenge_field, recaptcha_response_field, private_key, remote_ip)
        return result.is_valid

我在GET请求中获取验证码,在POST请求中提交验证码。

recaptcha返回的是一段recaptcha自己风格的html片段,效果大家参考twitter的验证码,实际上是一个iframe,iframe的url中包含了哈希串。其中的字段名也自然被写死成recaptcha_challenge_field和recaptcha_response_field,考虑到应用服务器无需验证这两个field的输入,所以也无可厚非。recaptcha_response_field用于输入字符,recaptcha_challenge_field在载入时被修改为一个唯一key。

提交验证时,recaptcha需要提供以上两个用户输入和应用的privatekey以及浏览器ip。recaptcha通过recaptcha_challenge_field 应用的private key以及用户出口ip可以唯一标示用户,并包含一些冗余实现安全相关策略。

Vidoop

Vidoop提供的服务机制与recaptcha大同小异

customer_id = "***"
site_id = "localtest"
api_username = "******"
api_password = "******"
vdp = VidoopSecure(api_username, api_password, customer_id, site_id)

class Vidoop(object):
    def GET(self):
        captcha_id, captcha_url, captcha_categories, captcha_text = vdp.create_captcha()
        return render.vidoop(captcha_id, captcha_url, captcha_categories, captcha_text)

    def POST(self):
        params =web.input()
        captcha_id, captcha_code = params.id, params.code
        try:
            vdp.submit_captcha(captcha_id, captcha_code)
            return True
        except:
            return False

提交验证时只需要要captcha_id和用户输入,这里相对recaptcha做了简化,但已经足够验证需要了。

验证码服务的两种方式

方式1,应用服务器负责生成验证码字符,验证码服务器主要负责验证码图片生成。

  1. 用户浏览器向应用服务器请求包含验证码的页面;
  2. 应用服务器生成验证码字符,存储在session中;应用服务器发送相关图片参数(验证码字符、宽、高、复杂度、背景色等)到验证码服务器;
  3. 验证码服务器返回图片地址到应用服务器;
  4. 应用服务器将包含验证码地址的网页发送给用户浏览器;
  5. 用户浏览器通过img的src方式向验证码服务器请求验证码图片;
  6. 验证码服务器输出验证码图片流到用户浏览器;
  7. 用户判读验证码图片,提交表单;
  8. 应用服务器取出session中的验证码字符比对,返回结果。

这种方式的优点:

  1. 较少的HTTP请求调用
  2. 替换原应用中独立的验证码功能相对容易
  3. 验证码服务器相对简单

方式2,验证码服务器承担验证功能,应用服务器在验证中仅起到传递作用。

  1. 用户浏览器向应用服务器请求包含验证码的页面;
  2. 应用服务器发送相关图片参数(宽、高、复杂度、背景色等)到验证码服务器;
  3. 验证码服务器返回图片地址、惟一的会话id到应用服务器;
  4. 应用服务器将包含验证码地址的网页发送给用户浏览器;
  5. 用户浏览器通过img的src方式向验证码服务器请求验证码图片;
  6. 验证码服务器输出验证码图片流到用户浏览器;
  7. 用户判读验证码图片,提交表单;
  8. 应用服务器将第三步获得的会话id和用户输入的验证码字符传给验证码服务器;
  9. 验证码服务器进行验证,返回通过或拒绝;
  10. 应用服务器根据验证码服务器结果进行响应。

这种方式的优点:

  1. 验证码服务功能完善,涵盖整个验证流程;
  2. 验证码服务端有详细的验证日志记录,便于数据分析;

欢迎大家就两种方式发表意见~

豆瓣架构发展PPT[转]

今天下午看到了这个豆瓣架构发展历程的PPT,是今年上半年QCon上的,看了以后感觉很有启发意义。随着用户量的增大,压力的增加,功能的扩展,豆瓣架构上做出相应的变化,从最初一台机器上跑lighttpd/mysql/Quixote/memcached到现在的DoubanFS存储,DoubanDB分布式Key-Value Store,加上多台mysql,多台appserver,专门的后台运算服务器等等。

PPT地址:
http://www.riawork.org/iarch/douban/douban_qcon2009_beijing.pdf

可惜因为字体的问题好像在Evince里很多中文字看不到,还得开一下虚拟机。

阿巴

早晨八点半下楼开自行车锁,突然听见背后有微弱的声音。回头一看是个老太太坐在轮椅上,眼睛直直地盯着我,嘴里含糊不清地发出阿巴阿巴的声音。我自然是听不懂她说什么了,继续开锁。十月份虽然还是阳光普照,但是风里已经有点肃穆的意思了。这样的天气,年纪大了的人独自在外面这么坐着,想起来还是很残酷的。我推车要走,老太太还是盯着我阿巴阿巴地喊。假日的早晨小区里空空荡荡,遇到这样的场面还真有点超出“奇怪”能表达的意思。我又不好意思头也不回就走,推着自行车走上前去,想问老太太点什么,但是好像又无从问起,最后大约问了些“您怎么在这里”,“您的家里人在哪”这类的问题。最终都没有形成对话,老太太还是自顾自颤颤巍巍地喊阿巴阿巴。这个时候旁边单元出来个中年妇女远远说了什么一句,我听不懂,只是听到“神经病”三个字。一看有亲戚在旁边,我想眼前这一切大约都还在别人的可控范围里,可以走了。

也不知道这个阿巴到底是什么意思,或者说于老人自己是什么意思。路上我故意想得戏剧性一些,难道是老太太的什么亲人,早年走失的儿子?当然了,很有可能只是一个老人丧失语言能力之后惟一能发出的声音而已。