收藏
回答

微信小程序可以用thinkphp的验证码类库captcha来做图形验证码吗

框架类型 问题类型 操作时间 AppID
小程序 Bug 2018-07-18 wx387f2da5e8802ac2

楼主菜鸡一枚,最近有在学习thinkphp,看到有个图形验证码的类库captcha,故想尝试用在小程序中。

小程序wxml代码如下:

<!--pages/test/test.wxml-->

<form bindsubmit="formsubmit">

<input name="code" placeholder="请输入验证码" style="border:1px solid black"/>

<image onload="imageload" src="{{captchaImage}}" style="width:200px;height:88px;" ></image>

<button form-type="submit">提交</button>

</form >

js代码如下:

// pages/test/test.js

Page({

data: {

captchaImage:'https://www.st1207.com/captcha'   //验证码图片地址

},

formsubmit: function (e) {

    console.log(e.detail.value);

    var that=this;

    wx.request({

        url: "https://www.st1207.com/api/v3.captcha/index",   //服务器验证地址

        method:"GET",

        data:e.detail.value,

        success: function (res) {

            console.log(res.data);

        },

        fail: function (err) {

        console.log(err);

        }

    })

},

})

服务器代码如下

<?php

namespace app\api\controller\v3;

use think\Controller;

use think\captcha\Captcha as Cap;

class Captcha extends  Controller{

    public function index($code=''){

        $captcha=new Cap;

    if(!$captcha->check($code)){

        return '验证失败'.$code;

    }else{

        return '验证成功'.$code;

    }

    }

}

?>


代码完成,开始测试,虽然验证码可以正常显示,但是提交表单进行验证的时候总是提示验证失败。



各种网络搜索查找资料,才发现thinkphp是用Session来储存验证码的。而小程序不支持主动保存cookie,更不会在request header中发送cookie。导致小程序每次向服务器发送请求的时候,SESSIONID都会发生变化,所以永远都不会验证成功。


思考解决办法:手动保存服务器response header中的sessionid,再向服务器发送验证请求的时候,在wx.request中手动添加header:{'cookie':'PHPSESSID=...' }.

  1. 查看以上代码,小程序第一次向服务器发送请求是在<image>组件加载服务器验证码图片的时候,此时没有办法获得response header。所以也就不能手动保存。

  2. 再想办法 :<image>组件的src 不直接使用服务器的图形验证码地址,先在onload事件中通过wx,request或者wx.downloadFile请求服务器https://www.st1207.com/captcha, 获得response header和图片信息再通过js的data 让小程序来显示。

  3. 查看wx.request 的回调函数success:function(res){ }

    有response header,可以获得sessionID 为  res.header['Set-Cookie'],但是返回的res.data确是一堆乱码,无法来让<image>组件进行显示

  4. 查看wx.downloadFile 的回调函数虽然可以把图片下载下来进行显示,但是并不能获得response header。


作为一名菜鸟,不知道有没有表达的清楚,请各位大神帮忙看看还有没有其他办法。

回答关注问题邀请回答
收藏

