ThinkPHP V6.0.12在php8.1下驗證碼出現問題

来源:https://www.cnblogs.com/zhangxilong/archive/2022/05/11/16257933.html
-Advertisement-
Play Games

一、問題描述 1、項目需求要求使用PHP8.1.*版本 2、運行程式發現驗證碼不生效報錯如下: 二、錯誤描述 1、報錯信息得出:從浮點(數字)到整數的隱式轉換將失去精度 三、解決流程 1、找到報錯文件位置 vendor\topthink\think-captcha\src\Captcha.php l ...


一、問題描述

1、項目需求要求使用PHP8.1.*版本

2、運行程式發現驗證碼不生效報錯如下:

二、錯誤描述

1、報錯信息得出:從浮點(數字)到整數的隱式轉換將失去精度

三、解決流程

1、找到報錯文件位置

vendor\topthink\think-captcha\src\Captcha.php line 309

2、發現是第309行報錯,將代碼改成以下內容(也可直接替換)

    /**
     * 畫雜點
     * 往圖片上寫不同顏色的字母或數字
     */
    protected function writeNoise(): void
    {
        $codeSet = '2345678abcdefhijkmnpqrstuvwxyz';
        for ($i = 0; $i < 10; $i++) {
            //雜點顏色
            $noiseColor = imagecolorallocate($this->im, mt_rand(150, 225), mt_rand(150, 225), mt_rand(150, 225));
            for ($j = 0; $j < 5; $j++) {
                // 繪雜點
                imagestring($this->im, 5, mt_rand(-10, (int) $this->imageW), mt_rand(-10, (int)$this->imageH), $codeSet[mt_rand(0, 29)], $noiseColor);
            }
        }
    }

3、此時刷新頁面發現了新的報錯信息(意思基本相同):

4、搜索(writeCurve)方法直接替換:

/**
     * 畫一條由兩條連在一起構成的隨機正弦函數曲線作干擾線(你可以改成更帥的曲線函數)
     *
     *      高中的數學公式咋都忘了涅,寫出來
     *        正弦型函數解析式:y=Asin(ωx+φ)+b
     *      各常數值對函數圖像的影響:
     *        A:決定峰值(即縱向拉伸壓縮的倍數)
     *        b:表示波形在Y軸的位置關係或縱向移動距離(上加下減)
     *        φ:決定波形與X軸位置關係或橫向移動距離(左加右減)
     *        ω:決定周期(最小正周期T=2π/∣ω∣)
     *
     */
    protected function writeCurve(): void
    {
        $px = $py = 0;

        // 曲線前部分
        $A = mt_rand(1, (int) $this->imageH / 2); // 振幅
        $b = mt_rand(-intval($this->imageH / 4), intval($this->imageH / 4)); // Y軸方向偏移量
        $f = mt_rand(-intval($this->imageH / 4), intval($this->imageH / 4)); // X軸方向偏移量
        $T = mt_rand((int) $this->imageH, intval($this->imageW * 2)); // 周期
        $w = (2 * M_PI) / $T;

        $px1 = 0; // 曲線橫坐標起始位置
        $px2 = mt_rand($this->imageW / 2, $this->imageW * 0.8); // 曲線橫坐標結束位置

        for ($px = $px1; $px <= $px2; $px = $px + 1) {
            if (0 != $w) {
                $py = $A * sin($w * $px + $f) + $b + $this->imageH / 2; // y = Asin(ωx+φ) + b
                $i  = (int) ($this->fontSize / 5);
                while ($i > 0) {
                    imagesetpixel($this->im, (int) $px + $i, (int) $py + $i, $this->color); // 這裡(while)迴圈畫像素點比imagettftext和imagestring用字體大小一次畫出(不用這while迴圈)性能要好很多
                    $i--;
                }
            }
        }

        // 曲線後部分
        $A   = mt_rand(1, intval($this->imageH / 2)); // 振幅
        $f   = mt_rand(-intval($this->imageH / 4), intval($this->imageH / 4)); // X軸方向偏移量
        $T   = mt_rand((int) $this->imageH, intval($this->imageW * 2)); // 周期
        $w   = (2 * M_PI) / $T;
        $b   = $py - $A * sin($w * $px + $f) - $this->imageH / 2;
        $px1 = $px2;
        $px2 = $this->imageW;

        for ($px = $px1; $px <= $px2; $px = $px + 1) {
            if (0 != $w) {
                $py = $A * sin($w * $px + $f) + $b + $this->imageH / 2; // y = Asin(ωx+φ) + b
                $i  = (int) ($this->fontSize / 5);
                while ($i > 0) {
                    imagesetpixel($this->im, (int) $px + $i, (int) $py + $i, $this->color);
                    $i--;
                }
            }
        }
    }

