TianaiCaptcha 开源验证码简单分析

7 分钟

滑块验证码参数

  1. 验证码的 ID:SLIDER_ff970847732c44859fb56935fab7f7c9
  2. 鼠标 move 的轨迹,一共记录 36 次
  3. 滑块从开始到结束的时间
ImageCaptchaTrack(bgImageWidth=300, bgImageHeight=180, templateImageWidth=null, templateImageHeight=null, startTime=Tue Sep 09 17:30:21 CST 2025, stopTime=Tue Sep 09 17:30:24 CST 2025, left=null, top=null, trackList=[ImageCaptchaTrack.Track(x=0.0, y=0.0, t=1244.0, type=down), ImageCaptchaTrack.Track(x=1.0, y=0.0, t=1268.0, type=move), ImageCaptchaTrack.Track(x=3.0, y=0.0, t=1284.0, type=move), ImageCaptchaTrack.Track(x=10.0, y=0.0, t=1301.0, type=move), ImageCaptchaTrack.Track(x=19.0, y=0.0, t=1318.0, type=move), ImageCaptchaTrack.Track(x=34.0, y=0.0, t=1334.0, type=move), ImageCaptchaTrack.Track(x=46.0, y=0.0, t=1351.0, type=move), ImageCaptchaTrack.Track(x=55.0, y=0.0, t=1368.0, type=move), ImageCaptchaTrack.Track(x=63.0, y=-1.0, t=1384.0, type=move), ImageCaptchaTrack.Track(x=75.0, y=-1.0, t=1401.0, type=move), ImageCaptchaTrack.Track(x=91.0, y=-1.0, t=1418.0, type=move), ImageCaptchaTrack.Track(x=113.0, y=-1.0, t=1435.0, type=move), ImageCaptchaTrack.Track(x=122.0, y=-1.0, t=1451.0, type=move), ImageCaptchaTrack.Track(x=132.0, y=-1.0, t=1468.0, type=move), ImageCaptchaTrack.Track(x=143.0, y=-1.0, t=1485.0, type=move), ImageCaptchaTrack.Track(x=156.0, y=-2.0, t=1501.0, type=move), ImageCaptchaTrack.Track(x=166.0, y=-2.0, t=1518.0, type=move), ImageCaptchaTrack.Track(x=172.0, y=-3.0, t=1535.0, type=move), ImageCaptchaTrack.Track(x=173.0, y=-3.0, t=1551.0, type=move), ImageCaptchaTrack.Track(x=174.0, y=-3.0, t=1568.0, type=move), ImageCaptchaTrack.Track(x=176.0, y=-3.0, t=1585.0, type=move), ImageCaptchaTrack.Track(x=182.0, y=-3.0, t=1602.0, type=move), ImageCaptchaTrack.Track(x=193.0, y=-3.0, t=1618.0, type=move), ImageCaptchaTrack.Track(x=206.0, y=-3.0, t=1635.0, type=move), ImageCaptchaTrack.Track(x=217.0, y=-3.0, t=1652.0, type=move), ImageCaptchaTrack.Track(x=218.0, y=-3.0, t=1668.0, type=move), ImageCaptchaTrack.Track(x=219.0, y=-3.0, t=1685.0, type=move), ImageCaptchaTrack.Track(x=220.0, y=-3.0, t=1701.0, type=move), ImageCaptchaTrack.Track(x=220.0, y=-4.0, t=1718.0, type=move), ImageCaptchaTrack.Track(x=221.0, y=-4.0, t=1735.0, type=move), ImageCaptchaTrack.Track(x=222.0, y=-4.0, t=1751.0, type=move), ImageCaptchaTrack.Track(x=221.0, y=-4.0, t=1835.0, type=move), ImageCaptchaTrack.Track(x=220.0, y=-4.0, t=2002.0, type=move), ImageCaptchaTrack.Track(x=218.0, y=-4.0, t=2018.0, type=move), ImageCaptchaTrack.Track(x=217.0, y=-3.0, t=2035.0, type=move), ImageCaptchaTrack.Track(x=218.0, y=-3.0, t=2369.0, type=move), ImageCaptchaTrack.Track(x=218.0, y=-3.0, t=2659.0, type=up)], data=null)

点选验证码参数

  1. 验证码的 ID:SLIDER_ff970847732c44859fb56935fab7f7c9
  2. 鼠标 move 的轨迹,一共记录 225 次
  3. 滑块从开始到结束的时间
