后端
1、先安装phpjwt(需要composer安装)
composer require firebase/php-jwt
2、验证类
$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、公共类统一验证
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返回给前端)
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()
})