用token作权限验证,这样就不用session了

浏览:17711 发布日期:2017/09/12 分类:技术分享 关键字: token session JWT
JWT使用实例

来源:原创(我的空间:http://groupby.cn)
在新的项目中使用了JWT密钥,效果不错。(还有JWT的异常处理,有待解决,但因为使用了vue前端框架,有没有异常已经暂时不影响使用了。)



先简单介绍一下JWT:

JWT 是 JSON Web Token的缩写,详细说明百度多的是,就不用我劳神了。

JWT的作用是加密和解密。它可以把一堆数据加密,并生成一串密文,也可以把密文解密,还原原始数据。

这样一来就可以用JWT加密个人登录信息,以便个人登录时,并提供密文,以证明自己是合法用户。

例如:把登录后的uid加密形成密文,然后发回个客户端,客户端以后每次都携带密文,访问带有权限验证的页面,服务服务端通过解密,得到uid,说明是已登录过的用户,并开放访问。

这样,就必须要求客户端在访问每个需要验证的页面,都必须携带密文,同时在服务端也就不需要使用session验证了。

顺便也避免了服务端session数据大的时候,引起的问题。

因为加密的密文不是很长,服务端解密是很快的,所以不会给服务端造成压力。(这是网上说的,我没有大数据测试的条件)

这样带来的好处是,多种设备使用一种密钥,都可以通用,可以避开手机端使用session等问题。



大概的使用方法:

下载jwt放在适当的目录。

在thinkphp加载jwt

定义一个数组,

用jwt加密这个数组,并得到一串密文。

把密文返回客户端,以便从此以后,客户端去到哪里都带着这一串密文。并依赖这一串密文作为访问服务端的权限。
即客户端打开另一个页面,并且需要验证的时候,客户端需要提交密文,服务端解密密文,还原得到密文里面的信息,
服务端再根据这些信息,作为下进入一步的条件,如果条件符合要求,就继续,不够不符合要求,就拒绝下一步。

例如,还原密文后,其中有用户id,就提供此用户的个人信息,如果解密失败,就停止。




安装:

我从这里下载了JWT

https://github.com/firebase/php-jwt

并把里面的src文件夹修改为firebase/JWT,然后再放在网站根路径的Library目录中,thinkphp的导入,我不会,也觉得有不好的地方。

这样我的JWT就安装在:

D:/www/Library/firebae/JWT目录下了,里面有四个文件,其中JWT.php是有用的。(另外,三个文件是跟异常有关的,还没用好)

之所以要加上目录firebase,是因为JWT.php的命名空间有firebase,为了避免因修改源文件引起的问题,所以,先保存原文件不变。变的是自己的配置,这样我好判断问题出在哪个部位。

所以,我的文件就是这样安排的:

D:/www/Library/firebae/JWT/JWT.php
D:/www/Library/firebae/JWT/BeforeValidException.php
D:/www/Library/firebae/JWT/ExpiredException.php
D:/www/Library/firebae/JWT/SignatureInvalidException.php


好了,接下来是thinkPHP的部分了,我用的是thinkPHP3.2.3版本

先用thinkPHP编写两个方法,测试一下TWJ是否可以正常使用:

注:我在配置中定义了Library,我觉得这样比较好用,不依赖thinkphp,即:

项目目录/Common/Conf/config.php

'Library' => 'D:/www/Library/',


下面是两个测试方法,先证明一下,JWT是否可以使用了。


<?php
namespace Home\Controller;
use Think\Controller;

require_cache(C('Library')."Firebase/JWT/JWT.php");
use \Firebase\JWT\JWT;

class UserController extends Controller {

public function one(){
$key = "jfdksajfkl;dsajfkdjsaklfdajffdsafdsfdsfdsfdsklfdsafdsafdsafdsdsajlkfdsa";
$token = array(
'uid' => 1050,
'username' => 'baby',
);

$jwt = JWT::encode($token, $key);
echo $jwt;
}


得到一串密文类似这个样子:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9leGFtcGxlLm9yZyIsImF1ZCI6Imh0dHA6XC9cL2V4YW1wbGUuY29tIiwidXNlcmlkIjoiMTAwMDEiLCJ1c2VybmFtZSI6ImJhYnkiLCJ0cnVlbmFtZSI6ImEgbGl0dGxlIGJveSIsIm1vYmlsZSI6IjEzMzU2NDg1MjIifQ.9_SIzSonrft-BMqaKEp_KZzjwuSxgjHWeFc4cKhDXV8





public function two(){
$key = "jfdksajfkl;dsajfkdjsaklfdajffdsafdsfdsfdsfdsklfdsafdsafdsafdsdsajlkfdsa";
$str = isset($_GET['str']) ? $_GET['str'] : '';
if($str == ''){
exit('empty');
}
$decoded = JWT::decode($jwt, $key, array('HS256'));
if(!is_object($decode)){
echo "error";
}else{
$arr = json_decode(json_encode($decoded), true);
dump($arr);
$uid = $arr['uid']; //既然能拿到uid,那么就说明是有权限的用户,并且他的uid是1050。剩下的,只要有uid,该干什么就干什么好了。
}
}
}


下面是打开另一个页面,同时携带密文,类似这个样子:


某某项目/Home/Index/two?str=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9leGFtcGxlLm9yZyIsImF1ZCI6Imh0dHA6XC9cL2V4YW1wbGUuY29tIiwidXNlcmlkIjoiMTAwMDEiLCJ1c2VybmFtZSI6ImJhYnkiLCJ0cnVlbmFtZSI6ImEgbGl0dGxlIGJveSIsIm1vYmlsZSI6IjEzMzU2NDg1MjIifQ.9_SIzSonrft-BMqaKEp_KZzjwuSxgjHWeFc4cKhDXV8


如果解密成功,就可以得到用户id。

同时,也说明试验成功。接下了来,是作实际的使用了。



==========实际的应用:用户登录===============



public function check_login(){
header("Access-Control-Allow-Origin: *");
$post_str = file_get_contents("php://input");
$post = json_decode($post_str, true);

$username = $post['username'];
$password = $post['password'];

$find_password = M('Pass')->where("username='$username'")->find();

if(如果密码正确){
$arr = array(
"uid" => $uid,
"username" => $find_password['username'],
);

//登录日志,不是必须的。
user_sign($find_password['uid'], 1);

//生成密钥
$jwt = JWT::encode($arr, $key);

$data['status'] = 200;
$data['msg'] = '登录成功';
$data['token'] = $jwt;
exit(json_encode($data));
}

}




==========用户访问有权限的页面=============


public function user_info(){
header("Access-Control-Allow-Origin: *");
$post_str = file_get_contents("php://input");
$post = json_decode($post_str, true);

$token = $post['token'];

if($token != ''){
$obj_token = JWT::decode($token, $key, array('HS256'));
$arr = json_decode(json_encode($obj_token), true);

$uid = $arr['uid'];

//下面是输出此会员的个人信息了。

...


}
}


使用效果:

因为前端使用了vue,后端程序需要作的工作就比以前好多了,不用再为模板嵌套数据了。

后端只要输出JSON数据就行了,加工数据、显示数据,就让前端js工作人员来完成好了。



最佳答案
评论( 相关
后面还有条评论,点击查看>>