ImageCaptchaTrack(bgImageWidth=300, bgImageHeight=180, templateImageWidth=null, templateImageHeight=null, startTime=Tue Sep 09 17:39:50 CST 2025, stopTime=Tue Sep 09 17:40:04 CST 2025, left=null, top=null, trackList=[ImageCaptchaTrack.Track(x=23.0, y=157.0, t=7061.0, type=click), ImageCaptchaTrack.Track(x=8.0, y=87.0, t=7133.0, type=move), ImageCaptchaTrack.Track(x=14.0, y=83.0, t=7142.0, type=move), ImageCaptchaTrack.Track(x=30.0, y=75.0, t=7159.0, type=move), ImageCaptchaTrack.Track(x=47.0, y=65.0, t=7176.0, type=move), ImageCaptchaTrack.Track(x=63.0, y=55.0, t=7193.0, type=move), ImageCaptchaTrack.Track(x=73.0, y=47.0, t=7209.0, type=move), ImageCaptchaTrack.Track(x=81.0, y=40.0, t=7226.0, type=move), ImageCaptchaTrack.Track(x=87.0, y=35.0, t=7243.0, type=move), ImageCaptchaTrack.Track(x=91.0, y=31.0, t=7259.0, type=move), ImageCaptchaTrack.Track(x=92.0, y=30.0, t=7276.0, type=move), ImageCaptchaTrack.Track(x=93.0, y=30.0, t=7293.0, type=move), ImageCaptchaTrack.Track(x=92.0, y=29.0, t=7454.0, type=move), ImageCaptchaTrack.Track(x=90.0, y=27.0, t=7461.0, type=move), ImageCaptchaTrack.Track(x=88.0, y=25.0, t=7476.0, type=move), ImageCaptchaTrack.Track(x=83.0, y=21.0, t=7493.0, type=move), ImageCaptchaTrack.Track(x=79.0, y=13.0, t=7509.0, type=move), ImageCaptchaTrack.Track(x=76.0, y=8.0, t=7526.0, type=move), ImageCaptchaTrack.Track(x=74.0, y=4.0, t=7543.0, type=move), ImageCaptchaTrack.Track(x=74.0, y=1.0, t=7560.0, type=move), ImageCaptchaTrack.Track(x=74.0, y=-1.0, t=7576.0, type=move), ImageCaptchaTrack.Track(x=74.0, y=-2.0, t=7593.0, type=move), ImageCaptchaTrack.Track(x=74.0, y=-4.0, t=7609.0, type=move), ImageCaptchaTrack.Track(x=78.0, y=-6.0, t=7626.0, type=move), ImageCaptchaTrack.Track(x=84.0, y=-10.0, t=7643.0, type=move), ImageCaptchaTrack.Track(x=91.0, y=-12.0, t=7660.0, type=move), ImageCaptchaTrack.Track(x=97.0, y=-12.0, t=7676.0, type=move), ImageCaptchaTrack.Track(x=106.0, y=-12.0, t=7693.0, type=move), ImageCaptchaTrack.Track(x=122.0, y=-8.0, t=7710.0, type=move), ImageCaptchaTrack.Track(x=129.0, y=-7.0, t=7726.0, type=move), ImageCaptchaTrack.Track(x=134.0, y=-7.0, t=7743.0, type=move), ImageCaptchaTrack.Track(x=137.0, y=-7.0, t=7760.0, type=move), ImageCaptchaTrack.Track(x=139.0, y=-7.0, t=7777.0, type=move), ImageCaptchaTrack.Track(x=141.0, y=-7.0, t=7793.0, type=move), ImageCaptchaTrack.Track(x=143.0, y=-8.0, t=7810.0, type=move), ImageCaptchaTrack.Track(x=144.0, y=-9.0, t=7826.0, type=move), ImageCaptchaTrack.Track(x=145.0, y=-10.0, t=7845.0, type=move), ImageCaptchaTrack.Track(x=145.0, y=-11.0, t=7894.0, type=move), ImageCaptchaTrack.Track(x=145.0, y=-12.0, t=7917.0, type=move), ImageCaptchaTrack.Track(x=146.0, y=-12.0, t=7934.0, type=move), ImageCaptchaTrack.Track(x=147.0, y=-12.0, t=7943.0, type=move), ImageCaptchaTrack.Track(x=154.0, y=-12.0, t=7960.0, type=move), ImageCaptchaTrack.Track(x=161.0, y=-13.0, t=7977.0, type=move), ImageCaptchaTrack.Track(x=166.0, y=-13.0, t=7993.0, type=move), ImageCaptchaTrack.Track(x=167.0, y=-13.0, t=8010.0, type=move), ImageCaptchaTrack.Track(x=168.0, y=-13.0, t=8027.0, type=move), ImageCaptchaTrack.Track(x=169.0, y=-13.0, t=8318.0, type=move), ImageCaptchaTrack.Track(x=170.0, y=-13.0, t=8327.0, type=move), ImageCaptchaTrack.Track(x=171.0, y=-13.0, t=8344.0, type=move), ImageCaptchaTrack.Track(x=172.0, y=-13.0, t=8365.0, type=move), ImageCaptchaTrack.Track(x=178.0, y=-11.0, t=8430.0, type=move), ImageCaptchaTrack.Track(x=182.0, y=-10.0, t=8444.0, type=move), ImageCaptchaTrack.Track(x=195.0, y=-7.0, t=8460.0, type=move), ImageCaptchaTrack.Track(x=210.0, y=-6.0, t=8477.0, type=move), ImageCaptchaTrack.Track(x=214.0, y=-5.0, t=8494.0, type=move), ImageCaptchaTrack.Track(x=214.0, y=-4.0, t=8549.0, type=move), ImageCaptchaTrack.Track(x=212.0, y=-4.0, t=8573.0, type=move), ImageCaptchaTrack.Track(x=208.0, y=-3.0, t=8581.0, type=move), ImageCaptchaTrack.Track(x=205.0, y=-3.0, t=8594.0, type=move), ImageCaptchaTrack.Track(x=198.0, y=-2.0, t=8611.0, type=move), ImageCaptchaTrack.Track(x=193.0, y=-2.0, t=8627.0, type=move), ImageCaptchaTrack.Track(x=190.0, y=-2.0, t=8644.0, type=move), ImageCaptchaTrack.Track(x=188.0, y=-2.0, t=8661.0, type=move), ImageCaptchaTrack.Track(x=186.0, y=-2.0, t=8677.0, type=move), ImageCaptchaTrack.Track(x=185.0, y=-2.0, t=8694.0, type=move), ImageCaptchaTrack.Track(x=192.0, y=-2.0, t=8744.0, type=move), ImageCaptchaTrack.Track(x=206.0, y=-2.0, t=8761.0, type=move), ImageCaptchaTrack.Track(x=221.0, y=-2.0, t=8778.0, type=move), ImageCaptchaTrack.Track(x=231.0, y=-2.0, t=8794.0, type=move), ImageCaptchaTrack.Track(x=236.0, y=-3.0, t=8811.0, type=move), ImageCaptchaTrack.Track(x=237.0, y=-3.0, t=8862.0, type=move), ImageCaptchaTrack.Track(x=238.0, y=-3.0, t=8885.0, type=move), ImageCaptchaTrack.Track(x=239.0, y=-4.0, t=8894.0, type=move), ImageCaptchaTrack.Track(x=240.0, y=-5.0, t=8911.0, type=move), ImageCaptchaTrack.Track(x=242.0, y=-6.0, t=8927.0, type=move), ImageCaptchaTrack.Track(x=243.0, y=-7.0, t=8944.0, type=move), ImageCaptchaTrack.Track(x=245.0, y=-9.0, t=8961.0, type=move), ImageCaptchaTrack.Track(x=246.0, y=-9.0, t=8978.0, type=move), ImageCaptchaTrack.Track(x=248.0, y=-10.0, t=8994.0, type=move), ImageCaptchaTrack.Track(x=251.0, y=-10.0, t=9011.0, type=move), ImageCaptchaTrack.Track(x=256.0, y=-10.0, t=9028.0, type=move), ImageCaptchaTrack.Track(x=260.0, y=-10.0, t=9044.0, type=move), ImageCaptchaTrack.Track(x=264.0, y=-10.0, t=9061.0, type=move), ImageCaptchaTrack.Track(x=265.0, y=-10.0, t=9078.0, type=move), ImageCaptchaTrack.Track(x=264.0, y=-9.0, t=9237.0, type=move), ImageCaptchaTrack.Track(x=279.0, y=60.0, t=9325.0, type=click), ImageCaptchaTrack.Track(x=263.0, y=-8.0, t=9382.0, type=move), ImageCaptchaTrack.Track(x=255.0, y=-6.0, t=9395.0, type=move), ImageCaptchaTrack.Track(x=240.0, y=-5.0, t=9412.0, type=move), ImageCaptchaTrack.Track(x=224.0, y=-5.0, t=9428.0, type=move), ImageCaptchaTrack.Track(x=210.0, y=-5.0, t=9445.0, type=move), ImageCaptchaTrack.Track(x=193.0, y=-5.0, t=9461.0, type=move), ImageCaptchaTrack.Track(x=187.0, y=-6.0, t=9478.0, type=move), ImageCaptchaTrack.Track(x=183.0, y=-7.0, t=9495.0, type=move), ImageCaptchaTrack.Track(x=180.0, y=-8.0, t=9511.0, type=move), ImageCaptchaTrack.Track(x=178.0, y=-8.0, t=9528.0, type=move), ImageCaptchaTrack.Track(x=177.0, y=-8.0, t=9545.0, type=move), ImageCaptchaTrack.Track(x=174.0, y=-9.0, t=9562.0, type=move), ImageCaptchaTrack.Track(x=172.0, y=-9.0, t=9578.0, type=move), ImageCaptchaTrack.Track(x=168.0, y=-10.0, t=9595.0, type=move), ImageCaptchaTrack.Track(x=166.0, y=-10.0, t=9612.0, type=move), ImageCaptchaTrack.Track(x=163.0, y=-12.0, t=9628.0, type=move), ImageCaptchaTrack.Track(x=162.0, y=-12.0, t=9646.0, type=move), ImageCaptchaTrack.Track(x=161.0, y=-12.0, t=9662.0, type=move), ImageCaptchaTrack.Track(x=160.0, y=-12.0, t=9694.0, type=move), ImageCaptchaTrack.Track(x=159.0, y=-12.0, t=9710.0, type=move), ImageCaptchaTrack.Track(x=158.0, y=-12.0, t=9745.0, type=move), ImageCaptchaTrack.Track(x=157.0, y=-12.0, t=9814.0, type=move), ImageCaptchaTrack.Track(x=172.0, y=57.0, t=9893.0, type=click), ImageCaptchaTrack.Track(x=155.0, y=-12.0, t=9974.0, type=move), ImageCaptchaTrack.Track(x=146.0, y=-12.0, t=9981.0, type=move), ImageCaptchaTrack.Track(x=135.0, y=-12.0, t=9995.0, type=move), ImageCaptchaTrack.Track(x=104.0, y=-12.0, t=10012.0, type=move), ImageCaptchaTrack.Track(x=81.0, y=-12.0, t=10029.0, type=move), ImageCaptchaTrack.Track(x=66.0, y=-12.0, t=10045.0, type=move), ImageCaptchaTrack.Track(x=69.0, y=-7.0, t=10126.0, type=move), ImageCaptchaTrack.Track(x=72.0, y=-2.0, t=10133.0, type=move), ImageCaptchaTrack.Track(x=74.0, y=3.0, t=10145.0, type=move), ImageCaptchaTrack.Track(x=82.0, y=15.0, t=10162.0, type=move), ImageCaptchaTrack.Track(x=90.0, y=26.0, t=10179.0, type=move), ImageCaptchaTrack.Track(x=98.0, y=35.0, t=10196.0, type=move), ImageCaptchaTrack.Track(x=107.0, y=44.0, t=10212.0, type=move), ImageCaptchaTrack.Track(x=112.0, y=49.0, t=10229.0, type=move), ImageCaptchaTrack.Track(x=122.0, y=56.0, t=10246.0, type=move), ImageCaptchaTrack.Track(x=129.0, y=61.0, t=10262.0, type=move), ImageCaptchaTrack.Track(x=134.0, y=66.0, t=10279.0, type=move), ImageCaptchaTrack.Track(x=137.0, y=70.0, t=10296.0, type=move), ImageCaptchaTrack.Track(x=138.0, y=71.0, t=10312.0, type=move), ImageCaptchaTrack.Track(x=138.0, y=72.0, t=10329.0, type=move), ImageCaptchaTrack.Track(x=137.0, y=72.0, t=10389.0, type=move), ImageCaptchaTrack.Track(x=135.0, y=72.0, t=10405.0, type=move), ImageCaptchaTrack.Track(x=133.0, y=72.0, t=10422.0, type=move), ImageCaptchaTrack.Track(x=132.0, y=71.0, t=10438.0, type=move), ImageCaptchaTrack.Track(x=131.0, y=70.0, t=10446.0, type=move), ImageCaptchaTrack.Track(x=130.0, y=69.0, t=10462.0, type=move), ImageCaptchaTrack.Track(x=129.0, y=68.0, t=10479.0, type=move), ImageCaptchaTrack.Track(x=130.0, y=68.0, t=10589.0, type=move), ImageCaptchaTrack.Track(x=130.0, y=69.0, t=10629.0, type=move), ImageCaptchaTrack.Track(x=130.0, y=70.0, t=10654.0, type=move), ImageCaptchaTrack.Track(x=130.0, y=71.0, t=10663.0, type=move), ImageCaptchaTrack.Track(x=130.0, y=72.0, t=10765.0, type=move), ImageCaptchaTrack.Track(x=128.0, y=74.0, t=10813.0, type=move), ImageCaptchaTrack.Track(x=122.0, y=74.0, t=10829.0, type=move), ImageCaptchaTrack.Track(x=114.0, y=72.0, t=10846.0, type=move), ImageCaptchaTrack.Track(x=107.0, y=69.0, t=10863.0, type=move), ImageCaptchaTrack.Track(x=101.0, y=64.0, t=10880.0, type=move), ImageCaptchaTrack.Track(x=97.0, y=62.0, t=10896.0, type=move), ImageCaptchaTrack.Track(x=92.0, y=58.0, t=10913.0, type=move), ImageCaptchaTrack.Track(x=89.0, y=55.0, t=10930.0, type=move), ImageCaptchaTrack.Track(x=86.0, y=52.0, t=10946.0, type=move), ImageCaptchaTrack.Track(x=83.0, y=51.0, t=10963.0, type=move), ImageCaptchaTrack.Track(x=82.0, y=50.0, t=10980.0, type=move), ImageCaptchaTrack.Track(x=82.0, y=49.0, t=10998.0, type=move), ImageCaptchaTrack.Track(x=81.0, y=49.0, t=11046.0, type=move), ImageCaptchaTrack.Track(x=79.0, y=48.0, t=11063.0, type=move), ImageCaptchaTrack.Track(x=76.0, y=46.0, t=11080.0, type=move), ImageCaptchaTrack.Track(x=74.0, y=45.0, t=11096.0, type=move), ImageCaptchaTrack.Track(x=71.0, y=43.0, t=11113.0, type=move), ImageCaptchaTrack.Track(x=71.0, y=44.0, t=11190.0, type=move), ImageCaptchaTrack.Track(x=73.0, y=47.0, t=11197.0, type=move), ImageCaptchaTrack.Track(x=77.0, y=52.0, t=11213.0, type=move), ImageCaptchaTrack.Track(x=80.0, y=57.0, t=11230.0, type=move), ImageCaptchaTrack.Track(x=82.0, y=60.0, t=11247.0, type=move), ImageCaptchaTrack.Track(x=82.0, y=62.0, t=11264.0, type=move), ImageCaptchaTrack.Track(x=83.0, y=62.0, t=11293.0, type=move), ImageCaptchaTrack.Track(x=81.0, y=62.0, t=11382.0, type=move), ImageCaptchaTrack.Track(x=78.0, y=61.0, t=11398.0, type=move), ImageCaptchaTrack.Track(x=74.0, y=58.0, t=11413.0, type=move), ImageCaptchaTrack.Track(x=70.0, y=56.0, t=11430.0, type=move), ImageCaptchaTrack.Track(x=69.0, y=55.0, t=11447.0, type=move), ImageCaptchaTrack.Track(x=67.0, y=53.0, t=11464.0, type=move), ImageCaptchaTrack.Track(x=66.0, y=52.0, t=11480.0, type=move), ImageCaptchaTrack.Track(x=64.0, y=52.0, t=11497.0, type=move), ImageCaptchaTrack.Track(x=64.0, y=51.0, t=11514.0, type=move), ImageCaptchaTrack.Track(x=63.0, y=50.0, t=11530.0, type=move), ImageCaptchaTrack.Track(x=62.0, y=48.0, t=11547.0, type=move), ImageCaptchaTrack.Track(x=61.0, y=46.0, t=11564.0, type=move), ImageCaptchaTrack.Track(x=60.0, y=44.0, t=11581.0, type=move), ImageCaptchaTrack.Track(x=58.0, y=43.0, t=11597.0, type=move), ImageCaptchaTrack.Track(x=59.0, y=43.0, t=11846.0, type=move), ImageCaptchaTrack.Track(x=60.0, y=42.0, t=11853.0, type=move), ImageCaptchaTrack.Track(x=61.0, y=42.0, t=11864.0, type=move), ImageCaptchaTrack.Track(x=62.0, y=42.0, t=11881.0, type=move), ImageCaptchaTrack.Track(x=62.0, y=41.0, t=11898.0, type=move), ImageCaptchaTrack.Track(x=63.0, y=41.0, t=11914.0, type=move), ImageCaptchaTrack.Track(x=62.0, y=40.0, t=12485.0, type=move), ImageCaptchaTrack.Track(x=61.0, y=39.0, t=12533.0, type=move), ImageCaptchaTrack.Track(x=67.0, y=41.0, t=13014.0, type=move), ImageCaptchaTrack.Track(x=80.0, y=43.0, t=13022.0, type=move), ImageCaptchaTrack.Track(x=95.0, y=46.0, t=13032.0, type=move), ImageCaptchaTrack.Track(x=133.0, y=52.0, t=13048.0, type=move), ImageCaptchaTrack.Track(x=167.0, y=57.0, t=13065.0, type=move), ImageCaptchaTrack.Track(x=208.0, y=61.0, t=13082.0, type=move), ImageCaptchaTrack.Track(x=240.0, y=63.0, t=13099.0, type=move), ImageCaptchaTrack.Track(x=265.0, y=63.0, t=13115.0, type=move), ImageCaptchaTrack.Track(x=279.0, y=63.0, t=13132.0, type=move), ImageCaptchaTrack.Track(x=283.0, y=62.0, t=13149.0, type=move), ImageCaptchaTrack.Track(x=283.0, y=61.0, t=13166.0, type=move), ImageCaptchaTrack.Track(x=283.0, y=60.0, t=13190.0, type=move), ImageCaptchaTrack.Track(x=283.0, y=59.0, t=13198.0, type=move), ImageCaptchaTrack.Track(x=283.0, y=57.0, t=13215.0, type=move), ImageCaptchaTrack.Track(x=283.0, y=55.0, t=13232.0, type=move), ImageCaptchaTrack.Track(x=281.0, y=50.0, t=13249.0, type=move), ImageCaptchaTrack.Track(x=277.0, y=46.0, t=13266.0, type=move), ImageCaptchaTrack.Track(x=274.0, y=41.0, t=13282.0, type=move), ImageCaptchaTrack.Track(x=267.0, y=37.0, t=13299.0, type=move), ImageCaptchaTrack.Track(x=263.0, y=35.0, t=13315.0, type=move), ImageCaptchaTrack.Track(x=260.0, y=34.0, t=13332.0, type=move), ImageCaptchaTrack.Track(x=259.0, y=34.0, t=13349.0, type=move), ImageCaptchaTrack.Track(x=256.0, y=34.0, t=13366.0, type=move), ImageCaptchaTrack.Track(x=253.0, y=34.0, t=13382.0, type=move), ImageCaptchaTrack.Track(x=249.0, y=35.0, t=13399.0, type=move), ImageCaptchaTrack.Track(x=243.0, y=36.0, t=13416.0, type=move), ImageCaptchaTrack.Track(x=240.0, y=37.0, t=13432.0, type=move), ImageCaptchaTrack.Track(x=237.0, y=37.0, t=13449.0, type=move), ImageCaptchaTrack.Track(x=235.0, y=37.0, t=13465.0, type=move), ImageCaptchaTrack.Track(x=231.0, y=37.0, t=13482.0, type=move), ImageCaptchaTrack.Track(x=227.0, y=37.0, t=13499.0, type=move), ImageCaptchaTrack.Track(x=224.0, y=37.0, t=13516.0, type=move), ImageCaptchaTrack.Track(x=220.0, y=37.0, t=13532.0, type=move), ImageCaptchaTrack.Track(x=217.0, y=37.0, t=13549.0, type=move), ImageCaptchaTrack.Track(x=212.0, y=37.0, t=13566.0, type=move), ImageCaptchaTrack.Track(x=209.0, y=37.0, t=13582.0, type=move), ImageCaptchaTrack.Track(x=207.0, y=37.0, t=13599.0, type=move), ImageCaptchaTrack.Track(x=222.0, y=106.0, t=13758.0, type=click)], data=null)