5 个回答

  • 2018-07-25

    已经真机测试通过,可以加qq讨论:974353437

    const app = getApp()
     
    Page({
      data: {
        imgUrl: '',
        result:''
      },
      onLoad() {
        this.initCaptcha();
      },
      initCaptcha() {
        let url = 'http://192.168.0.119:15539/Captcha/Index';
        wx.request({
          header: app.globalData.header,
          url,
          data:{},
          success: (res) => {
            this.setSessionId(res);
            this.downloadCaptcha();
          }
        })
      },
      downloadCaptcha(){
        let url = 'http://192.168.0.119:15539/Captcha/Generate?' + new Date().getTime();
        wx.downloadFile({
          header: app.globalData.header,
          url,
          success: (res) => {
            console.log(res);
            this.setData({
              imgUrl:res.tempFilePath
            });
          }
        })
      },
      refreshCaptcha() {
        this.initCaptcha();
      },
     
      setSessionId(res) {
        let cookieStr = res.header['Set-Cookie'];
        // app.globalData.header.Cookie = cookieStr;
        if (cookieStr){
          let cookies = cookieStr.split('; ')
     
          if (!cookies || cookies.length <= 0)
            return;
     
          cookies.forEach(
            (v) => {
              const str = v.split('=');
              if (str[0] && str[0] == 'ASP.NET_SessionId') {
                let sessionId = decodeURI(str[1]);
                app.globalData.header.Cookie = `ASP.NET_SessionId=${sessionId}`;
              }
            }
          );
        }
     
      },
     
      onSubmit(e){
        let { code } = e.detail.value;
        let url = 'http://192.168.0.119:15539/Captcha/Validate';
        wx.request({
          header: app.globalData.header,
          url,
          data: {code},
          success: (res) => {
            console.log(res);
            this.initCaptcha();
     
            this.setData({
              result:res.data.message
            })
          }
        })
      }
    })



    wxml

    <!--index.wxml-->
    <form bind:submit="onSubmit" class="form">
      <input placeholder='请输入验证码' name="code" />
      <image bindtap="refreshCaptcha" src="{{imgUrl}}" mode="cover" style="width:100px;height:50px"></image>
      <button formType="submit">验证</button>
      <view>操作结果:{{result}}</view>
    </form>


    2018-07-25
    有用 1
    回复 3
    • $威-
      $威-
      2018-09-08

      app.globalData.header.Cookie  这儿的 Cookie 显示未定义

      2018-09-08
      回复
    • $威-
      $威-
      2018-09-08回复$威-

      项目入口文件 app.js 增加下面代码.


      globalData: {
          userInfo: null,
          header: {
              'Cookie': ''
          }
           
      },


      如果是PHP程序, 将上面的 ASP.NET_SessionId  替换成 PHPSESSID

      2018-09-08
      回复
    • ୯嘿⃰୬
      ୯嘿⃰୬
      2021-09-15
      你是真牛逼啊我的哥,太猛了,我一直只想到通过sessionid去获取session,结果忘了头信息,你是真牛逼啊哥
      2021-09-15
      回复
  • panqi
    panqi
    2023-06-08
    uni.request({
        url: this.urlTimestamp, // 加上时间戳的验证码地址
        responseType: 'arraybuffer'
    })
    .then(res => {
        const [, {
            data,
            cookies,
            header
        }] = res;
        const base64Url = 'data:image/png;base64,' + uni.arrayBufferToBase64(data);
    
    
        console.log(data, cookies, header); // cookies/header 中都可以取到SESSIONID
        this.captchaUrl = base64Url; // base64用于展示
    });
    
    
    2023-06-08
    有用
    回复
  • ,,,
    ,,,
    2020-01-13

    前面一切正常,提交审核时候https请求验证码图片和token,tempFilePath返回的http的图片地址无法显示.

    2020-01-13
    有用
    回复
  • 谢凯
    谢凯
    2018-09-06

    恩,不嫌麻烦的话可以多写一次请求。

    第一次请求用wx.request,把返回的sessionid存起来,返回的二进制流图片数据不要管它(我目前不知道怎么放到image里)。

    第二次请求用过wx.downloadFile,在请求header里面加上你之前存起来的sessionid,把返回的tempFilePath临时文件地址放到image里显示。

    第三次用wx.request,header带上你的sessionid,进行验证。

    2018-09-06
    有用
    回复 2
    • Hasaki
      Hasaki
      2020-01-13
      ...这样不是浪费资源嘛,
      2020-01-13
      回复
    • panqi
      panqi
      2023-06-08
      试试我的方法,贴在下面了
      2023-06-08
      回复
  • 李良山
    李良山
    2018-07-18

    将验证码的sessionid和openid绑定,判断时读取当前openid绑定的sessionid的session

    2018-07-18
    有用
    回复
登录 后发表内容