tp+jwt

后端

1、先安装phpjwt(需要composer安装)

composer require firebase/php-jwt

2、验证类

  1. <?php
  2. namespace appindexcontroller;
  3. use FirebaseJWTJWT;
  4. class Jwttoken
  5. {
  6. //生成token
  7. public function createJwt($username)
  8. {
  9. $key = md5('nobita'); //jwt的签发密钥,验证token的时候需要用到
  10. $time = time();
  11. $expire = $time + 14400; //过期时间
  12. $token = array(
  13. "username" => $username,
  14. "iss" => "",//签发组织
  15. "aud" => "", //签发作者
  16. "iat" => $time, //签发时间
  17. "nbf" => $time, //生效时间
  18. "exp" => $expire
  19. );
  20. $jwt = JWT::encode($token, $key);
  21. return $jwt;
  22. }
  23. //校验jwt权限API
  24. public function verifyJwt($jwt)
  25. {
  26. $key = md5('nobita');
  27. try {
  28. $jwtAuth = json_encode(JWT::decode($jwt, $key, array('HS256')));
  29. $authInfo = json_decode($jwtAuth, true);
  30. $msg = [];
  31. if (!empty($authInfo['username'])) {
  32. $msg = [
  33. 'status' => 0,
  34. 'msg' => 'Token验证通过',
  35. 'username' => $authInfo['username']
  36. ];
  37. } else {
  38. //Token验证不通过,用户不存在
  39. $msg = [
  40. 'status' => 10001,
  41. 'msg' => '当前用户不存在'
  42. ];
  43. }
  44. return json_encode($msg);
  45. } catch (FirebaseJWTSignatureInvalidException $e) {
  46. echo json_encode([
  47. 'status' => 10002,
  48. 'msg' => 'Token无效'
  49. ]);
  50. exit;
  51. } catch (FirebaseJWTExpiredException $e) {
  52. //Token过期
  53. echo json_encode([
  54. 'status' => 10003,
  55. 'msg' => '登录信息已超时,请重新登录'
  56. ]);
  57. exit;
  58. } catch (Exception $e) {
  59. echo json_encode([
  60. 'status' => 10004,
  61. 'msg' => '未知错误'
  62. ]);
  63. exit;
  64. }
  65. }
  66. }

3、公共类统一验证

  1. <?php
  2. namespace appindexcontroller;
  3. use thinkController;
  4. use thinkRequest;
  5. use appindexcontrollerJwttoken;
  6. header('Access-Control-Allow-Origin: *');
  7. header('Access-Control-Allow-Methods:POST, GET, PUT, DELETE, OPTIONS');
  8. header('Access-Control-Allow-Headers:x-requested-with,content-type,Authorization');
  9. class Common extends Controller
  10. {
  11. //定义一个空的登录信息
  12. public $username = null;
  13. public function _initialize()
  14. {
  15. parent::_initialize();
  16. $this->checkToken();
  17. }
  18. public function checkToken()
  19. {
  20. $header = Request::instance()->header();
  21. if (isset($header['authorization'])) {
  22. if ($header['authorization'] == 'null') {
  23. echo json_encode([
  24. 'status' => 10005,
  25. 'msg' => 'Token不存在,拒绝访问'
  26. ]);
  27. exit;
  28. } else {
  29. $token = new Jwttoken;
  30. $checkJwtToken = $token->verifyJwt($header['authorization']);
  31. //验证通过
  32. if (json_decode($checkJwtToken, true)['status'] == 0) {
  33. //验证成功之后 继承了公共类的所有方法都可以直接调用登录用户 不用额外传参
  34. $this->username = json_decode($checkJwtToken, true)['username'];
  35. return true;
  36. }
  37. }
  38. } else {
  39. //Token不存在,拒绝访问
  40. return json_encode([
  41. 'status' => 10006,
  42. 'msg' => '请勿非法登录'
  43. ]);
  44. exit;
  45. }
  46. }
  47. }