简单校验

概述:

  • 提供点击式验证码和滑动式验证码的验证机制
  • 通过位置百分比计算和容忍度判断,验证用户操作的准确性
  • 支持存储验证过程中的关键数据(目标值、实际值、偏差等)

点击验证码校验:

  1. 提取预设目标点信息(格式为 "x%,y%;x%,y%")
  2. 从轨迹中筛选出点击类型(CLICK)的轨迹点
  3. 两种验证模式:
    1. 有序验证:按顺序匹配点击轨迹与目标点
    2. 无序验证:不限制顺序,只要每个目标点都有匹配的点击
  4. 通过百分比计算(相对背景图尺寸)和容忍度判断位置是否匹配

滑块验证码校验:

  1. 提取预设的目标滑动百分比
  2. 计算实际滑动距离(终点 X 坐标 - 起点 X 坐标)
  3. 将实际滑动距离转换为相对于背景图宽度的百分比
  4. 校验实际百分比与目标百分比是否在容忍范围内
 public boolean doValidClickCaptcha(ImageCaptchaTrack imageCaptchaTrack,
                                       AnyMap imageCaptchaValidData,
                                       Float tolerant,
                                       String type) {
        String validStr = imageCaptchaValidData.getString(PERCENTAGE_KEY, null);
        Object checkOrder = imageCaptchaValidData.getOrDefault(CLICK_IMAGE_CHECK_ORDER_KEY, true);
        if (ObjectUtils.isEmpty(validStr)) {
            return false;
        }
        String[] splitArr = validStr.split(";");
        List<ImageCaptchaTrack.Track> trackList = imageCaptchaTrack.getTrackList();
        if (trackList.size() < splitArr.length) {
            return false;
        }
        // 取出点击事件的轨迹数据
        List<ImageCaptchaTrack.Track> clickTrackList = trackList
                .stream()
                .filter(t -> TrackTypeConstant.CLICK.equalsIgnoreCase(t.getType()))
                .collect(Collectors.toList());
        if (clickTrackList.size() != splitArr.length) {
            return false;
        }
        StringBuilder sb = new StringBuilder();
        List<Double> percentages = new ArrayList<>();
        for (int i = 0; i < splitArr.length; i++) {
            String posStr = splitArr[i];
            String[] posArr = posStr.split(",");
            float xPercentage = Float.parseFloat(posArr[0]);
            float yPercentage = Float.parseFloat(posArr[1]);
            float calcXPercentage = 0f;
            float calcYPercentage = 0f;
            if (Boolean.TRUE.equals(checkOrder)) {
                ImageCaptchaTrack.Track track = clickTrackList.get(0);
                calcXPercentage = calcPercentage(track.getX(), imageCaptchaTrack.getBgImageWidth());
                calcYPercentage = calcPercentage(track.getY(), imageCaptchaTrack.getBgImageHeight());
                if (!checkPercentage(calcXPercentage, xPercentage, tolerant)
                        || !checkPercentage(calcYPercentage, yPercentage, tolerant)) {
                    return false;
                }
                clickTrackList.remove(0);
            } else {
                boolean flag = false;
                for (int a = 0; a < clickTrackList.size(); a++) {
                    ImageCaptchaTrack.Track track = clickTrackList.get(a);
                    calcXPercentage = calcPercentage(track.getX(), imageCaptchaTrack.getBgImageWidth());
                    calcYPercentage = calcPercentage(track.getY(), imageCaptchaTrack.getBgImageHeight());
                    if (checkPercentage(calcXPercentage, xPercentage, tolerant)
                            && checkPercentage(calcYPercentage, yPercentage, tolerant)) {
                        // 验证命中
                        clickTrackList.remove(a);
                        flag = true;
                        break;
                    }
                }
                if (!flag) {
                    return false;
                }
            }
            if (i > 0) {
                sb.append("|");
            }
            sb.append(calcXPercentage).append(",").append(calcYPercentage);
            percentages.add((double) ((calcXPercentage - xPercentage) + (calcYPercentage - yPercentage)));
        }
        // 存储一下当前计算出来的值
        return true;
    }

    public boolean doValidSliderCaptcha(ImageCaptchaTrack imageCaptchaTrack,
                                        AnyMap imageCaptchaValidData,
                                        Float tolerant,
                                        String type) {
        Float oriPercentage = imageCaptchaValidData.getFloat(PERCENTAGE_KEY);
        if (oriPercentage == null) {
            // 没读取到百分比
            return false;
        }
        List<ImageCaptchaTrack.Track> trackList = imageCaptchaTrack.getTrackList();
        ImageCaptchaTrack.Track firstTrack = trackList.get(0);
        // 取最后一个滑动轨迹
        ImageCaptchaTrack.Track lastTrack = trackList.get(trackList.size() - 1);
        // 计算百分比
        float calcPercentage = calcPercentage(lastTrack.getX() - firstTrack.getX(), imageCaptchaTrack.getBgImageWidth());
        // 校验百分比
        boolean percentage = checkPercentage(calcPercentage, oriPercentage, tolerant);
        if (percentage) {
            // 校验成功
            // 存储一下当前计算出来的值
            imageCaptchaValidData.put(USER_CURRENT_PERCENTAGE, String.valueOf(calcPercentage));
            imageCaptchaValidData.put(USER_CURRENT_PERCENTAGE_STD, String.valueOf(calcPercentage - oriPercentage));
        }
        return percentage;
    }

    protected void addPercentage(ImageCaptchaInfo imageCaptchaInfo, AnyMap imageCaptchaValidData) {
        float percentage = calcPercentage(imageCaptchaInfo.getRandomX(), imageCaptchaInfo.getBackgroundImageWidth());
        imageCaptchaValidData.put(PERCENTAGE_KEY, percentage);
    }
}

