tp+jwt
后端
1、先安装phpjwt(需要composer安装)
composer require firebase/php-jwt
2、验证类
- <?php
- namespace app\index\controller;
- use Firebase\JWT\JWT;
-
- class Jwttoken
- {
- //生成token
- public function createJwt($username)
- {
- $key = md5('nobita'); //jwt的签发密钥,验证token的时候需要用到
- $time = time();
- $expire = $time + 14400; //过期时间
- $token = array(
- "username" => $username,
- "iss" => "",//签发组织
- "aud" => "", //签发作者
- "iat" => $time, //签发时间
- "nbf" => $time, //生效时间
- "exp" => $expire
- );
- $jwt = JWT::encode($token, $key);
- return $jwt;
- }
-
-
- //校验jwt权限API
- public function verifyJwt($jwt)
- {
- $key = md5('nobita');
- try {
- $jwtAuth = json_encode(JWT::decode($jwt, $key, array('HS256')));
- $authInfo = json_decode($jwtAuth, true);
- $msg = [];
- if (!empty($authInfo['username'])) {
- $msg = [
- 'status' => 0,
- 'msg' => 'Token验证通过',
- 'username' => $authInfo['username']
- ];
- } else {
- //Token验证不通过,用户不存在
- $msg = [
- 'status' => 10001,
- 'msg' => '当前用户不存在'
- ];
- }
- return json_encode($msg);
- } catch (\Firebase\JWT\SignatureInvalidException $e) {
- echo json_encode([
- 'status' => 10002,
- 'msg' => 'Token无效'
- ]);
- exit;
- } catch (\Firebase\JWT\ExpiredException $e) {
- //Token过期
- echo json_encode([
- 'status' => 10003,
- 'msg' => '登录信息已超时,请重新登录'
- ]);
- exit;
- } catch (Exception $e) {
- echo json_encode([
- 'status' => 10004,
- 'msg' => '未知错误'
- ]);
- exit;
- }
- }
- }
3、公共类统一验证
- <?php
-
- namespace app\index\controller;
-
- use think\Controller;
- use think\Request;
- use app\index\controller\Jwttoken;
-
- header('Access-Control-Allow-Origin: *');
- header('Access-Control-Allow-Methods:POST, GET, PUT, DELETE, OPTIONS');
- header('Access-Control-Allow-Headers:x-requested-with,content-type,Authorization');
-
- class Common extends Controller
- {
- //定义一个空的登录信息
- public $username = null;
-
- public function _initialize()
- {
- parent::_initialize();
- $this->checkToken();
- }
-
- public function checkToken()
- {
- $header = Request::instance()->header();
- if (isset($header['authorization'])) {
- if ($header['authorization'] == 'null') {
- echo json_encode([
- 'status' => 10005,
- 'msg' => 'Token不存在,拒绝访问'
- ]);
- exit;
- } else {
- $token = new Jwttoken;
- $checkJwtToken = $token->verifyJwt($header['authorization']);
- //验证通过
- if (json_decode($checkJwtToken, true)['status'] == 0) {
- //验证成功之后 继承了公共类的所有方法都可以直接调用登录用户 不用额外传参
- $this->username = json_decode($checkJwtToken, true)['username'];
- return true;
- }
- }
- } else {
- //Token不存在,拒绝访问
- return json_encode([
- 'status' => 10006,
- 'msg' => '请勿非法登录'
- ]);
- exit;
- }
-
- }
- }
4、登录控制器(登录控制器不用继承公共类,登录成功之后把生成的token返回给前端)
- <?php
-
-
- namespace app\index\controller;
-
- use app\index\controller\Jwttoken;
- use think\Controller;
- use think\Db;
-
- header('Access-Control-Allow-Origin: *');
- header('Access-Control-Allow-Methods:POST, GET, PUT, DELETE, OPTIONS');
- header('Access-Control-Allow-Headers:x-requested-with,content-type,Authorization');
-
-
- class Login extends Controller
- {
-
- public function login()
- {
- if (Request()->isPost()) {
- $data = input();
- $isset = db('user')->where('username', $data['username'])->find();
- if (!$isset) {
- return json(['error' => '1000', 'errormsg' => '当前用户不存在']);
- }
- if (md5($data['password']) != $isset['password']) {
- return json(['error' => '1000', 'errormsg' => '密码错误']);
- } else {
- $token = new Jwttoken();
- $user_token = $token->createJwt($isset['username']);
- return json(['error' => '0', 'errormsg' => '登录成功', 'token' => $user_token]);
- }
- }
- }
-
- }
前端(vue+element)
1、登录操作(登录成功之后把token存入localStorage)
- loginSubmit() {
- this.$refs['loginForm'].validate(async valid => {
- if (valid) {
- const {
- data: result
- } = await this.$http.post("/index/login/login", this.loginForm)
- if (result.error != 0) {
- this.$message.error(result.errormsg)
- return false;
- } else {
- this.$message.success(result.errormsg)
- window.localStorage.setItem('token', result.token);
- this.getuserinfo()
- this.gettypelist()
- this.getbooklist(0)
- this.logindialog = false
- this.loginForm = {
- username: '',
- password: '',
- }
- }
- } else {
- return false;
- }
- });
- }
2、在main.js设置请求拦截器和响应拦截器
- import Vue from 'vue'
- import App from './App.vue'
- import router from './router'
- import ElementUI from 'element-ui';
- import 'element-ui/lib/theme-chalk/index.css';
-
- import axios from 'axios'
-
- Vue.config.productionTip = false
- Vue.use(ElementUI);
- Vue.prototype.$http = axios
- //配置请求根路径
- axios.defaults.baseURL = 'http://www.shifuchen.top'
-
- //请求拦截器
- axios.interceptors.request.use(config => {
- config.headers.Authorization = window.localStorage.getItem('token')
- return config
- }, error => {
- Promise.reject(error)
- })
- // 添加响应拦截器
- axios.interceptors.response.use(response => {
- const status = response.data.status
- const msg = response.data.msg
- if (status > 10000) {
- ElementUI.Message({
- message: msg,
- type: 'error'
- });
- window.localStorage.clear();
- return false;
- } else {
- return response
- }
- }, error => {
- Promise.reject(error)
- });
-
- new Vue({
- router,
- render: h => h(App)
- }).$mount('#app')
3、在路由中挂载路由守卫router/index.js(判断token过期或者不合法直接跳转到登录页面)
- //挂载路由导航守卫
- router.beforeEach((to, from, next) => {
- //to将要访问的路径
- //from从哪个路径跳转而来
- //next放心函数 next()直接放行 next('/login')强制访问
- if (to.path === '/login') return next();
- //获取token
- const tokenStr = window.localStorage.getItem('token');
- if (!tokenStr) return next('/login')
- next()
- })