php laravel 实现扫码登录

php laravel 实现扫码登录

laravel 实现扫码登录

1.首先扫码端(移动端)必须登录了

2.进去登录页时,成生一个token,然后生成带token值的登录链接的二维码

3.前端定时异步请求服务前判断是否缓存 中 改token 是否有对应的用户信息

4.用户扫码,将用户的信息 与 缓存的token 对应

5.前端定时异步请求 获取 到 token 的用户信息,并将用户信息加入session,刷新页面

控制器
<?php

namespace App\Http\Controllers\PHP\Demo;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;

use Endroid\QrCode\Color\Color;
use Endroid\QrCode\Encoding\Encoding;
use Endroid\QrCode\ErrorCorrectionLevel\ErrorCorrectionLevelLow;
use Endroid\QrCode\QrCode;
use Endroid\QrCode\Label\Label;
use Endroid\QrCode\Logo\Logo;
use Endroid\QrCode\RoundBlockSizeMode\RoundBlockSizeModeMargin;
use Endroid\QrCode\Writer\PngWriter;
use Illuminate\Support\Facades\Redis;
use phpseclib3\Crypt\Random;
use Ramsey\Uuid\Uuid;


class QrCodeLoginController extends Controller
{
    //登录页面
    public function index(Request $request)
    {
        $user = $request->session()->get("user");
        if ($user)
        {
            print_r($user);
            return "<h1>已登录了</h1>";
        }
        return view('php.demo.qr_code_login.login');
    }

    //获取二维码
    public function getQrCode(Request $request)
    {
        if ($request->session()->get("user"))
        {
            return response()->json(['code'=>0]);
        }

        $token = $request->session()->get('token');
        if (!empty($token))
        {
            $this->delCode($token);
        }

        $token = (string)Uuid::uuid4();
        $request->session()->put('token',$token);
        $data =  route("qr_code_login.login",['token'=>$token]);

        $writer = new PngWriter();

        // Create QR code
        $qrCode = QrCode::create($data)
                        ->setEncoding(new Encoding('UTF-8'))
                        ->setErrorCorrectionLevel(new ErrorCorrectionLevelLow())
                        ->setSize(300)
                        ->setMargin(10)
                        ->setRoundBlockSizeMode(new RoundBlockSizeModeMargin())
                        ->setForegroundColor(new Color(0, 0, 0))
                        ->setBackgroundColor(new Color(255, 255, 255));




        $result = $writer->write($qrCode);
        $full_name = "img/code/".md5($token).".png";
        touch($full_name);
        $result->saveToFile($full_name);
        return response()->json(['code'=>1,'data'=> [ 'qr_code'=> "/".$full_name] ]);
    }

    public function delCode(string $token)
    {
        if (file_exists("img/code/{$token}.png"))
        {
            unlink("img/code/{$token}.png");
        }

    }

    //检查是否扫码了
    public function check(Request $request)
    {
        if ($request->session()->get("user"))
        {
            return response()->json(['code'=>1]);
        }

        $token = $request->session()->get('token');
        if (!$token){
            return response()->json(['code'=>0]);
        }
        $user = Cache::pull("user-token:{$token}");
        if ($user)
        {
            $request->session()->put("user",$user);
            $this->delCode($token);
        }

        return response()->json(['code'=>$user?1:0 ]);
    }

    //登录
    public function login(Request $request)
    {
        if ( !$token = $request->input("token") )
        {
            return "<h1>token 无效</h1>";
        }
        $file = "img/code/".md5($token).".png";
        if( !file_exists($file) )
        {
            return "<h1>token 无效1</h1>";
        }

        if ( time() - filectime($file) > 15 )
        {
            $this->delCode($token);
            return "<h1>token 无效2</h1>";
        }


        /**
         * 先要判断扫码这个端是否登录了,没登陆要登录后,再扫
         */
        //模拟用户信息,真正用要改成自己的用户逻辑
        $user = [
            'user_id'      => random_int(1,999),
            'access_token' => md5(Uuid::uuid1()),
            'name'         => '随机用户',
        ];
        Cache::put("user-token:{$token}",$user);
        $this->delCode($token);
        return "<h1>扫码登录成功</h1>";
    }
}
?>
route.php
<?php
Route::prefix('php/demo/qr_code_login')->group(function () {
    Route::get('/',[QrCodeLoginController::class,'index']);

    Route::get('code',[QrCodeLoginController::class,'getQrCode'])->name('qr_code_login.code');

    Route::get('login',[QrCodeLoginController::class,'login'])->name('qr_code_login.login');

    Route::get('check',[QrCodeLoginController::class,'check'])->name('qr_code_login.check');
});
?>
页面代码
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <title>Laravel</title>

        <link rel="stylesheet" type="text/css" href="/css/vertical_horizontal_center.css">
        <script src="/js/axios.js"></script>
        <style>
            body {
                font-family: 'Nunito', sans-serif;
            }
            .title{
                width:100px;
            }
            .v-h-center{
                background-color: #FFF;
            }
        </style>
    </head>
    <body >
        <div class="v-h-center">
            <p >扫码登录</p>
            <div>
                <img class="qr_code_img" src="/img/loading.png" width="100%" height="100%" >
            </div>
        </div>
    </body>
</html>

<script>
    var img = document.querySelector('.qr_code_img');

    get_code();

    setInterval(function(){
        get_code();
    },15000);

    function get_code()
    {
        let url = "{{ route('qr_code_login.code') }}";
        img.src = "/img/loading.png";
        axios.get(url)
            .then(function (response) {
                if (response &&  response.data.code == 1) {
                    let data = response.data.data;
                    if (data.qr_code)
                    {
                        img.src = data.qr_code;
                    }
                }
            })
            .catch(function (error) {
                console.log(error);
            });
    }


    check();
    function check()
    {
        let url = "{{ route('qr_code_login.check') }}";
        axios.get(url)
            .then(function (response) {
                if (response &&  response.data.code == 1) {
                    alert("登录成功");
                    window.location.reload();
                    return;
                }else{
                    setTimeout(function(){
                        check();
                    },1000);
                }
            })
            .catch(function (error) {
                console.log(error);
            });
    }
</script>

留下回复