复杂轨迹校验

// 遍历轨迹列表
Iterator var2 = imageCaptchaTrack.getTrackList().iterator();
do {
    if (!var2.hasNext()) {
        return; // 所有轨迹点都校验通过
    }
    ImageCaptchaTrack.Track track = (ImageCaptchaTrack.Track)var2.next();
    x = track.getX();      // X坐标
    y = track.getY();      // Y坐标
    t = track.getT();      // 时间戳
    type = track.getType();// 轨迹类型
// 只要有一个轨迹点的任何属性为空,就抛出异常
} while(x != null && y != null && t != null && !ObjectUtils.isEmpty(type));

throw new IllegalArgumentException("track[x,y,t,type] must not be null");

根据上文获取到的坐标行为轨迹,做的校验:

  1. 滑动时间验证:检查滑动开始到结束的时间是否过短(小于 300 毫秒)
  2. 轨迹点数量验证:轨迹点数量需满足 10 ≤ 数量 ≤ 背景图宽度×5,太少(<10)可能是简单脚本,太多(> 宽度 ×5)可能是异常数据。
  3. 初始位置验证:x 轴和 y 轴应该是从 0 开始的,要是一开始 x 轴和 y 轴乱跑,返回 false
  4. 轨迹连续性与合理性验证:
  • 相邻轨迹点的 X 或 Y 方向位移不能超过 50 像素(防止瞬间跳变,真人滑动有速度限制);
  • 统计 Y 坐标不变的点(机器可能水平匀速滑动,真人难免有上下波动);
  • 统计 X 坐标超出背景图宽度的点(正常滑动不会越界,过多越界点为异常)
  1. 滑动速度变化验证:
  • 验证逻辑:对比滑动过程中前 70% 轨迹与后 30% 轨迹的平均时间间隔。
  • 判断标准:真人滑动通常越到后期速度越快(后 30% 平均时间间隔 > 前 70%),若不符合此特征(如匀速或减速),则判定为异常。
