登录时密码加密及token

916 阅读2分钟
  • 在登录时用js-md5对密码进行加密与后台使用同种方式加密的密码对比,这样后台的数据库泄露就不会影响客户的信息了
  • 使用通用符*,判断请求的接口是登录接口还是其他接口,如果是登录接口,就直接post,传递加密的token,如果是其他接口,后台判断是否有token,且token是否能解密,如果可以,使用next()转到相应的接口,如果不可以,则不能获取数据

页面放在public中

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <div id="app">
        <div>
            <input type="text" v-model="loginUserInfo.username" placeholder="请输入用户名">
        </div>
        <div>
            <input type="password" v-model="loginUserInfo.password" placeholder="请输入密码">
        </div>
        <button @click='login'>提交</button>
        <button @click='getList'>get</button>
        {{list}}
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script src="https://cdn.bootcss.com/axios/0.19.0-beta.1/axios.js"></script>
    <script src="https://cdn.bootcss.com/blueimp-md5/2.12.0/js/md5.js"></script>
    <script>
        let instance = axios.create({
            baseURL:'http://localhost:8088'
        })
        let get=function(url){
            instance.defaults.headers.common['token']=localStorage.getItem('token')||''
            return instance.get(url)
        }
        let post=function(url,data){
            instance.defaults.headers.common['token']=localStorage.getItem('token')||''
            return instance.post(url,data)
        }
        function reverseStr(str) {
            return str.split('').reverse().join()
        }
        function fmtPwd(password) {
            return md5(reverseStr(md5(reverseStr(password))))
        }
        let vm = new Vue({
            el: '#app',
            data() {
                return {
                    loginUserInfo: {
                        username: 'admin',
                        password: '123'
                    },
                    list: []
                }
            },
            methods: {
                async login() {
                    this.loginUserInfo.password = fmtPwd(this.loginUserInfo.password)
                    let res = await post('/login', this.loginUserInfo)
                    if (res.data.isSuccess) {
                        alert('登录成功')
                        console.log(res.data.token)
                        localStorage.setItem('token', res.data.token)
                    } else {
                        alert('登录失败')
                    }
                },
                async getList() {
                    console.log(localStorage.getItem('token'))
                    let res = await get('/list')
                    this.list = res.data
                } 
            },
        })
    </script>
</body>
</html>

node.js后台

let express = require('express')
let app = express()
//bodyParser解析post参数
var bodyParser = require('body-parser')
var md5 = require('js-md5')
const util = require('./utils')
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
app.use('/', express.static('public'))
function reverseStr(str) {
    return str.split('').reverse().join()
}
function fmtPwd(password) {
    return md5(reverseStr(md5(reverseStr(password))))
}
app.use('*', (req, res, next) => {
    if (req.baseUrl !== '/login') {
        //检查token
        let { token } = req.headers
        if (!token) return res.json('非法请求')
        try {
            let str = util.decryption(token)
            console.log('str',str)
            let person = str.split('|')[0]
            let time = new Date(parseInt(str.split('|')[1])).toDateString()
            console.log(person, time + '请求了') //打印当前登录人员,登录时间
            next()
        } catch (error) {
            return res.json('非法请求1') 
        }
    }
    console.log(req.method + '了' + req.baseUrl)
    next()
})
app.post('/login', (req, res) => {
    let { username, password } = req.body
    if (username === 'admin' && password === fmtPwd('123')) {
        //生成token
        let token = util.encryption([username, +new Date].join('|'))
        console.log(token)
        res.json({
            token,
            isSuccess: true
        })
    } else {
        res.json({
            isSuccess: false
        })
    }
})
app.get('/list', (req, res) => {
    if (!req.headers.token) return res.json('非法请求')
    console.log(req.headers.token)
    try {
        let str = util.decryption(req.headers.token)
        console.log(str)
        let person = str.split('|')[0]
        let time = new Date(parseInt(str.split('|')[1])).toDateString()
        console.log(person, time) //打印当前登录人员,登录时间
    } catch (error) {
        return res.json('非法请求1')
    }
    res.json([1, 2, 3])
})

app.listen(8088)

AES加密

'use strict';
const crypto = require('crypto');

/**
 * AES加密的配置 
 * 1.密钥 
 * 2.偏移向量 
 * 3.算法模式CBC 
 * 4.补全值
 */
var AES_conf = {
    key: getSecretKey(), //密钥
    iv: '1012132405963708', //偏移向量
    padding: 'PKCS7Padding' //补全值
}

/**
 * 读取密钥key
 * 更具当前客户端的版本vid、平台platform获取对应的key
 */
function getSecretKey(){
    return "abcdabcdabcdabcd";
}

/**
 * AES_128_CBC 加密 
 * 128位 
 * return base64
 */
function encryption(data) {
    let key = AES_conf.key;
    let iv = AES_conf.iv;
    // let padding = AES_conf.padding;

    var cipherChunks = [];
    var cipher = crypto.createCipheriv('aes-128-cbc', key, iv);
    cipher.setAutoPadding(true);
    cipherChunks.push(cipher.update(data, 'utf8', 'base64'));
    cipherChunks.push(cipher.final('base64'));
    return cipherChunks.join('');
}


/**
 * 解密
 * return utf8
 */
function decryption(data){

    let key = AES_conf.key;
    let iv = AES_conf.iv;
    // let padding = AES_conf.padding;

    var cipherChunks = [];
    var decipher = crypto.createDecipheriv('aes-128-cbc', key, iv);
    decipher.setAutoPadding(true);
    cipherChunks.push(decipher.update(data, 'base64', 'utf8'));
    cipherChunks.push(decipher.final('utf8'));
    return cipherChunks.join('');
}
module.exports={
    decryption,encryption
}