样式可能有点丑,请不要在乎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…
若有错误,请及时指出!