前言
最近需要搭建一个前后端分离的项目,前端当然就使用常见的框架Vue的脚手架,关于Vue脚手架的安装可以参考之前的博客。后端采用php中的laravel框架,号称最受欢迎的框架,确实相比其他php的框架,在github上的星星的个数要高很多。因为之前的系统大部分前后端一个人搞定的,也常用模板引擎,现在前后端分离以后,可能前端和后端都不在同一台服务器上,因此有必要先配置后端的请求地址。
前端配置后端请求地址
配置admin开头的请求全部转发到8000的后端端口上
客户端带着账号密码登录,服务端处理
//生成token
$token = Token::getToken(['id' => $info['id'],'username' => $info['username'],'time' => time()]);
// 把token存储在redis中用于更新有效期
$val = ['token' => $token];
$key = "ADMIN:UID:".$info['id'];
$redis = new Predis();
$redis->set($key,$val,3600);
//登录成功后把token返回给客户端,客户端保存
客户端存放登录成功后的token
客户端登录后的请求
拦截器中生成需要带的token,这里把时间戳参数加进去后端解密出来,根据时间戳判断请求的有效性。
service.interceptors.request.use(
config => {
let time = Math.round(new Date() / 1000);
let sign = md5("appname=LaravelAdmin&appsecret=Sl7qkF2DKglAdlk4397qdKCUf3×tamp=" + time);
// 设置请求头
let data = {
sign: sign,
timestamp: time,
token: localStorage.getItem('token')
}
config.headers.token = Base64.encode(JSON.stringify(data));
return config;
},
error => {
console.log(error);
return Promise.reject();
}
);
登录后的服务端处理
$token = $request->header('token');//对应上面的data的base64后的值
$str = base64_decode($token);
$arr = json_decode($str,true);
//首先验证时间戳是否在有效期
if ((time() - $arr['timestamp']) > 60) {
errorReturn();
}
//签名是否正确
$sign = md5('appname='.config('style.app.name').'&appsecret='.config('style.app.secret').'×tamp='.$arr['timestamp']);
if ($arr['sign'] != $sign) {
errorReturn();
}
$userToken = $arr['token'];//用户传过来的token
//反解token
$result = Token::checkToken($userToken);
//验证redis中是否存储改用户信息
$result = (array)$result;
$userInfo = (array)$result['data'];
# 从redis获取信息
$key = "ADMIN:UID:".$userInfo['id'];
$redis = new Predis();
$data = $redis->get($key);
if (!$data) {
errorReturn('登录失效,请重新登录',1001);
}
# 只允许账号一次登录, 判断用户传过来的token是不是之前服务端给的token,因为多次登录的token中包含的user_id可能是相同的,但是生成的完整的token是不相同的,因此如果需账号只能一次登录,可以使用该判断,反之,注释代码即可。
if ($userToken != $data['token']) {
errorReturn('登录失效,请重新登录',1001);
}
# 刷新token的有效期,类似于sessionID有效期从操作后开始计算
$redis->expire($key,3600*4);