V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
maninfog
V2EX  ›  V2EX

V2ex 客户端模拟登录,一直提示「验证码错误」?

  •  
  •   maninfog · 29 天前 · 1583 次点击

    最近在做一款 V2EX Android App ,正在实现登录功能。

    已经有不少优秀的 V2EX 客户端开源项目,我经常参考的如:

    Android: https://github.com/v2er-app/Android

    iOS: https://github.com/Finb/V2ex-Swift

    通过查看他们源码得知,模拟登录的步骤如下:

    1. 发送一个 get 请求到 /signin 。通过解析网页结果,获取到用户名,密码,以及验证码的 form key ,以及一个字符串 once 。
    2. 通过拼接 /_captcha?once=$once ,得到验证码的图片 url ,加载该 url ,让用户查看和输入验证码
    3. 发送 post 请求到 /signin, 这是一个表单请求,结合第一步的 form key 和 once 以及用户输入的验证码拼装表单数据。
    4. 通过第 3 步返回的 response code 和数据判断是否登录成功。

    现在卡在第 3 步,现象是:即使我十分确定验证码正确的情况下,还是会得到提示「验证码错误」的情况。

    经过反复对比实现方式,我比较确定自己的代码的实现是没问题的,有一些细节比如添加一些额外的 header 之类的我也做了,但是还是出现这个问题。我自己的一些猜测的可能:

    1. IP 和账号问题。(通过使用别的客户端,发现可以正常登录,排除。)
    2. 验证码 url 被加载了多次,导致界面上看到的不是最新的验证码。(通过手动加载验证码并确保只加载一次,还是有问题。)
    3. 加载验证码 url 的请求的 header 必须和请求 /signin 时保持一致。(通过修改代码确保一致,无果。)

    折腾一两天,现在有点黔驴技穷的感觉,另外登录次数多了还会导致 IP 被风控,导致调试都是谨小慎微。

    不知道 v 友有没啥好的想法?

    第 1 条附言  ·  29 天前
    问题解决,此贴终结。

    感谢大家,特别是 @SillyAdam 提到关于 cookie 的事情帮助很大。

    目前列出一些比较关键的点:
    1. 获取验证码的 url - /_captcha/once?=$once 会给一个叫“PB3_SESSION” 的 cookie ,这个 signin 的时候需要带上。

    2. 因为 Mobile 端一般会使用图片加载框架直接加载图片,这样会导致获取验证码时请求会不经过网络框架,因此 cookie 不会缓存。我目前方案是先用网络框架加载成 ByteArray 再塞给图片框架,这样 cookie 得以保存。

    3. OkHttp 支持 POST 请求 response code 302 的重定向,Ktor 不支持,这导致使用 Ktor 网络请求时,登录成功了不会加载重定向的网页,进而获取不到用户信息。目前解决方案方案是登录时如果发现 response code 是 302 ,自己手动再发一个请求获取用户信息。
    16 条回复    2024-09-27 17:21:04 +08:00
    wowo243
        1
    wowo243  
       29 天前
    没开发过客户端,但是可以提供个思路:
    开抓包工具,分别对已有开源代码和问题代码,然后对比抓包工具中各个请求的参数与返回。
    实际上就是比对流程的差异,排查问题。
    另外,个人经验,有的时候问题解决不了可以先放一放,等到放松下来转换个思路说不定就解决了。
    lawler
        2
    lawler  
       29 天前
    我刚巧在两年前也开发过 V2EX 模拟登录的功能,可以非常确认是你的代码问题。

    因为模拟登录步骤所描述的逻辑没有问题。
    SillyAdam
        3
    SillyAdam  
       29 天前
    我看了一下,图片验证码的路径是 `/_captcha?now=...`。这个 `now` 后面跟的应该是时间戳,用来避免浏览器缓存图片的。实际上验证码的信息应该是存在 session / cookie 里面的。我清空 cookie 之后访问验证码,看到服务器有发一个新的 cookie 叫 `PB3_SESSION`。校验的时候应该是要把这个 cookie 带上才行。
    Blanke
        4
    Blanke  
       29 天前
    带上 cookie 了吗
    finab
        5
    finab  
       29 天前
    我依稀记得第二次请求登录页会导致上一次的验证码和 once 失效,可以排查下你是不是重复请求登录页面了。
    wnpllrzodiac
        6
    wnpllrzodiac  
       29 天前 via Android
    每天签到脚本工作正常
    maninfog
        7
    maninfog  
    OP
       29 天前
    @wowo243 感谢建议。之前通过看 log 大致对比了下请求,发现是一样的,我再通过抓包的方式试试。
    @lawler 我自己 review 了好几遍了,另外看 request 的日志 form 的提交数据也是能对应上的,奇怪。
    @SillyAdam 应该不是,看了好几个开源的都没有用到这个 now 字段. 这个 now 应该 是浏览器刷新验证码用的,但是大部分客户端刷新验证码的逻辑都是直接重新全量请求 /signin 实现。
    @Blanke 试过带与不带,同样错误。
    @finab 我现在测试都是每次重进下页面,重新请求 /signin ,不涉及重复请求的问题。
    oneisall8955
        8
    oneisall8955  
       29 天前
    Postman 走一遍
    abu
        9
    abu  
       29 天前
    我用自己另一台 pc 登录的时候也提示错误,我也确认我输入的就是显示的验证码,后来就戒了在那台 pc 上看 V2
    Livid
        10
    Livid  
    MOD
       29 天前   ❤️ 1
    @abu 那种情况通常是因为插件。
    NoOneNoBody
        11
    NoOneNoBody  
       29 天前
    v2ex 的 token ,跟 css 有关
    别问我怎么发现的
    wnpllrzodiac
        12
    wnpllrzodiac  
       27 天前
    @wnpllrzodiac 发现不正常了。。。。
    cookie 里面的 value 带 " 和 | 是合法字符的吗?
    maninfog
        13
    maninfog  
    OP
       27 天前
    @wnpllrzodiac 啥问题? 我理解 cookie 里面有" 和 | 是没问题的
    wnpllrzodiac
        14
    wnpllrzodiac  
       27 天前
    @maninfog 查下来发现 firefox 里面 f12 复制 curl 命令到 linux 测试正常,能返回登陆页面。到 windows 端就不能返回登陆的页面。windows 的 bat 不支持 -H 'xxx' 单引号。只能用双引号,但是这样;|就需要处理,但是 firefox 好像也没有正确的处理。
    cf worker 做个自动签到功能还是挺好的。
    Xushet
        15
    Xushet  
       25 天前
    给个项目地址我可以点点 star ,顺便求一个支持 Android 默认链接打开的功能,找了几个 v2 客户端都没有
    maninfog
        16
    maninfog  
    OP
       25 天前 via Android
    @Xushet 目前还处于雏形期,私有项目。另外你说的「默认链接打开的功能」是指你希望当在 APP 打开链接的时候可以指定浏览器而不是直接 Chrome 吗?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1323 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 23:40 · PVG 07:40 · LAX 16:40 · JFK 19:40
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.