4、登录控制器(登录控制器不用继承公共类,登录成功之后把生成的token返回给前端)

  1. <?php
  2. namespace appindexcontroller;
  3. use appindexcontrollerJwttoken;
  4. use thinkController;
  5. use thinkDb;
  6. header('Access-Control-Allow-Origin: *');
  7. header('Access-Control-Allow-Methods:POST, GET, PUT, DELETE, OPTIONS');
  8. header('Access-Control-Allow-Headers:x-requested-with,content-type,Authorization');
  9. class Login extends Controller
  10. {
  11. public function login()
  12. {
  13. if (Request()->isPost()) {
  14. $data = input();
  15. $isset = db('user')->where('username', $data['username'])->find();
  16. if (!$isset) {
  17. return json(['error' => '1000', 'errormsg' => '当前用户不存在']);
  18. }
  19. if (md5($data['password']) != $isset['password']) {
  20. return json(['error' => '1000', 'errormsg' => '密码错误']);
  21. } else {
  22. $token = new Jwttoken();
  23. $user_token = $token->createJwt($isset['username']);
  24. return json(['error' => '0', 'errormsg' => '登录成功', 'token' => $user_token]);
  25. }
  26. }
  27. }
  28. }

前端(vue+element)

1、登录操作(登录成功之后把token存入localStorage)

  1. loginSubmit() {
  2. this.$refs['loginForm'].validate(async valid => {
  3. if (valid) {
  4. const {
  5. data: result
  6. } = await this.$http.post("/index/login/login", this.loginForm)
  7. if (result.error != 0) {
  8. this.$message.error(result.errormsg)
  9. return false;
  10. } else {
  11. this.$message.success(result.errormsg)
  12. window.localStorage.setItem('token', result.token);
  13. this.getuserinfo()
  14. this.gettypelist()
  15. this.getbooklist(0)
  16. this.logindialog = false
  17. this.loginForm = {
  18. username: '',
  19. password: '',
  20. }
  21. }
  22. } else {
  23. return false;
  24. }
  25. });
  26. }

2、在main.js设置请求拦截器和响应拦截器

  1. import Vue from 'vue'
  2. import App from './App.vue'
  3. import router from './router'
  4. import ElementUI from 'element-ui';
  5. import 'element-ui/lib/theme-chalk/index.css';
  6. import axios from 'axios'
  7. Vue.config.productionTip = false
  8. Vue.use(ElementUI);
  9. Vue.prototype.$http = axios
  10. //配置请求根路径
  11. axios.defaults.baseURL = 'http://www.shifuchen.top'
  12. //请求拦截器
  13. axios.interceptors.request.use(config => {
  14. config.headers.Authorization = window.localStorage.getItem('token')
  15. return config
  16. }, error => {
  17. Promise.reject(error)
  18. })
  19. // 添加响应拦截器
  20. axios.interceptors.response.use(response => {
  21. const status = response.data.status
  22. const msg = response.data.msg
  23. if (status > 10000) {
  24. ElementUI.Message({
  25. message: msg,
  26. type: 'error'
  27. });
  28. window.localStorage.clear();
  29. return false;
  30. } else {
  31. return response
  32. }
  33. }, error => {
  34. Promise.reject(error)
  35. });
  36. new Vue({
  37. router,
  38. render: h => h(App)
  39. }).$mount('#app')

3、在路由中挂载路由守卫router/index.js(判断token过期或者不合法直接跳转到登录页面)

  1. //挂载路由导航守卫
  2. router.beforeEach((to, from, next) => {
  3. //to将要访问的路径
  4. //from从哪个路径跳转而来
  5. //next放心函数 next()直接放行 next('/login')强制访问
  6. if (to.path === '/login') return next();
  7. //获取token
  8. const tokenStr = window.localStorage.getItem('token');
  9. if (!tokenStr) return next('/login')
  10. next()
  11. })
原文地址:https://www.cnblogs.com/ianlab/p/14142761.html