有关React-hooks的token自己的理解及应用

在这里聊聊关于我对token的浅显认知,由于本人学习前端不久,如有错误,请指正。

一、token是什么

1、token的本质就是一串字符串,是一段从服务端生成的字符串。在你进行登录时,前端会保存你登录的数据,比如用户名,密码,邮箱,手机号等等。。。。然后通过请求发送到后端,后端对你的前端传来的数据进行加密(根据安全性,可以使用不同的加密算法进行不同程度的加密),生成字符串。

2、token主要是用来干啥的,很多人说token是个令牌,对,确实没错,token就是令牌作用。当用户登录后进入到其他的功能页面,之后发的每个请求都会带有‘令牌’token,如果‘令牌’正确看,则可以正常请求,完成相应的功能,否则,则退出,需要重新进行登录。

二、token的大致应用

1、我们先了解下使用token的简单流程

首先,我们在首次进入一个网站时,会进行注册,之后到登录页面。在登录页面,我们会进行登录操作,即为首次登录,在首次登录后,登录页面传入的信息通过请求发送到后端,后端会先验证该用户是否存在,并且密码是否正确,若用户存在,且密码正确,则根据安全性,对该用户的登录信息进行不同程度的加密,保存到token中;并将该token返回至前端。

其次,前端接收到后台返回的token后,会将token保存到本地存储中,如cookies等,等待调用,并设置过期时间,若过期则自动删除。

之后,在除了登录、注册等其他的功能页面中进行请求,我们会将cooKies中保存的token放到请求头里,发送到后端。

再之后,后端取出请求头里的token,进行解密,并于在数据库中保存的用户信息进行比对(或者也许不用与数据库中的数据进行比对,直接与之前第一次在后台生成的token进行比对),若比对相等,则正常进行请求,否则,则返回登录页面,重新登录。

最后,还有一种情况,当设置cookies的时间过期了,cookies之前保存的内容也就没了,当然也就返回登录页面,重新登录。

三、token应用代码实际演示

结合二,我们来进行一步步的演示,在这里我用的技术有react-hooks、node、express、MySQL、react-cookies

1、在二的步骤之前,我们要加入一个操作,即设置一个自定的请求头set-cookie,用来在除登录、注册的其它的功能页面发送的请求头中保存token,并发送到后端。代码如下:

    res.header("Access-Control-Allow-Headers", "Content-Type,XFILENAME,XFILECATEGORY,XFILESIZE,set-cookie");//一定要在这里面加上自定义的请求头

最后的set-cookies,即为我们添加的自定义请求头属性,之后我们打开控制台,查看请求头会发现,set-cookie 已经添加到请求头中

2、将前端登录信息返回到后端,在后端进行验证,并加密保存到token中;进行加密保存操作,我们需要下载一个依赖,jsonwebtoken,并进行引入

npm install jsonwebtoken

const jwt = require('jsonwebtoken')
 if (result.length) {   //如果在数据库中查到该用户名
                    console.log('------------start----------------');
                    var string = JSON.stringify(result);
                    var json = JSON.parse(string)[0];
                    console.log(string)
                    if (json.password == LoginData.password) {//进行验证密码
                        console.log('密码校验正确');
                        console.log(result);
                        // res.send('登录成功!')
                        
                        
                        // 用JWT 将token 将用户信息加密
                        const token = jwt.sign(LoginData,'sxy3469998737')
                        res.send({//将token返回至前端
                            a:'登录成功!',
                            b:{token}
                        }) 
                    }

                    else {
                        console.log('密码校验错误');
                        res.send('密码错误!')


                    } 
   }

3、前端接收到后台返回的token后,我们会将他保存到cookies中(这里我们引入一个依赖react-cookies来对cookies进行相关操作)

npm install --save react-cookie

import cookie from 'react-cookies'


      //将token保存到cookies  并且   定时删除
      const deleteTimeCookie = (a) => {
            //定义cookies在一小时后自动失效
            let deleteTime = new Date(new Date().getTime() +1000*60*60)
            //userInfo为保存的cookie的名称,a为后台返回的token,
            //{ expires: deleteTime }则记时,到期自动删除,
            //{path:'/'}设置在该域名的所有路径下都可使用该cookie
            cookie.save('userInfo',a,{ expires: deleteTime },{path:'/'})
      }

 	 axios.post('http://localhost:8000/Signin',
                  {data1:JSON.stringify(data1)},
                  {headers:{'Content-Type' : 'application/json'}})
                        .then((res) => {Loginin(res.data.a,res.data);
                              // cookie.save('userInfo',res.data.b.token,{path:'/'});
                              deleteTimeCookie(res.data.b.token);//这里的res.data.b.token即为后台返回的token
                  })
                        .catch((err) => {console.log(err);})           
      }

4、在除登录、注册等其他功能页面发送请求时(我这里为一个会议预订的请求),将cookie中保存的token放在自定义的请求头中,发送到后端