5、最後一步,搜索(create)方法直接替換:

 /**
     * 輸出驗證碼並把驗證碼的值保存的session中
     * @access public
     * @param null|string $config
     * @param bool        $api
     * @return Response
     */
    public function create(string $config = null, bool $api = false): Response
    {
        $this->configure($config);

        $generator = $this->generate();

        // 圖片寬(px)
        $this->imageW || $this->imageW = $this->length * $this->fontSize * 1.5 + $this->length * $this->fontSize / 2;
        // 圖片高(px)
        $this->imageH || $this->imageH = $this->fontSize * 2.5;
        // 建立一幅 $this->imageW x $this->imageH 的圖像
        $this->im = imagecreate((int) $this->imageW, (int) $this->imageH);
        // 設置背景
        imagecolorallocate($this->im, $this->bg[0], $this->bg[1], $this->bg[2]);

        // 驗證碼字體隨機顏色
        $this->color = imagecolorallocate($this->im, mt_rand(1, 150), mt_rand(1, 150), mt_rand(1, 150));

        // 驗證碼使用隨機字體
        $ttfPath = __DIR__ . '/../assets/' . ($this->useZh ? 'zhttfs' : 'ttfs') . '/';

        if (empty($this->fontttf)) {
            $dir  = dir($ttfPath);
            $ttfs = [];
            while (false !== ($file = $dir->read())) {
                if ('.' != $file[0] && substr($file, -4) == '.ttf') {
                    $ttfs[] = $file;
                }
            }
            $dir->close();
            $this->fontttf = $ttfs[array_rand($ttfs)];
        }

        $fontttf = $ttfPath . $this->fontttf;

        if ($this->useImgBg) {
            $this->background();
        }

        if ($this->useNoise) {
            // 繪雜點
            $this->writeNoise();
        }
        if ($this->useCurve) {
            // 繪干擾線
            $this->writeCurve();
        }

        // 繪驗證碼
        $text = $this->useZh ? preg_split('/(?<!^)(?!$)/u', $generator['value']) : str_split($generator['value']); // 驗證碼

        foreach ($text as $index => $char) {

            $x     = $this->fontSize * ($index + 1) * mt_rand((int) 1.2, (int) 1.6) * ($this->math ? 1 : 1.5);
            $y     = $this->fontSize + mt_rand(10, 20);
            $angle = $this->math ? 0 : mt_rand(-40, 40);

            imagettftext($this->im, $this->fontSize, $angle, (int) $x, (int) $y, $this->color, $fontttf, $char);
        }

        ob_start();
        // 輸出圖像
        imagepng($this->im);
        $content = ob_get_clean();
        imagedestroy($this->im);

        return response($content, 200, ['Content-Length' => strlen($content)])->contentType('image/png');
    }

 

說明:以上是按照報錯信息依次修改;如有大佬有更好的解決辦法歡迎評論留言


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 跟著教程寫了幾種方法,才發現自己寫的雖然能實現,但比較繁瑣。教程有三種方法: 1.移位法,每次左移一位,相比我自己寫的,優點是不用把每一種情況都寫出來。但是需要考慮左移到最後一位時需要自己再寫個賦值語句重新回到第一位。 2.位拼接法,迴圈左移,每一次都把最後一位放到第一位,其他六位左移一位,剋服了移 ...
  • JUC自定義線程池練習 首先上面該線程池的大致流程 自定義阻塞隊列 首先定義一個雙向的隊列和鎖一定兩個等待的condition 本類用lock來控制多線程下的流程執行 take和push方法就是死等,調用await就是等,後面優化為限時等待 take調用後取出阻塞隊列的task後會調用fullWai ...
  • Google支付Java服務端訂單校驗 原文鏈接:https://blog.csdn.net/qq_40193787/article/details/123507578 一、Google Play 結算系統概覽 Google Play 結算系統是一項可讓您在 Android 應用中銷售數字產品和內容 ...
  • 前言 現如今,視頻!每個人飯後或睡前都會刷一刷,查看每日新奇或小姐姐帥哥、明星視頻~ 而我們今天採集得是一個開眼界、漲知識的視頻 App, 作為國內領先的中視頻平臺,它源源不斷地為不同人群提供優質內容, 讓人們看到更豐富和有深度的世界,收穫輕鬆的獲得感,點亮對生活的好奇心。 準備工作 第三方模塊: ...
  • 📕併發基本概念以及實現、進程、線程基本概念 一、併發、進程、線程的基本概念和綜述 這些詳細概念具體去看os筆記; 1.1 併發 兩個或者更多的任務(獨立的活動)同時發生(進行):一個程式同時執行多個獨立的任務; 以往電腦,單核cpu(中央處理器):某一個時刻只能執行一個任務,由操作系統調度,每秒 ...
  • 來源:toutiao.com/i6698255904053133827 這是一位讀者帶回來的面試題 Nginx 是如何實現併發的?為什麼 Nginx 不使用多線程?Nginx常見的優化手段有哪些?502錯誤可能原因有哪些? 面試官心理分析 主要是看應聘人員的對NGINX的基本原理是否熟悉,因為大多數 ...
  • @ 一、前言 我們先來聊聊消息中間件: 消息中間件利用高效可靠的消息傳遞機制進行平臺無關的數據交流,並基於數據通信來進行分散式系統的集成。通過提供消息傳遞和消息排隊模型,它可以在分散式環境下擴展進程間的通信。(來自百度百科) 我們常見的中間件其實有很多種了,例如ActiveMQ、RabbitMQ、R ...
  • 介紹 powerjob提供了容器功能,用來做一些靈活的任務處理。這裡容器為 JVM 級容器,而不是操作系統級容器(Docker)。(至於為什麼取“容器”這個有歧義的名字是因為作者沒想出來更合適的稱呼,哈哈) 用途 有一些任務完全獨立於業務,代碼量也不大,既不希望耦合於原業務代碼,也不值得再搞一套新建 ...
