學生一枚,做爲學習和總結。若是有哪些不對的地方,還請指教javascript
HTTP
協議是無狀態的協議。一旦數據交換完畢,客戶端與服務器端的鏈接就會關閉,再次交換數據須要創建新的鏈接。html
爲解決這個問題,有了cookie
出現vue
Cookie
是由服務器端生成,發送給User-Agent
(通常是瀏覽器),(通知瀏覽器設置一下cookie
),瀏覽器自動會將Cookie
以進行保存(以key/value
的形式)。當下次請求同一網站時也會自動發送該Cookie
給服務器,即添加在請求頭部。java
存放在瀏覽器端node
const http = require("http")
http.createServer((req, res) => {
// 觀察cookie是否存在 若是存在就打印cookie
console.log('cookie:', req.headers.cookie)
// 設置cookie
res.setHeader('Set-Cookie', 'cookie=abc;')
res.end('hello cookie!!')
}).listen(3000)
複製代碼
第一次 請求的時候 發現沒有cookie
,就進行了設置ios
第二次請求,發現有cookie
了,就直接輸出了git
cookie
實現,存放在服務端cookieId
,其餘的保存在服務器中// principle
const http = require("http")
const session = {} // 用來存放cookie
http.createServer((req, res) => {
// 觀察cookie存在
console.log('cookie:', req.headers.cookie)
const sessionKey = 'sid'
const cookie = req.headers.cookie
if (cookie && cookie.indexOf(sessionKey) > -1) { // 證實cookie 存在
res.end('Come Back ')
// 簡略寫法未必具備通用性
const pattern = new RegExp(`${sessionKey}=([^;]+);?\s*`) // 正則表達式對象 判斷是否又sid = XX等
console.log(pattern)
const sid = pattern.exec(cookie)[1] // 檢索字符串中指定的值。返回找到的值
console.log('session:', sid, session, session[sid])
} else {
const sid = (Math.random() * 99999999).toFixed()
// 設置cookie
res.setHeader('Set-Cookie', `${sessionKey}=${sid};`)
session[sid] = {name: 'oldWang'}
res.end('Hello')
}
res.end('hello cookie!!')
}).listen(3000)
複製代碼
瀏覽器不存在cookie 的時候,走else
,隨機設置一個sid
,(通常是本身設置,儘可能麻煩一點),而後 設置cookie
, 在session
集合中保存用戶信息,(通常存到數據庫裏面), 最後返回結果github
第二次進入的時候,會走if
,進行取值判斷。web
Session不足
,服務器存在狀態cookie
只存在於瀏覽器)<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<div><input v-model="username"/> <input v-model="password"/></div>
<div>
<button @click="login">登錄</button>
<button @click="logout">退出</button>
<button @click="getUser" >獲取用戶</button>
</div>
<div>
<button @click="logs=[]">清除頁面</button>
</div>
<ul>
<li v-for="(log,idx) in logs" :key="idx"> {{ log }}</li>
</ul>
</div>
<script> axios.defaults.baseURL = 'http://localhost:3000' axios.defaults.withCredentials = true axios.interceptors.request.use(config => { const token = window.localStorage.getItem("token"); if (token) { // 判斷是否存在token,若是存在的話,則每一個http header都加上token // Bearer是JWT的認證頭部信息 config.headers.common["Authorization"] = "Bearer " + token; } return config; }, err => { return Promise.reject(err); }); axios.interceptors.response.use(response => { app.logs.push(JSON.stringify(response.data)); return response; }, err => { app.logs.push(JSON.stringify(response.data)); return Promise.reject(err); }); var app = new Vue({ el: "#app", data: { username: "admin", password: "admin", logs: [] }, methods: { login: async function () { const res = await axios.post("/users/login-token", { username: this.username, password: this.password }); localStorage.setItem("token", res.data.token); }, logout: async function () { this.logs.push('退出登錄') localStorage.removeItem("token"); }, getUser: async function () { await axios.get("/users/getUser-token"); } } }); </script>
</body>
</html>
複製代碼
const Koa = require('koa')
const router = require('koa-router')() // koa路由
const jwt = require("jsonwebtoken")
const jwtAuth = require("koa-jwt")
const secret = "it's a secret"
const cors = require('koa2-cors')
// https://www.jb51.net/article/135924.htm 跨域參考
const bodyParser = require('koa-bodyparser') // 不支持table,支持json
const static = require('koa-static')
const app = new Koa();
app.keys = ['some secret'];
app.use(cors({credentials: true})) // 解決跨域
app.use(static(__dirname + '/'));
app.use(bodyParser())
router.post("/users/login-token", async ctx => {
const {body} = ctx.request;
console.log(body)
//登陸邏輯,略略
// 設置session
const userinfo = body.username;
ctx.body = {
message: "登陸成功", user: userinfo,
// ⽣生成 token 返回給客戶端
token: jwt.sign({
data: userinfo,
// 設置 token 過時時間,一⼩小時後,秒爲單位
exp: Math.floor(Date.now() / 1000) + 60 * 60
}, secret)
};
})
router.get("/users/getUser-token", jwtAuth({secret}), async ctx => {
// 驗證經過,state.user
console.log(ctx.state.user);
//獲取session
ctx.body = {message: "獲取數據成功", userinfo: ctx.state.user.data};
});
app.use(router.routes());
app.use(router.allowedMethods());
app.listen(3000);
複製代碼
jsonwebtoken github正則表達式