public ApiResponse<?> afterValid(Boolean basicValid, ImageCaptchaTrack imageCaptchaTrack, AnyMap captchaValidData, Float tolerant, String type) {
    // 如果基础验证未通过,直接返回成功(无需二次验证)
if (!basicValid) {
    return ApiResponse.ofSuccess();
// 如果不是滑块验证码类型,直接返回成功(无需验证)
} else if (!CaptchaTypeClassifier.isSliderCaptcha(type)) {
    return ApiResponse.ofSuccess();
}
long startSlidingTime = imageCaptchaTrack.getStartTime().getTime(); // 滑动开始时间
long endSlidingTime = imageCaptchaTrack.getStopTime().getTime();   // 滑动结束时间
Integer bgImageWidth = imageCaptchaTrack.getBgImageWidth();        // 背景图宽度
List<ImageCaptchaTrack.Track> trackList = imageCaptchaTrack.getTrackList(); // 滑动轨迹点列表
// 如果滑动时间小于300毫秒(太快),判定为机器操作
if (startSlidingTime + 300L > endSlidingTime) {
    return ApiResponse.ofMessage(DEFINITION);
}
// 轨迹点数量需在 [10, 背景图宽度*5] 范围内
else if (trackList.size() >= 10 && trackList.size() <= bgImageWidth * 5) {
    // 轨迹点数量合理,进入下一步验证
} else {
    // 轨迹点太少(<10)或太多(>宽度*5),判定为异常
    return ApiResponse.ofMessage(DEFINITION);
}
ImageCaptchaTrack.Track firstTrack = trackList.get(0); // 第一个轨迹点
// 检查初始位置是否在 [(-10,-10), (10,10)] 范围内(接近起点)
if (!(firstTrack.getX() > 10.0F) && !(firstTrack.getX() < -10.0F) && 
    !(firstTrack.getY() > 10.0F) && !(firstTrack.getY() < -10.0F)) {
    // 初始位置合理,进入下一步验证
} else {
    // 初始位置偏离起点过远,判定为异常
    return ApiResponse.ofMessage(DEFINITION);
}
int check4 = 0; // 记录Y坐标与初始Y相同的轨迹点数量
int check7 = 0; // 记录X坐标超出背景图宽度的轨迹点数量

for(i = 1; i < trackList.size(); ++i) {
    track = trackList.get(i);
    x = track.getX();
    y = track.getY();

    // 统计Y坐标未变化的点(机器可能水平滑动,Y值不变)
    if (firstTrack.getY() == y) {
        ++check4;
    }

    // 统计X坐标超出背景图宽度的点(异常越界)
    if (x >= bgImageWidth) {
        ++check7;
    }

    // 检查相邻轨迹点的位移是否过大(单次移动>50像素)
    preTrack = trackList.get(i - 1);
    if (track.getX() - preTrack.getX() > 50.0F || 
        track.getY() - preTrack.getY() > 50.0F) {
        return ApiResponse.ofMessage(DEFINITION); // 位移过大,判定为异常
    }
}
// 条件1:Y坐标不变的点数量≠总轨迹点数量(排除完全水平滑动)
// 条件2:越界点数量≤200(允许少量异常,但不能过多)
if (check4 != trackList.size() && check7 <= 200) {
    // 取轨迹的前70%和后30%,计算两段的平均时间间隔
    int i = (int)(trackList.size() * 0.7);
    ImageCaptchaTrack.Track track70 = trackList.get(i - 1);
    float avgTimeFirst70 = track70.getT() / i; // 前70%轨迹的平均时间

    ImageCaptchaTrack.Track lastTrack = trackList.get(trackList.size() - 1);
    double avgTimeLast30 = lastTrack.getT() / (trackList.size() - i); // 后30%轨迹的平均时间

    // 真人滑动通常会越到后面越快(平均时间间隔增大)
    if (avgTimeLast30 > avgTimeFirst70) {
        return ApiResponse.ofSuccess(); // 符合真人特征,验证通过
    } else {
        return ApiResponse.ofMessage(DEFINITION); // 速度变化异常,验证失败
    }
} else {
    return ApiResponse.ofMessage(DEFINITION); // 异常点比例过高,验证失败
}
}
~  ~  The   End  ~  ~


 赏 
承蒙厚爱,倍感珍贵,我会继续努力哒!
logo图像
tips
(*) 8 + 6 =
快来做第一个评论的人吧~