樣式可能有點醜,請不要在乎html
express、vue、redis、axios前端
svg-captcha
是一個能夠生成圖形驗證碼的模塊,詳細介紹移步svg-captcha文檔vue
下載svg-captcha
模塊node
npm i svg-captcha -S
複製代碼
在nodejs中引入ios
const code = require("svg-captcha");
複製代碼
以後對模塊進行配置並導出git
const code = require("svg-captcha");
function createCode() {
return code.create({
size: 4,
ignoreChars: "0o1iIl",
noise: 3,
color: true,
background: "#fff",
fontSize: 60
});
}
module.exports = createCode;
複製代碼
模塊導出後在後端路由模塊中引入生成圖片驗證碼的模塊github
const captcha = require("./Code")
複製代碼
svg-captcha
的實例,給咱們提供了兩個屬性redis
咱們要讓前端顯示的確定是svg格式的圖片,不多是text文本,由於若是要爬蟲模擬登陸,豈不是太簡單了?數據庫
以後訪問驗證碼接口地址,就能夠看到圖片了。express
全部框架和工具,我引的都是CND
html部分
<div id="app">
<p><label>用戶名:</label><input type="text" ref="username" value="Wick"></p>
<p><label>密碼:</label><input type="text" ref="password" value="123456"></p>
<p id="code">
<label>驗證碼:</label>
<input ref="codeValue" type="text">
<img @click="getCode" :src="codeImg" alt="">
</p>
<button id="login" @click="login">登陸</button>
</div>
複製代碼
js部分
axios.defaults.baseURL = "http://localhost:10086";
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
axios.defaults.withCredentials = true;
axios.interceptors.request.use(config => {
return config;
})
const app = new Vue({
el: "#app",
data: {
codeImg: `http://localhost:10086/code?t=${new Date().getTime()}`
},
methods: {
getCode() {
// 添加時間戳進行驗證碼切換
this.codeImg = `http://localhost:10086/code?t=${new Date().getTime()}`;
this.$refs.codeValue.value = "";
},
login() {
let username = this.$refs.username.value;
let password = this.$refs.password.value;
let code = this.$refs.codeValue.value;
let data = {
username,
password: CryptoJS.AES.encrypt(password, username).toString(), //密碼加密
code
}
axios.post("/login", Qs.stringify(data)).then(res => {
alert(res.data.msg);
if(res.data.success === "ok") {
window.location = "/Home.html";
}
})
}
}
});
複製代碼
原生nodejs未提供session功能,因此咱們只能引入第三方模塊express-session
下載express-session
npm i -S express-session
複製代碼
nodejs引入express-session
const session = require("express-session");
複製代碼
中間件設置,詳細配置移步express-session文檔
app.use(session({
secret: "WickYo", // 對cookie進行簽名
name: "session", // cookie名稱,默認爲connect.sid
resave: false, // 強制將會話保存回會話容器
rolling: true, // 強制在每一個response上設置會話標識符cookie
cookie: {
// 5分鐘
maxAge: 300000
}
}))
複製代碼
配置以後,頁面的response都會帶有這個session
查看一下Application裏的cookies
這裏的session的存活時間,我是用來作驗證碼是否失效的,當session過時了,那麼驗證碼也就跟着失效,那麼就須要切換驗證進行登陸
下載redis
模塊
npm i redis -S
複製代碼
nodejs中引入
const redis = require("redis");
複製代碼
對redis進行配置,這裏只是簡單配置,詳細移步redis文檔
const client = redis.createClient({
host: "192.168.56.101", // redis地址
port: 6379 // 端口號
})
// 監聽鏈接事件
client.on("connect", error => {
if(!error) {
console.log("connect to redis")
}
})
// 監聽錯誤事件
client.on("error", error => {
throw new Error(error)
})
複製代碼
封裝set方法
function setString(key, value, expire) {
return new Promise((resolve, reject) => {
client.set(key, value, (error, replay) => {
if(error) {
reject("設置失敗")
}
if(expire) {
client.expire(key, expire);
}
resolve("設置成功")
});
})
}
複製代碼
封裝get方法
function getString(key) {
return new Promise((resolve, reject) => {
if(key) {
client.get(key, (error, replay) => {
if(error) {
reject(`獲取${key}失敗`)
}
resolve(replay);
})
}
})
}
複製代碼
最後導出方法。
module.exports = {
setString,
getString
}
複製代碼
上面封裝了set和get方法,那麼咱們就能夠在redis中設置值了。
通過前面的express-session
配置以後,咱們在進入頁面時,就會加載驗證碼圖片並設置cookie(存着sessionID的值),而後在登陸的時候,會帶上這個cookie。那這樣,咱們就能夠在獲取圖片的時候,以sessionID值爲key,svg-captcha
的text爲value進行設置
注:sessionID是使用了express-session
後注入的
爲了方便,就不鏈接數據庫了,直接建立一個本地的文件當作用戶的帳號密碼吧
直接上代碼
Router.post("/login", (req, res) => {
let username = req.body.username;
let password = CryptoJS.AES.decrypt(req.body.password, username).toString(CryptoJS.enc.Utf8); // 解密
let code = req.body.code.toLowerCase();
if(!req.signedCookies.session) {
res.send({success: "no", msg: "驗證碼過時"})
return;
}
// redis封裝的方法
getString(req.signedCookies.session).then(data => {
// signedCookies即被簽名過的cookie
console.log(data)
if(code === data) {
console.log("驗證碼正確")
// 讀文件
fs.readFile(__dirname + "/../user.conf", "utf8", (err, data) => {
let dataArr = data.toString().split("=");
if(username === dataArr[0]) {
if(password === dataArr[1]) {
// 根據登陸用戶名設置cookie,並規定只能cookie存活30分鐘
res.cookie("uid", username, {maxAge: 300000})
res.send({success: "ok", msg: "登陸成功"})
return;
}
}
res.send({success: "no", msg: "用戶名或密碼錯誤"})
})
} else {
res.send({success: "no", msg: "驗證碼錯誤"})
}
}).catch(err => {
console.log(err)
})
})
複製代碼
咱們能夠引入cookie-parse
對cookie進行解密
中間件設置
app.use(cookieParser(secret))
複製代碼
配置好以後,就能解析出被指定secret加密過的cookie了
咱們沒辦法直接獲取到post的參數,須要安裝body-parser
模塊,才能進行獲取
npm i -S body-parser
複製代碼
配置body-parser
app.use(bodyParser.urlencoded({ extended: false })) //解析application/x-www-form-urlencoded
複製代碼
配置以後,咱們就能獲取到請求體了
cookie有一個很差地方的,就是在瀏覽器中可見,而且是能夠修改的,若是咱們直接把敏感信息存儲在cookie中,那麼任何人均可見,任何人均可對其進行修改,這是很不安全的。
正是由於不安全,因此纔會須要簽名Cookie(Signed Cookie)對其進行加密,以防止被某些信息被泄露。
咱們手動對加密後的cookie進行解密
解密出來的值,其實就是在獲取驗證碼時的sessionID。
因此,咱們能經過req.signedCookies
獲取對應的cookie,都是由於cookie-parser
幫咱們作了解密。
本文已收錄至github:github.com/OnlyWick/Fu…
若有錯誤,請及時指出!