koa2+vue
- 用vue-cli搭建前端項目
- 用koa2搭建后臺,給前端提供數據訪問接口
項目結構
- 用vue-cli 搭建的項目,紅色框中是新建的文件夾用于存放koa
- 剩下的文件在寫項目中慢慢增加,最初就是這樣的
- 之后將項目跑起來,看一下有沒有問題(這里就當作沒有問題)
前端
- 這里選用Element-ui和vue搭配
- 這里采用的是element-UI的完整引入,如果小伙伴想用按需加載的話 參考按需引入
- 登陸頁面就不介紹了 大家可以直接用(components/login.vue)
安裝element-ui
npm i element-ui -S
在src/main.js中引入
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);
登陸
- 安裝axios用于前后臺的數據傳輸
npm install --save axios
- 在main.js中配置全局的axios
- 在src下新建一個axios文件夾,配置攔截器 和 全局地址 token
import axios from 'axios' // axios引用
import qs from 'qs'
// axios.defaults.baseURL = 'http://localhost:3000'; // 全局的地址,因為我的koa監聽端口是3000, 這里可以按照大家自己的來配置
// axios.defaults.headers.common['Authorization'] = AUTH_TOKEN; //這是配置token
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
// 添加請求攔截器
axios.interceptors.request.use(function (config) {
// 在發送請求之前做些什么
if(config.method === 'post'){
config.data = qs.stringify(config.data)
}
return config;
}, function (error) {
// 對請求錯誤做些什么
return Promise.reject(error);
});
// 添加響應攔截器
axios.interceptors.response.use(function (response) {
// 對響應數據做點什么
return response;
}, function (error) {
// 對響應錯誤做點什么
return Promise.reject(error);
});
export default axios;
- 在src下新建一個api文件夾,存放訪問后臺的地址
import axios from 'axios';
export default{
denglu: (data) => {
return axios.post('/login', data)
}
}
前端先告一段落,我們來配置后臺接口
搭建koa2
學習koa
- 安裝koa2 koa-bodyparser koa-router koa2-cors
npm install --save koa koa-bodyparser koa-router koa2-cors
[x] koa-bodyparser:用于接收并解析前臺發送過來的post數據
[x] koa-router:路由
[x] koa2-cors:用來解決前端的跨域
-
搭建koa 在瀏覽器運行localhost:3000 頁面輸出 hello 表示成功了 ??
下面的代碼是驗證koa是否搭建成功,可以跳過
const Koa = require('koa');
const bodyparser = require('koa-bodyparser');
const app = new Koa();
app.use(async (ctx) => {
ctx.body = 'hello';
})
app.listen(3000);
- 接下來 開始搭建koa的路由
const Koa = require('koa');
const bodyparser = require('koa-bodyparser');
const router = require('koa-router')();
const login = require('./router/login.js'); //這是登陸路由的文件
const cors = require('koa2-cors');
const app = new Koa();
app.use(bodyparser())
這是處理前端跨域的配置
app.use(cors({
origin: function (ctx) {
if (ctx.url === '/login') {
return "*"; // 允許來自所有域名請求
}
return 'http://localhost:8080';
},
exposeHeaders: ['WWW-Authenticate', 'Server-Authorization'],
maxAge: 5,
credentials: true,
allowMethods: ['GET', 'POST', 'DELETE'],
allowHeaders: ['Content-Type', 'Authorization', 'Accept'],
}));
router.use('/login',login); //將路由提取出去便于管理
app
.use(router.routes())
.use(router.allowedMethods());
app.listen(3000);
- 接下來就是去配置登陸的路由
const router = require('koa-router')();
router
.post('/', async ctx => {
ctx.body = { //這是向前臺返回的數據 因為沒有連接數據庫所以我們自己定義,后面講連接數據庫
user:'111',
code:1,
status:200
};
});
module.exports = router.routes();
- 接下來 進入src/axios下的文件打開 將注釋的代碼放開
axios.defaults.baseURL = 'http://localhost:3000'; // 全局的地址,因為我的koa監聽端口是3000, 這里可以按照大家自己的來配置
ok 我們開測試一下
可以用postmain 也可以直接在瀏覽器中測試
postmain
postmain.png
chrome瀏覽器 直接在瀏覽器中測試
chrome.png
能取到數據 那就說明沒有問題
接下來開始連接數據庫 數據庫用的是 mysql
創建數據庫
我在本地用的是mamp+navicat 大家可以用自己熟悉的
安裝mysql-pro 一個連接數據庫的中間件
npm install mysql-pro
接下來在創建表
-
需要的字段
id user pass database.png 隨便添加兩個就可以了,這里沒有做驗證,需要的小伙伴可以自己添加這個功能
到此就結束了,我們來驗證一下
-
在koa2/sql下新建一個js文件
const Client = require('mysql-pro'); const db = new Client({ mysql:{ host:'localhost', port:3306, database:'vue-koa2', user:'root', password:'root' } }) module.exports = db;
接下來進入koa2/router下的login.js
看一下我們在前端拿到的數據
因為我們用了中間件koa-bodyparser ,在koa2/router/login.js中這樣寫
```
const router = require('koa-router')();
const db = require('../sql/sql');
router
.post('/', async ctx => {
let user = ctx.request.body //接收前端傳過來的post數據
console.log(user);
ctx.body = {
user:'111',
code:1,
status:200
};
});
module.exports = router.routes();
```
控制臺輸出 { user: '123', pass: '123' }
接下來連接數據數據庫,查詢
const router = require('koa-router')();
const db = require('../sql/sql');
router
.post('/', async ctx => {
let user = ctx.request.body.user;
let pass = ctx.request.body.pass;
// 將接收到的前臺數據和數據庫中的數據匹配
// 如果匹配成功 返回status 200 code 1
// 不成功返回status 1000 code 0
db.query('select * from login where user=? and pass=?;',[user,pass]).then(res => {
console.log(res);
})
ctx.body = {
user:'111',
code:1,
status:200
};
});
module.exports = router.routes();
控制臺輸出[ RowDataPacket { id: 1, user: '111', pass: '111' } ]
表示拿到數據
注意
這是個數組的格式,如果將user返回給前端res[0].user
,
const router = require('koa-router')();
const db = require('../sql/sql');
router
.post('/', async ctx => {
let user = ctx.request.body.user;
let pass = ctx.request.body.pass;
// 將接收到的前臺數據和數據庫中的數據匹配
// 如果匹配成功 返回status 200 code 1
// 不成功返回status 1000 code 0
await db.query('select * from login where user=? and pass=?;', [user, pass]).then(res => {
if (res.length === 0) { // 數據庫中沒有匹配到用戶
ctx.body = {
code: 0,
status: 1000,
msg: 'error'
}
} else { //匹配到用戶
ctx.body = {
user: res[0].user,
code: 1,
status: 200
}
}
})
});
module.exports = router.routes();
以上就是簡單的前后數據交互
接下來講解的是vuex權限驗證和token
token
創建token我們要用到
[x] 驗證token的網站
[x] 創建token中間件
在koa2中新建文件夾token
token下新建一個addtoken.js用于創建token再新建一個proving.js用于驗證token
addtoken
const jwt = require('jsonwebtoken');
const serect = 'token'; //密鑰,不能丟
module.exports = (userinfo) => { //創建token并導出
const token = jwt.sign({
user: userinfo.user,
id: userinfo.id
}, serect, {expiresIn: '1h'});
return token;
};
在router/login中引入
const router = require('koa-router')();
const db = require('../sql/sql');
const addtoken = require('../token/addtoken');
router
.post('/', async ctx => {
let user = ctx.request.body.user;
let pass = ctx.request.body.pass;
// 將接收到的前臺數據和數據庫中的數據匹配
// 如果匹配成功 返回status 200 code 1
// 不成功返回status 1000 code 0
await db.query('select * from login where user=? and pass=?;', [user, pass]).then(res => {
if (res.length === 0) { // 數據庫中沒有匹配到用戶
ctx.body = {
code: 0,
status: 1000,
msg: 'error'
}
} else { //匹配到用戶
let tk = addtoken({user:res[0].user,id:res[0].id}) //token中要攜帶的信息,自己定義
ctx.body = {
tk, //返回給前端
user: res[0].user,
code: 1,
status: 200
}
}
})
});
module.exports = router.routes();
vuex
拿到了后臺的token,我們要做什么呢?
- 存到localStorage中
- 在src/components/login.vue中將token和user存進localStorage中
- 存到vuex中
- npm install --save vuex
這看自己的需求了
回到前端 我們改一下路由
沒改之前
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'login',
component: resolve => require(['@/components/login'],resolve)
},
{
path: '/homes',
name: 'homes',
component: resolve => require(['@/components/homes'],resolve)
}
]
})
改過之后
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router);
const router = new Router({
routes: [
{
path: '/',
name: 'login',
component: resolve => require(['@/components/login'], resolve)
},
{
path: '/homes',
name: 'homes',
meta: {
auth: true
},
component: resolve => require(['@/components/homes'], resolve)
}
]
});
router.beforeEach((to, from, next) => {
if (to.meta.auth) { //權限判斷
if ('進行判斷') { //讀取token值
// 成功
next()
} else {
next({path:'/'})
}
} else {
// 沒有meta.auth 不用管
next()
}
});
export default router;
在路由中要驗證的地方添加meta:{auth:true}
接下來就是創建vuex
在src下新建文件夾vuex
全局引入vuex
-
在vuex中新建store.js文件
import Vue from 'vue'; import Vuex from 'vuex' Vue.use(Vuex); const store = new Vuex.Store({ state:{ user:localStorage.getItem('user') || '', token:localStorage.getItem('token') || null } }); export default store;
-
接下來改一下路由中的權限判斷
router.beforeEach((to, from, next) => { if (to.meta.auth) { //權限判斷 if (localStorage.getItem('token')) { //讀取token值 // 成功 next() } else { next({path:'/'}) } } else { // 沒有meta.auth 不用管 next() } });
在login.vue中接收到數據后添加
localStorage.setItem('token', data.data.tk) //存儲token
localStorage.setItem('user', data.data.user) //存儲用戶
this.LOGIN({
token:data.data.tk,
user:data.data.user
});
這樣就將token拿到了并存進localStorage中,接下來就是將token在發送的時候 添加進頭部中 發送給后臺
-
在axios/axios.js中
axios.defaults.headers.common['Authorization'] = 'Bearer '+ localStorage.getItem('token');
在登陸的時候這樣就會將token發送給后臺了
-
后臺驗證前臺發送的token
const jwt = require('jsonwebtoken'); const serect = 'token'; //密鑰,不能丟 module.exports =(tokens) => { if (tokens){ let toke = tokens.split(' ')[1]; // 解析 let decoded = jwt.decode(toke, serect); return decoded; } };
-
在login.js中,添加
router.get('/test',async (ctx,next) => { let token = ctx.request.header.authorization; if (token){ // 獲取到token let res = proving(token); if (res && res.exp <= new Date()/1000){ ctx.body = { message: 'token過期', code:3 }; } else { ctx.body = { message: '解析成功', code:1 } } } else{ // 沒有取到token ctx.body = { msg:'沒有token', code:0 } } });
項目至此算是告一段落,大家可以把我的項目clone到本地下運行
項目地址
- 運行方式
- 運行vue npm start
- 在koa2下運行app.js node app.js