一周排行
    -Advertisement-
    Play Games
  • 1、預覽地址:http://139.155.137.144:9012 2、qq群:801913255 一、前言 隨著網路的發展,企業對於信息系統數據的保密工作愈發重視,不同身份、角色對於數據的訪問許可權都應該大相徑庭。 列如 1、不同登錄人員對一個數據列表的可見度是不一樣的,如數據列、數據行、數據按鈕 ...
  • 前言 上一篇文章寫瞭如何使用RabbitMQ做個簡單的發送郵件項目,然後評論也是比較多,也是準備去學習一下如何確保RabbitMQ的消息可靠性,但是由於時間原因,先來說說設計模式中的簡單工廠模式吧! 在瞭解簡單工廠模式之前,我們要知道C#是一款面向對象的高級程式語言。它有3大特性,封裝、繼承、多態。 ...
  • Nodify學習 一:介紹與使用 - 可樂_加冰 - 博客園 (cnblogs.com) Nodify學習 二:添加節點 - 可樂_加冰 - 博客園 (cnblogs.com) 介紹 Nodify是一個WPF基於節點的編輯器控制項,其中包含一系列節點、連接和連接器組件,旨在簡化構建基於節點的工具的過程 ...
  • 創建一個webapi項目做測試使用。 創建新控制器,搭建一個基礎框架,包括獲取當天日期、wiki的請求地址等 創建一個Http請求幫助類以及方法,用於獲取指定URL的信息 使用http請求訪問指定url,先運行一下,看看返回的內容。內容如圖右邊所示,實際上是一個Json數據。我們主要解析 大事記 部 ...
  • 最近在不少自媒體上看到有關.NET與C#的資訊與評價,感覺大家對.NET與C#還是不太瞭解,尤其是對2016年6月發佈的跨平臺.NET Core 1.0,更是知之甚少。在考慮一番之後,還是決定寫點東西總結一下,也回顧一下.NET的發展歷史。 首先,你沒看錯,.NET是跨平臺的,可以在Windows、 ...
  • Nodify學習 一:介紹與使用 - 可樂_加冰 - 博客園 (cnblogs.com) Nodify學習 二:添加節點 - 可樂_加冰 - 博客園 (cnblogs.com) 添加節點(nodes) 通過上一篇我們已經創建好了編輯器實例現在我們為編輯器添加一個節點 添加model和viewmode ...
  • 前言 資料庫併發,數據審計和軟刪除一直是數據持久化方面的經典問題。早些時候,這些工作需要手寫複雜的SQL或者通過存儲過程和觸發器實現。手寫複雜SQL對軟體可維護性構成了相當大的挑戰,隨著SQL字數的變多,用到的嵌套和複雜語法增加,可讀性和可維護性的難度是幾何級暴漲。因此如何在實現功能的同時控制這些S ...
  • 類型檢查和轉換:當你需要檢查對象是否為特定類型,並且希望在同一時間內將其轉換為那個類型時,模式匹配提供了一種更簡潔的方式來完成這一任務,避免了使用傳統的as和is操作符後還需要進行額外的null檢查。 複雜條件邏輯:在處理複雜的條件邏輯時,特別是涉及到多個條件和類型的情況下,使用模式匹配可以使代碼更 ...
  • 在日常開發中,我們經常需要和文件打交道,特別是桌面開發,有時候就會需要載入大批量的文件,而且可能還會存在部分文件缺失的情況,那麼如何才能快速的判斷文件是否存在呢?如果處理不當的,且文件數量比較多的時候,可能會造成卡頓等情況,進而影響程式的使用體驗。今天就以一個簡單的小例子,簡述兩種不同的判斷文件是否... ...
  • 前言 資料庫併發,數據審計和軟刪除一直是數據持久化方面的經典問題。早些時候,這些工作需要手寫複雜的SQL或者通過存儲過程和觸發器實現。手寫複雜SQL對軟體可維護性構成了相當大的挑戰,隨著SQL字數的變多,用到的嵌套和複雜語法增加,可讀性和可維護性的難度是幾何級暴漲。因此如何在實現功能的同時控制這些S ...