This content originally appeared on DEV Community and was authored by Sahil kashyap
Cross mobile to web browser login
Method used: Polling
Things required: memcache and imagick extension(in php)
- Create a QR code using a random string,Save the random string in memcache for 3 minutes
- Poll did scan api
- Poll did login api
- QR scanner app
in web.php
//web.php
Route::get('/qrtesting2', 'Admin\QRLoginTwoController@qr');
Route::get('/qrscanner','Admin\DashboardController@qrscanner');
in api.php
//api.php
Route::post('/login/create/qrcode', 'Admin\QRLoginTwoController@CreateQrcodeAction');//creates QR
Route::post('/login/mobile/scan/qrcode', 'Admin\QRLoginTwoController@mobileScanQrcodeAction');//gets scaned by phone
Route::post('/login/qrcodedoLogin', 'Admin\QRLoginTwoController@qrcodeDoLoginAction');
Route::post('/login/scan/qrcode', 'Admin\QRLoginTwoController@isScanQrcodeAction');
Route::post('/login/entry/login', 'Admin\QRLoginTwoController@loginEntry');
Lets generate the QR code
look in the console, qr key, and it started polling for qrscan check
Scan it with the QR scanner or use the postman api to simulate the scan
api:
pass the userpasscode in headers
- When dologinapi hit is done
api: api/login/qrcodedoLogin?key=3pdBjf5tVq0onKbQQJBokrTxhC2z2r&type=scan&login=12345pass&sign=p3p3zRWd72mZ
- Login will be succsfully, you'll get the passcode you passed
- QR scanner look like this
here is the code gist
here's the controller code
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Cache;
use SimpleSoftwareIO\QrCode\Facades\QrCode;
use Memcache;
use Illuminate\Support\Facades\Auth;
class QRLoginTwoController extends Controller
{
// QR code should be only avilable for non logged in user
public function qr()
{
if (Auth::check())
{
return "you are already logged in, open it in incognito mode";
}
else
{
return view('frontend.drm.qr');
}
}
//QR scanner only avilable for logged in user
public function qrscanner()
{
if (Auth::check())
{
$login = true;
return view('frontend.drm.qrscanner', compact('login'));
}
return redirect()->route('home');
}
public function CreateQrcodeAction()
{
$url = 'http://' . $_SERVER['HTTP_HOST']; // Get the current url
// dd($url);
$http = $url . '/api/login/mobile/scan/qrcode'; // Verify the url method of scanning code
$key = Str::random(30); //$this->getRandom(30); // The key value stored in memcache, a random 32-bit string
$random = mt_rand(1000000000, 9999999999); //random integer
$_SESSION['qrcode_name'] = $key; // Save the key as the name of the picture in the session
$forhash = substr($random, 0, 2);
$sgin_data = HashUserID($forhash); // The basic algorithm for generating the sign string
$sgin = strrev(substr($key, 0, 2)) . $sgin_data; // Intercept the first two digits and reverse them
$value = $http . '?key=' . $key . '&type=1'; // Two-dimensional Code content
$pngImage = QrCode::format('png')
// ->merge(public_path('frontend/img/streamly-logo.png'), 0.3, true)
->size(300)
->errorCorrection('H')
->generate($value, public_path('assets/img/qrcodeimg/' . $key . '.png'));
$return = array(
'status' => 0,
'msg' => ''
);
$qr = public_path('assets/img/qrcodeimg/' . $key . '.png');
if (!file_exists($qr))
{
$return = array(
'status' => 0,
'msg' => ''
);
return response()->json($return, 404);
// return "no found qr img";
}
$qr = asset('assets/img/qrcodeimg/' . $key . '.png');
$mem = new \Memcache();
$mem->connect('127.0.0.1', 11211);
$res = json_encode(array(
'sign' => $sgin,
'type' => 0
));
// store in memcache, expiration time is three minutes
$mem->set($key, $res, 0, 180); // 180
$return = array(
'status' => 1,
'msg' => $qr,
'key' => $key
);
return response()->json($return, 200);
}
// Mobile device scan code
public function mobileScanQrcodeAction(Request $request)
{
$key = $_GET['key'];
$url = 'http://' . $_SERVER['HTTP_HOST'];
$agent = $_SERVER["HTTP_USER_AGENT"];
$headerpasscode = $request->header('userpasscode');
$http = $url . '/api/login/qrcodedoLogin'; // Return to confirm the login link
$mem = new \Memcache();
$mem->connect('127.0.0.1', 11211);
$data = json_decode($mem->get($key) , true);
if (empty($data))
{
$return = array(
'status' => 2,
'msg' => 'expired'
);
return response()->json($return, 200);
}
$data['type'] = 1; // Increase the type value to determine whether the code has been scanned
$res = json_encode($data);
$mem->set($key, $res, 0, 180);
$http = $http . '?key=' . $key . '&type=scan&login=' . $headerpasscode . '&sign=' . $data['sign'];
$return = array(
'status' => 1,
'msg' => $http
);
return response()->json($return, 200);
}
/* *
* Log in after the client scans the code
* $sign passes the identification when the client scans the code, and compares it with the memcache
* $key is the key passed in the QR code on the web page
* $uid The user id sent by scanning the code after the client logs in
* @return void
*/
public function qrcodeDoLoginAction(Request $request)
{
$login = $_GET['login']; //jwt or passcode
$key = $_GET['key'];
$sign = $_GET['sign'];
$mem = new \Memcache();
$mem->connect('127.0.0.1', 11211);
$data = json_decode($mem->get($key) , true); // Remove the value of memcache
if (empty($data))
{
$return = array(
'status' => 2,
'msg' => 'expired'
);
return response()->json($return, 200);
}
else
{
if (!isset($data['sign']))
{
$return = array(
'status' => 0,
'msg' => 'Sign notset'
);
}
if ($data['sign'] != $sign)
{ // Verify delivery Sign
$return = array(
'status' => 0,
'msg' => 'Verification Error'
);
// return $this ->createJsonResponse( $return );
return response()->json($return, 403);
}
else
{
if ($login)
{ // Mobile phone scan code webpage login, save the user name in memcache
$data['jwt'] = $login;
$res = json_encode($data);
$mem->set($key, $res, 0, 180);
$return = array(
'status' => 1,
'msg' => 'Login successful'
);
// return $this ->createJsonResponse( $return );
return response()->json($return, 200);
}
else
{
$return = array(
'status' => 0,
'msg' => 'Please pass the correct user information'
);
// return $this ->createJsonResponse( $return );
return response()->json($return, 401);
}
}
}
}
/* *
* Check whether the code has been scanned, this checked by polling,
* it looks for the key, the filename,
*/
public function isScanQrcodeAction(Request $request)
{
$key = $request['key'];
$mem = new \Memcache();
$mem->connect('127.0.0.1', 11211);
$data = json_decode($mem->get($key) , true);
if (empty($data))
{
$return = array(
'status' => 2,
'msg' => 'expired'
);
}
else
{
if ($data['type'])
{
$return = array(
'status' => 1,
'msg' => 'success'
);
}
else
{
$return = array(
'status' => 0,
'msg' => ''
);
}
}
return response()->json($return, 200);
// return $this->createJsonResponse( $return );
}
public function loginEntry(Request $request)
{
$key = $request['key'];
if (empty($key))
{
$return = array(
'status' => 2,
'msg' => 'key not provided'
);
return response()->json($return, 200);
}
$mem = new \Memcache();
$mem->connect('127.0.0.1', 11211);
$data = json_decode($mem->get($key) , true);
// $passcode=$data['login'];
if (empty($data))
{
$return = array(
'status' => 2,
'msg' => 'expired'
);
return response()->json($return, 200);
}
else
{
if (isset($data['jwt']))
{
$userid = UnHashUserID($data['jwt']);
$user = Auth::loginUsingId($userid, true);
$return = array(
'status' => 1,
'msg' => 'success',
'jwt' => $data['jwt'],
'user' => $user
);
return response()->json($return, 200);
}
else
{
$return = array(
'status' => 0,
'msg' => '',
'data' => $data
);
return response()->json($return, 400);
}
}
//to do web ajax login
// Use passcode to login and return the object in reposne or jWT
// extract memcache and the login var jwt/passcode
//use passcode to login and return the jwt
}
}
?>
blade files are present in the gist
This content originally appeared on DEV Community and was authored by Sahil kashyap
Sahil kashyap | Sciencx (2021-10-02T19:18:37+00:00) QR Login in PHP. Retrieved from https://www.scien.cx/2021/10/02/qr-login-in-php/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.