前几天买阿里云服务器的时候,被扫码登陆给吸引到了。然后就一直在琢磨自己的实现方式。也许是巧合吧,昨晚竟然在梦中找到了一个自认为还不错的实现思路。但是已经凌晨了,为了防止忘记,赶紧写了个小纸条放在床边。于是今天上午就着手编码做了个雏形。
作此文,以记之。
原理
感觉还是应该先进行声明一下。
纯属个人拙见,如果有些许不当,还望海涵。
按照我扫码登陆的亲身经历,可以分为下面几个阶段。
打开网页
拿阿里云来说,打开首页点击登录按钮之后,就会跳转到下面的这个网页,让我们使用阿里云手机客户端 扫码。
扫码阶段
其实我们可能会很疑惑,为什么一扫码, 人家就能知道咱扫过了呢?而且就这么真的登陆成功了?
其实如果让我自己来做的话,关键就在于这个阿里云手机客户端。众所周知,二维码只是个用于传递数据的工具,它本身并不能帮助我们确认是否被扫码,被谁扫了。
但是关键就在于这个数据。其实这个数据至关重要,因为借助此数据,手机客户端才能“定位”(这个词不是特别贴切,看完后面的相信就可以明白了。)
验证阶段
然后手机客户端,将客户端上已经登录的您的账号,加上这个数据。
-
如果在时效内确认,则会登陆成功。
-
如果时效内未进行验证,则二维码失效。
如此将需要的数据进行打包,然后向服务器发送一个请求,然后服务器通过这个数据 定位到数据库中相关的登录表上,然后添加登陆的用户的用户名,确认登陆。然后登陆标记记为已登录, 状态。
好了,大致的整个流程就是这样了,是不是很容易也可以理解呢。
准备
“工欲善其事,必先利其器”,所以咱们还是先着手搭建一个好用的环境吧。
搭建环境
可能每个人使用的软件版本会有所不同,但是基本上都是可以正常工作的,如果您正确安装了的话。 下面罗列一下我自己的环境。
服务器环境
- PHP5.2.8
- Apache2.2
- MySQL5.7
第三方依赖
另外,本次试验要完成的是扫码登陆,所以必不可少的要生成二维码。在PHP中生成二维码的方式有很多,比较常用的是:
借助google api.可以参照: http://www.jb51.net/article/37775.htm
-
借助PHP QRCode 库。
然后为了更加方便的进行HTML元素的操作,就把JQuery也拿过来好了。
不过这不是必须需要的,如果不想用,可以用原生的JavaScript来实现。
我用的是
jquery-2.2.4.min.js
后端
我感觉上面原理熟悉了之后,后台设计就应该很简单了。先来看看目录结构吧(比较散乱,吸取教训哈)。
数据库
因为这次试验主要是为了实现扫码登陆,所以就直接设计一个登录表好了,虽然实际中肯定不是这样的。也比这要复杂的多。
id就作为上面讲述的那个特殊的数据。
而创建时间createtime 则是为了时效。而存在。
其余字段不再过多解释。
生成二维码
借助PHP的QRCode库,其实是很方便的。
<?php
error_reporting(E_ALL);
ini_set('error_reporting', '1');
session_start();
include "./phpqrcode/phpqrcode.php";
$value = uniqid();
$errorCorrectionLevel = "L";
$matrixPointSize = "4";
// session storage
$_SESSION['uuid'] = $value;
// 向数据库中插入生成的数据
$link = mysql_connect('localhost', 'root', 'root') or die(mysql_error());
mysql_query('set names utf8');
mysql_select_db('test');
$createtime = date("Y-m-d H:i:s");
$account = 'guest';
$isscanned = 0;
$issuccess = mysql_query("insert into qrcode values('$value', '$account', '$createtime', $isscanned)") or die(mysql_error());
//var_dump($issuccess);
if($issuccess==1){
QRcode::png($value, false, $errorCorrectionLevel, $matrixPointSize);
}else{
echo "insert into db failed!";
}
?>
虽然代码中向数据库中插入了游客账号,但是这并不影响接下来客户端发送请求后对登陆用户及信息的更改。
然后需要注意的是记得在代码的开始处开启session,不然有可能会出错。
处理确认登陆请求
处理登陆请求其实也算是重中之重了。所以handler.php的责任义不容辞。
<?php
session_start();
header("Content-Type: text/json;charset=UTF-8");
$uuid = $_REQUEST['uuid'];
// echo $uuid;
// 获取到数据库中与此uuid一致的那一行的用户信息
$link = mysql_connect('localhost', 'root', 'root') or die(mysql_error());
mysql_query('set names utf8');
mysql_select_db('test');
$resultset = mysql_query("select * from qrcode where id= '$uuid'") or die(mysql_error());
while(($row=mysql_fetch_array($resultset))) {
$result[] = $row;
}
mysql_close($link);
echo json_encode($result);
?>
至于作用嘛,就是网页前台那块用于更改登陆者信息。使用ajax轮询的方式对登录表进行查询,从而来实时的更新状态信息。
前端
好了,后台已经搭建好了,这个时候就可以好好的写写前端的代码了。我本人不太懂设计这块,所以就简单的写了下,聊表心意算了。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0" />
<title>二维码扫描登陆</title>
<style>
.container {
width: 600px;
height: 480px;
position: absolute;
background: gray;
left: 50%;
margin-left: -300px;
}
.header {
width: 100%;
height: 64px;
position: relative;
background: black;
}
.main {
width: 80%;
height: 340px;
position: relative;
left: 50%;
margin-left: -30%;
top: 12%;
background: url(921555.png) no-repeat;
background-size: contain;
}
ul {
margin: 0px;
padding: 0px;
width: auto;
list-style: none;
position: relative;
}
ul >li {
float: right;
position: relative;
}
/* 设计显示二维码的空间*/
.qrcontainer{
width: 300px;
height: 300px;
top: 64px;
position: relative;
background: green;
}
.qrcontainer > img {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<ul>
<font color="white" size="6" style="margin-top: 6px;">二维码扫描登陆测试</font>
<li><font color="white" size="6"><a href="#">登陆</a>/ <a href="#">注册</a></font></li>
</ul>
</div>
<div class="main">
<img id="photo" src="" />
</div>
</div>
<div class="qrcontainer">
![](./qrcode.php)
</div>
<input type="hidden" name="uuid" value="<?php session_start(); echo $_SESSION['uuid'];?>"/>
</body>
<script src="jquery-2.2.4.min.js"></script>
<script>
$(document).ready(function(){
var uuid = document.getElementsByName('uuid')[0].value;
// 想法是通过ajax轮询,请求服务器上的登录状态信息
$.ajax({
url: './handler.php',
type: 'POST',
async: true,
data: {
'uuid': uuid
},
timeout: 5000,
dataType: 'json',
success: function(result){
document.getElementById("photo").src = 'photo.jpeg';
$(".qrcontainer").css('display', 'none');
console.log(result);
},
error: function(){
console.log('额,AJAX请求出错了!');
}
});
});
</script>
</html>
效果
观看完人家阿里云的,再来看咱自己的。额,瞬间感觉档次下降了好多啊。
首页
先来看看首页效果图
扫码
扫码这块,我没有另外写一个app。其实原理了解了就行了。 App的作用就是将扫描到的二维码的UUID值,加上用户的用户名等信息传给服务器。
这个时候服务器就可以根据UUID查找到刚才插入到数据库上的信息,然后进行信息的更新操作即可。操作比较简单,这里就不再进行演示了。
前台通过ajax请求就可以获取到:是谁登陆了?这些信息。
这里通过添加一张图片来验证确实通过了验证请求。
查看一下后台发送过来的数据,也可以进一步进行验证的啦。
拓展
基本上效果已经实现的差不多了。但是做的仍然不够好。我觉得可以从下面几个角度进行加强。
轮询
上面的代码没有进行轮询处理。其实完全可以设置一个Inerval来进行的。这样才能更加逼真的体现实时性的特点。
超时
想必您也已经看到了数据库中设计好的createtime字段。之所以设置这样的一个字段,就是为了让二维码在一定是的时段内有效。这样可以进一步加强登录操作的安全性。
至于优化部分,使用JavaScript很容易啦。不过多叙述。
扫描后失效
这一点可以通过isscanned字段进行控制。当然了,离不开ajax的配合。通过对此字段的“监控”。就可以很容易的实现这一个效果。
总结
回顾一下本次实验。主要是实现了一个非权威的扫码登陆功能,(雏形一个)。
然后根据代码本身,找到了几个可以进行优化和拓展的方向。想来进一步的话,做成一个更加完善的扫码登陆,也会水到渠成的。