建设主管部门门户网站,虚拟网站怎么做的,微信推广多少钱一次,wordpress图片0x0在前后端完全分离的情况下#xff0c;Vue项目中实现token验证大致思路如下#xff1a;
1、第一次登录的时候#xff0c;前端调后端的登陆接口#xff0c;发送用户名和密码
2、后端收到请求#xff0c;验证用户名和密码#xff0c;验证成功#xff0c;就给前端返回一个…在前后端完全分离的情况下Vue项目中实现token验证大致思路如下
1、第一次登录的时候前端调后端的登陆接口发送用户名和密码
2、后端收到请求验证用户名和密码验证成功就给前端返回一个token
3、前端拿到token将token存储到localStorage和vuex中并跳转路由页面
4、前端每次跳转路由就判断 localStroage 中有无 token 没有就跳转到登录页面有则跳转到对应路由页面
5、每次调后端接口都要在请求头中加token
6、后端判断请求头中有无token有token就拿到token并验证token验证成功就返回数据验证失败例如token过期就返回401请求头中没有token也返回401
7、如果前端拿到状态码为401就清除token信息并跳转到登录页面
. . . . 实操代码
1.login页(账号密码登录完成后将后台返回的token储存到本地)最后附上了登录页完整代码
handleSubmit(e) {var that this;this.userName this.userName.trim();this.password this.password.trim();if (this.userName this.password ) {that.$message.warning(账号和密码无内容);return;}if (this.userName ) {that.$message.warning(账号无内容);return;}if (this.password ) {that.$message.warning(密码无内容);return;}var username document.getElementById(username).value;var password document.getElementById(password).value;e.preventDefault();this.form.validateFields((err, values) {//这一步将用户名储存在vuex ||||||||||目前域账号和用户名都是写一样了||||||||||||||||||||||||||||||||||||||||||||||||axios.post(this.$store.state.windowCONTENT sysConfig/getUserRole, {loginUser: this.userName,}).then((res) {if (res.data.success 0) {//有权限this.$store.state.loginUser this.userName;this.$store.state.userName this.userName;this.$store.state.roleCode res.data.data.roleCode;//存入tokenlocalStorage.setItem(token,JSON.stringify(res.data.data.token));// console.log(res.data.data,this.$store.state.roleCode);if (!err) {this.$router.push(/layout);this.$message.success(登陆成功);}} else {//无权限this.$message.error(res.data.data);}});});},2.marn.js配置请求拦截器每次请求携带token后端进行验证配置响应拦截器根据后端验证返回的结果判断token是否过期
import babel-polyfill;
import Vue from vue;
import App from ./App.vue;
import router from ./router;
import store from ./store;
import { Button, message } from ant-design-vue;
import Antd from ant-design-vue;
import ant-design-vue/dist/antd.css;
import zh_CN from ant-design-vue/lib/locale-provider/zh_CN;
import moment from moment;
import moment/locale/zh-cn;
import ./assets/iconfont/iconfont;
import axios from axios;Vue.component(Button.name, Button);Vue.config.productionTip false;Vue.use(Antd);
Vue.prototype.$message message;// 设置axios全局默认的BASE-URL 只要设置了全局的默认base_url以后的请求会自动拼接上base_url
//axios.defaults.baseURL http://localhost:8888/api/private/v1/// 配置axios的请求拦截器-(每次在请求头上携带后台分配的token-后台判断token是否有效等问题)
axios.interceptors.request.use(function(config) {// 在发送请求之前做些什么// console.log(请求到了哟, config.headers.Authorization)// 统一的给config设置 tokenconfig.headers.Authorization JSON.parse(localStorage.getItem(token));config.headers[Token] JSON.parse(localStorage.getItem(token));return config;},function(error) {// 对请求错误做些什么return Promise.reject(error);}
);//响应拦截器 与后端定义状态是100时候是错误 跳转到登录界面
axios.interceptors.response.use(function (response) {// 对响应数据做点什么console.log(response)//当返回信息为未登录或者登录失效的时候重定向为登录页面if (response.data.status 100 || response.data.message 用户未登录或登录超时请登录) {router.push({path: /login,querry: { redirect: router.currentRoute.fullPath }//从哪个页面跳转})message.warning(response.data.message);}return response;
}, function (error) {// 对响应错误做点什么return Promise.reject(error)
})moment.locale(zh-cn);
new Vue({zh_CN,router,watch: {// 监听路由变化$route.path: function(newVal, oldVal) {console.log(new_path ${newVal}, old_path ${oldVal});},},store,render: (h) h(App),
}).$mount(#app);
3.router.js配置导航守卫有token或者是去登录页就通过否则定向到登录页
import Vue from vue
import VueRouter from vue-router
import Home from ../views/Home.vue
import Layout from ../components/Layout.vue
import Login from ../components/Login.vueVue.use(VueRouter)const routes [{path: /,redirect: login},{path: /login,name: Login,component: Login},{path: /layout,name: Layout,component: Layout},{path: /about,name: About,// route level code-splitting// this generates a separate chunk (about.[hash].js) for this route// which is lazy-loaded when the route is visited.component: () import(/* webpackChunkName: about */ ../views/About.vue)}
]const router new VueRouter({routes
})// to 到哪去
// from 从哪来
// next 是否放行 next() 放行 next(/login) 拦截到登录
// 如果准备去登录, 不需要拦截
// 如果已经登录过了, 有token, 不需要拦截
// 如果不是去登陆, 且没有 token, 拦截到登录页
router.beforeEach((to, from, next) {const token JSON.parse(localStorage.getItem(token));console.log(token);// console.log(to)if (to.path /login || token) {next()} else {next(/login)}
})export default router
4.退出清除本地储存的token
//退出登录signOut() {console.log(点击了退出, this.$route.query.sessionId);localStorage.clear(token);this.$route.push(/)//将vuex的数据初始化和清除默认的数据},. . . . . .
完整登录页
templatediv classlogindiv classlogoimg :srclogoUrl alt //divdiv classwelcomeWELCOME/divdiv classplatform欢迎来到XX平台/divdiv classboxa-formidcomponents-form-demo-normal-login:formformclasslogin-formsubmit.preventhandleSubmita-form-itemdiv classl-bor登录/div/a-form-itema-form-itemdiv classaccount账号/div/a-form-itema-form-itema-input v-modeluserName allowClear classuser-name placeholder请输入!-- v-decorator[userName,{ rules: [{ required: true, message: 请输入账号名! }] },]--a-icon slotprefix typeuser stylecolor: rgba(0,0,0,.25) //a-input/a-form-itema-form-itemdiv classp-box密码/div/a-form-itema-form-item!-- a-inputv-decorator[password,{ rules: [{ required: true, message: Please input your Password! }] },]typepasswordplaceholderPassworda-icon slotprefix typelock stylecolor: rgba(0,0,0,.25) //a-input--a-input-passwordv-modelpasswordallowClearclasspasswordtypepasswordplaceholder请输入!-- v-decorator[password,{ rules: [{ required: true, message: 请输入密码! }] },]--a-icon slotprefix typelock stylecolor: rgba(0,0,0,.25) //a-input-password/a-form-itema-form-item!-- a-checkboxv-decorator[remember,{valuePropName: checked,initialValue: true,},]Remember me/a-checkbox--!-- a classlogin-form-forgot hrefForgot password/a --a-button:style{opacity: (btnFlag ? .5 : 1)}typeprimaryhtml-typesubmitclasslogin-form-buttonspanstylewidth:58px;height:24px;font-size:17px;font-family:PingFang-SC-Light,PingFang-SC;font-weight:300;color:rgba(255,255,255,1);line-height:24px;text-shadow:0px 2px 3px rgba(62,32,201,0.1);登录/span/a-button!-- Or --!-- a hrefregister now!/a --/a-form-item/a-form/divdiv classbottom/div/div
/templatescript
import axios from axios;
export default {data() {return {logoUrl: require(../assets/logo.svg),userName: ,password: ,btnFlag: true,flagColor: {opacity: 0.5,},};},beforeCreate() {this.form this.$form.createForm(this, { name: normal_login });},created() {},methods: {handleSubmit(e) {var that this;this.userName this.userName.trim();this.password this.password.trim();if (this.userName this.password ) {that.$message.warning(账号和密码无内容);return;}if (this.userName ) {that.$message.warning(账号无内容);return;}if (this.password ) {that.$message.warning(密码无内容);return;}// jucenter.submit({name:this.userName,pwd:this.password});e.preventDefault();this.form.validateFields((err, values) {//这一步将用户名储存在vuex ||||||||||目前域账号和用户名都是写一样了||||||||||||||||||||||||||||||||||||||||||||||||console.log(this.userName, this.password);axios.post(this.$store.state.windowCONTENT sysConfig/getUserRole,{loginUser: this.userName}).then(res {if (res.data.success 0) {//有权限this.$store.state.loginUser this.loginUser;this.$store.state.userName res.data.data.userName;this.$store.state.roleCode res.data.data.roleCode;//存入tokenlocalStorage.setItem(token,JSON.stringify(res.data.data.token));if (!err) {this.$router.push(/layout);console.log(111);this.$message.success(登陆成功)}} else {//无权限this.$message.error(res.data.data)}})});},},watch: {userName: function (v1, v2) {var that this;if (v1 this.password) {this.btnFlag false;console.log(this.btnFlag);} else {this.btnFlag true;console.log(this.btnFlag);}},password: function (v1, v2) {var that this;if (v1 this.userName) {this.btnFlag false;console.log(this.btnFlag);} else {this.btnFlag true;console.log(this.btnFlag);}},},
};
/script
style langless
.login {position: relative;text-align: left;height: 100%;background: linear-gradient(154deg,rgba(119, 182, 244, 1) 0%,rgba(66, 106, 229, 1) 100%);// background-color: pink!important;// overflow: hidden;.logo {position: absolute;top: 21px;left: 35px;}.welcome {position: absolute;bottom: 60%;left: 10%;width: 416px;height: 100px;font-size: 72px;font-family: PingFang-SC-Regular, PingFang-SC;font-weight: 400;color: rgba(255, 255, 255, 1);line-height: 100px;letter-spacing: 6px;}.platform {position: absolute;bottom: 53%;left: 10%;width: 313px;height: 33px;font-size: 24px;font-family: PingFang-SC-Light, PingFang-SC;font-weight: 300;color: rgba(255, 255, 255, 1);line-height: 33px;letter-spacing: 2px;}.box {position: absolute;bottom: 10%;right: 0;// margin: 0 auto;// margin-bottom: 151px; //定位高度-----↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓margin-right: 21%;width: 370px;height: 500px;border-radius: 10px;background: rgba(252, 251, 255, 1);padding: 0px 53px;//去除默认下边距.ant-form-item {margin-bottom: 0;}//输入框.ant-input-affix-wrapper .ant-input:not(:last-child) {height: 36px;font-size: 14px;font-family: PingFang-SC-Regular, PingFang-SC;font-weight: 400;color: rgba(53, 58, 64, 1);// background-color: pink;}//登录按钮#components-form-demo-normal-login .login-form-button {width: 264px;height: 44px;background: linear-gradient(90deg,rgba(60, 163, 247, 1) 0%,rgba(28, 106, 235, 1) 100%);box-shadow: 0px 2px 3px 0px rgba(62, 32, 201, 0.1);border-radius: 6px;}.l-bor {margin-left: -53px;margin-top: 50px;line-height: 25px;border-left: 6px solid rgba(28, 106, 235, 1);padding-left: 47px;font-size: 18px;font-family: PingFang-SC-Medium, PingFang-SC;font-weight: 500;color: rgba(53, 58, 64, 1);letter-spacing: 1px;}// .account{// margin-top: 58px;// width:27px;// height:17px;// font-size:12px;// font-family:PingFang-SC-Light,PingFang-SC;// font-weight:300;// color:rgba(53,58,64,1);// line-height:17px;// letter-spacing:1px;// }.ant-form-item:nth-child(2) {position: absolute;top: 133px;.account {width: 27px;height: 17px;font-size: 12px;font-family: PingFang-SC-Light, PingFang-SC;font-weight: 300;color: rgba(53, 58, 64, 1);line-height: 17px;letter-spacing: 1px;}}.ant-form-item:nth-child(3) {position: absolute;top: 160px;width: 264px;}.ant-form-item:nth-child(4) {position: absolute;top: 230px;width: 264px;.p-box {width: 27px;height: 17px;font-size: 12px;font-family: PingFang-SC-Light, PingFang-SC;font-weight: 300;color: rgba(53, 58, 64, 1);line-height: 17px;letter-spacing: 1px;}}.ant-form-item:nth-child(5) {position: absolute;top: 257px;width: 264px;}.ant-form-item:nth-child(6) {position: absolute;top: 376px;width: 264px;}}.bottom {position: absolute;bottom: 0;width: 100%;// height: 151px; //固定高度-----↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑height: 10%; //固定高度-----↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑background: linear-gradient(360deg,rgba(75, 118, 232, 0) 0%,rgba(57, 98, 224, 0.41) 100%);}
}
#components-form-demo-normal-login .login-form {max-width: 300px;
}
#components-form-demo-normal-login .login-form-forgot {float: right;
}
#components-form-demo-normal-login .login-form-button {width: 100%;
}
/style