var a= cookie.load('userInfo');//取出cookie中userinfo中保存的内容

 axios.post('http://localhost:8000/Index/Meeting',
            {data4:JSON.stringify(data4)},
            {headers:{'Content-Type' : 'application/json;charset=UTF-8',
                        'set-cookie' : a //将其给之前自定义的请求头
                     }
                      
            })
            .then((res) => {Loginexpired(res.data);})
            .catch((err) => {console.log(err);})

5、后端取出请求头里的token,进行解密,并于数据库中存入的用户信息进行比对

app.post('/Index/Meeting',
function(req,res) {
    const MeetData = JSON.parse(req.body.data4);
    const token = req.headers['set-cookie'].pop()//取出请求头中的token,这里pop()的作用是将token值变成字符串,若不是字符串,则解析时会报错
    console.log(token);

	//这里是用token的长度来判断token是否存在
	//因为当cookie因为过期而被删除时,打印token会显示undefined,但是用undefined判断却不正确,null也不正确,所以用长度
    if(token.length > 10) {
        const a = jwt.verify(token,'sxy3469998737')//解析token,若token不为字符串,则会报错

        var find2 = "SELECT * FROM useinfo WHERE username = '"+a.username+"' and password = '"+a.password+"'" 
       
         
        connection.query(find2,(err,result) => {
            if (err) {   //链接失败 直接return;
                console.log('[错误]' + err);
                return;
            };
            if(result.length) {
                if(MeetData !== '删除记录!') {
                    //编写查询语句
                    var find1 = "SELECT * FROM meetbook WHERE meetRoom = '"+MeetData.meetRoom+"' and meetWeek = '"+MeetData.meetWeek+"'" 
                    //插入语 句 
                    var insert = 'INSERT INTO meetbook (id,meetRoom,meetMen,meetWeek,meetStartTime,meetEndTime) VALUES (0,?,?,?,?,?)';
                    var inserInfo = [MeetData.meetRoom,MeetData.meetMen,MeetData.meetWeek,MeetData.meetStartTime,MeetData.meetEndTime];   //定义插入数据
                    //判断会议时间是否冲突
                    var timeConflict = "SELECT * FROM meetbook WHERE (meetStartTime between '"+MeetData.meetStartTime+"' and  '"+MeetData.meetEndTime+"') or (meetEndTime between '"+MeetData.meetStartTime+"' and  '"+MeetData.meetEndTime+"')  or (meetStartTime > '"+MeetData.meetStartTime+"' and meetEndTime <  '"+MeetData.meetEndTime+"') or (meetStartTime < '"+MeetData.meetStartTime+"' and meetEndTime > '"+MeetData.meetEndTime+"')  "
                 
                    //查询
                    connection.query(find1,(err,result) => {
                        if (err) {   //链接失败 直接return;
                            console.log('[错误]' + err);
                            return;
                        };
                        if(result.length) {
                            connection.query(timeConflict,(err,result) => {
                                if (err) {   //链接失败 直接return;
                                    console.log('[判断会议室时间冲突错误错误]' + err);
                                    return;
                                };
                                if(result.length) {
                                    res.send("改时间段已经被预定!")
                                }
                                else {
                                    connection.query(insert,inserInfo,(err,result) => {
                                        if (err) {   //链接失败 直接return;
                                            console.log('[插入数据库错误]' + err);
                                            return;
                                        };
                                        console.log('------------start----------------');
                                        console.log('预订成功');
                                        console.log(result);
                                        console.log('--------------end-----------------');
                                        res.send('预订成功!')
                                    })
                                }
                            })
                        }
                        else {
                            connection.query(insert,inserInfo,(err,result) => {
                                if (err) {   //链接失败 直接return;
                                    console.log('[插入数据库错误]' + err);
                                    return;
                                };
                                console.log('------------start----------------');
                                console.log('预订成功');
                                console.log(result);
                                console.log('--------------end-----------------');
                                res.send('预订成功!')
                            })
                        }
                    })
            
                   
                    
                }
                else {
                        //console.log(MeetData);
                       //删除最后一条数据
                       var delete1 = "DELETE  FROM meetbook WHERE 1 ORDER BY id DESC LIMIT 1"
                       connection.query(delete1,(err,result) => {
                            if (err) {   //链接失败 直接return;
                                console.log('[错误]' + err);
                                return;
                            };
                            

                       })
                }
            }
            else {
                res.send("验证出现错误!")
            }
        })
    }
    else {
        res.send("登录已过期!")//向前端发送请求已过期的请求
    }

6、前端接收到后端返回到的数据,若为‘登录已过期!’,则直接返回到登录页面,否则正常请求

 //登录时间过期后  自动跳转到登录页面
    const Loginexpired = (s) => {
        if (s === "验证出现错误!" || s === "登录已过期!") {
            window.location.href="http://localhost:3000"
        }
        else {
            alert(s);
        }
    }
    
 axios.post('http://localhost:8000/Index/Meeting',
            {data4:JSON.stringify(data4)},
            {headers:{'Content-Type' : 'application/json;charset=UTF-8',
                        'set-cookie' : a
                     }
                      
            })
            .then((res) => {Loginexpired(res.data);})//接收到返回的数据,并传入到函数中
            .catch((err) => {console.log(err);})


    }

你可能感兴趣的:(javascript,node.js,reactjs)