蝙蝠岛资源网 Design By www.hbtsch.com
初始于登录页面
Home.vue
<template> <div class="home"> </div> </template> <script> // @ is an alias to /src import HelloWorld from '@/components/HelloWorld.vue' import axios from 'axios'; export default { name: 'home', components: { HelloWorld }, created(){ axios.get('/api/userinfo').then(res=>console.log(res.data)) } } </script>
About.vue
<template> <div class="about"> <h1>This is an about page</h1> </div> </template>
login.vue
<template> <div> <div class="logo"> <img src="/UploadFiles/2021-04-02/logo-new.png">/service/user
import axios from "axios"; export default { login(user) { return axios.get("/api/login", { params: user }) .then(({ data }) => data); } };App.vue
<template> <div id="app"> <div id="nav"> <router-link to="/">Home</router-link> | <router-link to="/about">About</router-link> <button v-if="$store.state.user.isLogin" @click="logout">注销</button> </div> <router-view/> </div> </template> <script> export default { methods: { logout() { this.$store.dispatch('logout') } }, } </script> <style> #app { font-family: "Avenir", Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; } </style>cube-ui组件的引用 cube-ui.js
import Vue from 'vue' // By default we import all the components. // Only reserve the components on demand and remove the rest. // Style is always required. import { /* eslint-disable no-unused-vars */ Style, // basic Button, Loading, Tip, Toolbar, TabBar, TabPanels, // form Checkbox, CheckboxGroup, Checker, Radio, RadioGroup, Input, Textarea, Select, Switch, Rate, Validator, Upload, Form, // popup Popup, Toast, Picker, CascadePicker, DatePicker, TimePicker, SegmentPicker, Dialog, ActionSheet, Drawer, ImagePreview, // scroll Scroll, Slide, IndexList, Swipe, Sticky, ScrollNav, ScrollNavBar } from 'cube-ui' Vue.use(Button) Vue.use(Loading) Vue.use(Tip) Vue.use(Toolbar) Vue.use(TabBar) Vue.use(TabPanels) Vue.use(Checkbox) Vue.use(CheckboxGroup) Vue.use(Checker) Vue.use(Radio) Vue.use(RadioGroup) Vue.use(Input) Vue.use(Textarea) Vue.use(Select) Vue.use(Switch) Vue.use(Rate) Vue.use(Validator) Vue.use(Upload) Vue.use(Form) Vue.use(Popup) Vue.use(Toast) Vue.use(Picker) Vue.use(CascadePicker) Vue.use(DatePicker) Vue.use(TimePicker) Vue.use(SegmentPicker) Vue.use(Dialog) Vue.use(ActionSheet) Vue.use(Drawer) Vue.use(ImagePreview) Vue.use(Scroll) Vue.use(Slide) Vue.use(IndexList) Vue.use(Swipe) Vue.use(Sticky) Vue.use(ScrollNav) Vue.use(ScrollNavBar)cube-ui的样式 theme.styl
@require "~cube-ui/src/common/stylus/var/color.styl" // action-sheet $action-sheet-color := $color-grey $action-sheet-active-color := $color-orange $action-sheet-bgc := $color-white $action-sheet-active-bgc := $color-light-grey-opacity $action-sheet-title-color := $color-dark-grey $action-sheet-space-bgc := $color-mask-bg /// picker style $action-sheet-picker-cancel-color := $color-light-grey $action-sheet-picker-cancel-active-color := $color-light-grey-s // bubble // button $btn-color := $color-white $btn-bgc := $color-regular-blue $btn-bdc := $color-regular-blue $btn-active-bgc := $color-blue $btn-active-bdc := $color-blue $btn-disabled-color := $color-white $btn-disabled-bgc := $color-light-grey-s $btn-disabled-bdc := $color-light-grey-s /// primary $btn-primary-color := $color-white $btn-primary-bgc := $color-orange $btn-primary-bdc := $color-orange $btn-primary-active-bgc := $color-dark-orange $btn-primary-active-bdc := $color-dark-orange /// light $btn-light-color := $color-grey $btn-light-bgc := $color-light-grey-sss $btn-light-bdc := $color-light-grey-sss $btn-light-active-bgc := $color-active-grey $btn-light-active-bdc := $color-active-grey /// outline $btn-outline-color := $color-grey $btn-outline-bgc := transparent $btn-outline-bdc := $color-grey $btn-outline-active-bgc := $color-grey-opacity $btn-outline-active-bdc := $color-grey /// outline-primary $btn-outline-primary-color := $color-orange $btn-outline-primary-bgc := transparent $btn-outline-primary-bdc := $color-orange $btn-outline-primary-active-bgc := $color-orange-opacity $btn-outline-primary-active-bdc := $color-dark-orange // toolbar $toolbar-bgc := $color-light-grey-sss $toolbar-active-bgc := $color-active-grey // checkbox $checkbox-color := $color-grey $checkbox-icon-color := $color-light-grey-s /// checked $checkbox-checked-icon-color := $color-orange $checkbox-checked-icon-bgc := $color-white /// disabled $checkbox-disabled-icon-color := $color-light-grey-ss $checkbox-disabled-icon-bgc := $color-light-grey-ss // checkbox hollow $checkbox-hollow-checked-icon-color := $color-orange $checkbox-hollow-disabled-icon-color := $color-light-grey-ss // checkbox-group $checkbox-group-bgc := $color-white $checkbox-group-horizontal-bdc := $color-light-grey-s // radio $radio-group-bgc := $color-white $radio-group-horizontal-bdc := $color-light-grey-s $radio-color := $color-grey $radio-icon-color := $color-light-grey-s /// selected $radio-selected-icon-color := $color-white $radio-selected-icon-bgc := $color-orange /// disabled $radio-disabled-icon-bgc := $color-light-grey-ss // radio hollow $radio-hollow-selected-icon-color := $color-orange $radio-hollow-disabled-icon-color := $color-light-grey-ss // dialog $dialog-color := $color-grey $dialog-bgc := $color-white $dialog-icon-color := $color-regular-blue $dialog-icon-bgc := $color-background $dialog-title-color := $color-dark-grey $dialog-close-color := $color-light-grey $dialog-btn-color := $color-light-grey $dialog-btn-bgc := $color-white $dialog-btn-active-bgc := $color-light-grey-opacity $dialog-btn-highlight-color := $color-orange $dialog-btn-highlight-active-bgc := $color-light-orange-opacity $dialog-btn-disabled-color := $color-light-grey $dialog-btn-disabled-active-bgc := transparent $dialog-btns-split-color := $color-row-line // index-list $index-list-bgc := $color-white $index-list-title-color := $color-dark-grey $index-list-anchor-color := $color-light-grey $index-list-anchor-bgc := #f7f7f7 $index-list-item-color := $color-dark-grey $index-list-item-active-bgc := $color-light-grey-opacity $index-list-nav-color := $color-grey $index-list-nav-active-color := $color-orange // loading // picker $picker-bgc := $color-white $picker-title-color := $color-dark-grey $picker-subtitle-color := $color-light-grey $picker-confirm-btn-color := $color-orange $picker-confirm-btn-active-color := $color-light-orange $picker-cancel-btn-color := $color-light-grey $picker-cancel-btn-active-color := $color-light-grey-s $picker-item-color := $color-dark-grey // popup $popup-mask-bgc := rgb(37, 38, 45) $popup-mask-opacity := .4 //scroll // slide $slide-dot-bgc := $color-light-grey-s $slide-dot-active-bgc := $color-orange // time-picker // tip $tip-color := $color-white $tip-bgc := $color-dark-grey-opacity // toast $toast-color := $color-light-grey-s $toast-bgc := rgba(37, 38, 45, 0.9) // upload $upload-btn-color := $color-grey $upload-btn-bgc := $color-white $upload-btn-active-bgc := $color-light-grey-opacity $upload-btn-box-shadow := 0 0 6px 2px $color-grey-opacity $upload-btn-border-color := #e5e5e5 $upload-file-bgc := $color-white $upload-file-remove-color := rgba(0, 0, 0, .8) $upload-file-remove-bgc := $color-white $upload-file-state-bgc := $color-mask-bg $upload-file-success-color := $color-orange $upload-file-error-color := #f43530 $upload-file-status-bgc := $color-white $upload-file-progress-color := $color-white // switch $switch-on-bgc := $color-orange $switch-off-bgc := $color-white $switch-off-border-color := #e4e4e4 // input $input-color := $color-grey $input-bgc := $color-white $input-border-color := $color-row-line $input-focus-border-color := $color-orange $input-placeholder-color := $color-light-grey-s $input-clear-icon-color := $color-light-grey //textarea $textarea-color := $color-grey $textarea-bgc := $color-white $textarea-border-color := $color-row-line $textarea-focus-border-color := $color-orange $textarea-outline-color := $color-orange $textarea-placeholder-color := $color-light-grey-s $textarea-indicator-color := $color-light-grey-s // validator $validator-msg-def-color := #e64340 // select $select-color := $color-grey $select-bgc := $color-white $select-disabled-color := #b8b8b8 $select-disabled-bgc := $color-light-grey-opacity $select-border-color := $color-light-grey-s $select-border-active-color := $color-orange $select-icon-color := $color-light-grey $select-placeholder-color := $color-light-grey-s // swipe $swipe-btn-color := $color-white // form $form-color := $color-grey $form-bgc := $color-white $form-invalid-color := #e64340 $form-group-legend-color := $color-light-grey $form-group-legend-bgc := $color-background $form-label-required-color := #e64340 // drawer $drawer-color := $color-dark-grey $drawer-title-bdc := $color-light-grey-ss $drawer-title-bgc := $color-white $drawer-panel-bgc := $color-white $drawer-item-active-bgc := $color-light-grey-opacity // scroll-nav $scroll-nav-bgc := $color-white $scroll-nav-color := $color-grey $scroll-nav-active-color := $color-orange // image-preview $image-preview-counter-color := $color-white // tab-bar & tab-panel $tab-color := $color-grey $tab-active-color := $color-dark-orange $tab-slider-bgc := $color-dark-orangeaxios 请求响应拦截器 interceptor.js
import axios from "axios"; export default function(vm) { axios.interceptors.request.use(config => { const token = localStorage.getItem("token"); if (token) { config.headers.Authorization = "Bearer " + token; } return config; }); axios.interceptors.response.use(null, err => { if (err.response.status === 401) { // 清空 vm.$store.dispatch("logout"); // 跳转 vm.$router.push("/login"); } return Promise.reject(err); }); }路由守卫 路由 router.js
import Vue from "vue"; import Router from "vue-router"; import Home from "./views/Home.vue"; import Login from "./views/Login.vue"; Vue.use(Router); const router = new Router({ mode: "history", base: process.env.BASE_URL, routes: [ { path: "/", name: "home", component: Home }, { path: "/login", name: "login", component: Login }, { path: "/about", name: "about", meta: { auth: true }, // 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") } ] }); router.beforeEach((to, from, next) => { if (to.meta.auth) { // 只要本地有token就认为登录了 const token = localStorage.getItem("token"); if (token) { next(); } else { // 未登录 next({ path: "/login", query: { redirect: to.path } }); } } else { next(); } }); export default router;mock数据 或mock-easy vue.config.js
module.exports = { css: { loaderOptions: { stylus: { "resolve url": true, import: ["./src/theme"] } } }, pluginOptions: { "cube-ui": { postCompile: true, theme: false } }, configureWebpack: { devServer: { proxy: { "/api": { target: "http://127.0.0.1:3000/", changOrigin: true } }, // before(app) { // app.get("/api/login", (req, res) => { // const { username, password } = req.query; // if (username === "kaikeba" && password === "123") { // res.json({ code: 1, token: "jilei" }); // } else { // res.status(401).json({ code: 0, message: "用户名或密码错误" }); // } // }); // 中间件函数 // function auth(req, res, next) { // if (req.headers.token) { // next(); // } else { // res.status(401); 如果设置这个 只是设置状态,并没有返回前端,会导致前端等待状态 res.sendStatus(401) 这个正确的 // } // } // app.get("/api/userinfo", auth, (req, res) => { // res.json({ code: 1, data: { name: "Jerry" } }); // }); // } } } };登录动作,store.js
index.js
import user from './user' Vue.use(Vuex) export default new Vuex.Store({ modules: {user} })user.js
import us from '@/service/user' export default { state: { isLogin: !!localStorage.getItem("token") }, mutations: { setLoginState(state, val) { state.isLogin = val; } }, actions: { login({commit}, userInfo) { return us.login(userInfo).then(({token}) => { // code, token if (token) { // 登录成功 commit('setLoginState', true) localStorage.setItem('token', token) return true } return false }) }, logout({commit}){ localStorage.removeItem('token') commit('setLoginState', false) } } }gitignore
.DS_Store node_modules /dist # local env files .env.local .env.*.local # Log files npm-debug.log* yarn-debug.log* yarn-error.log* # Editor directories and files .idea .vscode *.suo *.ntvs* *.njsproj *.sln *.sw*main.js
import Vue from 'vue' import './cube-ui' import App from './App.vue' import store from './store' import router from './router' import interceptor from './interceptor' Vue.config.productionTip = false const app = new Vue({ store, router, render: h => h(App) }).$mount('#app'); interceptor(app);深入理解令牌机制
Bearer Token规范
概念:描述在http访问OAuth2保护资源时如何使用令牌的规范
特点:令牌就是身份证明,无需证明令牌的所有权
具体规定:在请求头中定义AuthorizationAuthorization: Bearer <token>Json Web Token规范
概念:令牌的具体定义方式
规定:令牌由三部分构成 “头”,“载荷”,“签名”
头:包含加密算法。令牌类型等信息
载荷:包含用户信息。签发时间和过期时间等信息,base64编码
签名:根据头 和载荷及秘钥加密得到的哈希串Hmac Sha1 256server/server.js
const Koa = require("koa"); const Router = require("koa-router"); const jwt = require("jsonwebtoken"); const jwtAuth = require("koa-jwt"); const secret = "it's a secret"; const app = new Koa(); const router = new Router(); router.get("/api/login", async ctx => { const { username, passwd } = ctx.query; console.log(username, passwd); if (username == "kaikeba" && passwd == "123") { // 生成令牌 const token = jwt.sign( { data: { name: "kaikeba" }, // 用户信息数据 exp: Math.floor(Date.now() / 1000) + 60 * 60 // 过期时}, secret ); ctx.body = { code: 1, token }; } else { ctx.status = 401; ctx.body = { code: 0, message: "用户名或者密码错误" }; } }); router.get( "/api/userinfo", jwtAuth({ secret }), async ctx => { ctx.body = { code: 1, data: { name: "jerry", age: 20 } }; } ); app.use(router.routes()); app.listen(3000);
蝙蝠岛资源网 Design By www.hbtsch.com
广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
蝙蝠岛资源网 Design By www.hbtsch.com
暂无vue中的使用token的方法示例的评论...
稳了!魔兽国服回归的3条重磅消息!官宣时间再确认!
昨天有一位朋友在大神群里分享,自己亚服账号被封号之后居然弹出了国服的封号信息对话框。
这里面让他访问的是一个国服的战网网址,com.cn和后面的zh都非常明白地表明这就是国服战网。
而他在复制这个网址并且进行登录之后,确实是网易的网址,也就是我们熟悉的停服之后国服发布的暴雪游戏产品运营到期开放退款的说明。这是一件比较奇怪的事情,因为以前都没有出现这样的情况,现在突然提示跳转到国服战网的网址,是不是说明了简体中文客户端已经开始进行更新了呢?
更新日志
2024年12月24日
2024年12月24日
- 小骆驼-《草原狼2(蓝光CD)》[原抓WAV+CUE]
- 群星《欢迎来到我身边 电影原声专辑》[320K/MP3][105.02MB]
- 群星《欢迎来到我身边 电影原声专辑》[FLAC/分轨][480.9MB]
- 雷婷《梦里蓝天HQⅡ》 2023头版限量编号低速原抓[WAV+CUE][463M]
- 群星《2024好听新歌42》AI调整音效【WAV分轨】
- 王思雨-《思念陪着鸿雁飞》WAV
- 王思雨《喜马拉雅HQ》头版限量编号[WAV+CUE]
- 李健《无时无刻》[WAV+CUE][590M]
- 陈奕迅《酝酿》[WAV分轨][502M]
- 卓依婷《化蝶》2CD[WAV+CUE][1.1G]
- 群星《吉他王(黑胶CD)》[WAV+CUE]
- 齐秦《穿乐(穿越)》[WAV+CUE]
- 发烧珍品《数位CD音响测试-动向效果(九)》【WAV+CUE】
- 邝美云《邝美云精装歌集》[DSF][1.6G]
- 吕方《爱一回伤一回》[WAV+CUE][454M]