令牌Token的生成和使用详解 通过用前端原生ajax网络请求和后端node.js的expres库模拟demo来实现

  1. 令牌Token作用和使用场景
    Token主要是用于登录模块使用,实现在设置的一段时间内来实现自动登录,减少再次输入账号密码,提高用户体验

  2. 为什么不使用cookie和session来实现自动登录而使用令牌Token

    不使用cookie是因为cookie数据保存在浏览器上数据不加密容易被伪造数据不安全,加上cookie数据手动可以删除数据。
    不使用session的原因是因为session数据以文件的形式保存在服务器,如果用户数量大,这样增加造成服务器压力,和session数据在不同服务器上数据不共享,因为现在用户量大,都是使用分布式服务器,这就是不适用的原因
    
  3. Token生成和保存解释

    后端获取前端登录时传来的账号和密码等ip信息,加上自定义密钥和过期时间,使用jsonwebtoken库,来签名加密数据生成token,保存一份到数据库,响应一份token到前端,前端获取token,通过localStorage.setItem()来保存到浏览器,登录成功后,每次发起请求的时候,通过localStorage.getItem()来获取token值,然后在请求头上面携带token值,传到后端,后端通过jsonwebtoken库来解密验证token值是否过期和解密后的用户账号和密码IP值从数据库获取响应用户数据,如果过期则跳到登陆界面
    
  4. localStorage的作用和方法解释

    localStorage数据保存浏览器上,数据是持久化保存,不会因为浏览器关闭和过期时间的设定而自动删除数据,它的数据要手动设置删除数据

    主要方法:
    setItem(key,value) :设置key和value值保存数据
    getItem(key) : 通过key来获取数据
    clear():清除localStorage保存的所有数据
    remove(key):清除指定key值的数据

  5. 通过一个demo练习来实现token使用过程,下面的前端代码使用原生xmlHttpRuest对象发起网络请求

<script>
	//模拟的登录的时候获取的账号密码
	var account=123;
	var password="abc123";
	var tokenText={"account":account,"password":password};
	//通过原生ajax来进行网络请求,创建网络请求对象XMLHttpRequest()
	
	var xmlHttRequest = new XMLHttpRequest();
	xmlHttRequest.open("post","http://localhost:80/SetToken",true);
	//open() 方法就是创建网络请求,第一个参数是 请求方式我是用的是post方式,第二个参数是请求的后端网址,第三个就是是否使用异步(true)或同步(false)请求
	//当xmlHttRequest状态码readyState发生改变 自动触发onreadystatechange事件
	//注意后面方法不用小括号
	xmlHttRequest.onreadystatechange=getData;
	//先从本地获取token,如果本地token还没保存有,则token=null
	var token=localStorage.getItem("token")
	
	//注意 tokenText和token是自定义,在后端,响应头部设置的,如果不设置,发起请求会报错
	//通过请求头发送账号密码到后端,格式设置为字符串格式,用请求头传送数据 我这个是测试用的,密码和账号会在浏览器能看的到,不安全和get方式一样,网址能看得到账号数据信息,最好用post方式发送数据
	
	xmlHttRequest.setRequestHeader("tokenText",JSON.stringify(tokenText))
	
	
	//用这个方法在请求头添加内容,添加token
	
	xmlHttRequest.setRequestHeader("token",token)  
	
	

	function getData(){
		if(xmlHttRequest.readyState==4){ //状态码为4表示接收响应数据成功    	
			if(xmlHttRequest.status==200){ //状态码为200说明响应数据正常
				//后端响应的数据是字符串格式,先转换为对象数据
				//hastoken的意思是是否已经有在浏览器生成保存token或者是否过期token 类型 boolen
				if(JSON.parse(xmlHttRequest.responseText).hastoken){
					console.log("token验证成功。 不用跳到登录界面重新登录!!")
				}else{
					console.log("跳到登录界面 重新登录!!")
					//清除过期的token
					localStorage.remove("token")
					//下面一段代码的是跳到登陆界面,点击登陆时发起网咯请求,后端生成token,前端保存token
					localStorage.setItem("token",JSON.parse(xmlHttRequest.responseText).token)
					console.log("保存成功!")
				}
					
			}
	}
  1. 使用后端node.js语言的express库,来实现token生成demo
// 后端代码项目启动 通过黑窗口 输入node token.js

//下载库 npm install express 
const express=require("express")

const app=express()

//jsonwebtoken 作用是生成令牌token 签名 加密账号密码数据 加上 密钥 加上 过期时间 然后解密对比token是否一致
//过期时间设置格式 "1h" "2day"
const jwt=require("jsonwebtoken")

//bodyparser库的作用是 解决post请求 数据格式问题,这段代码暂时没用,因为我使用请求头获取数据
var bodyParser = require("body-parser")

app.use(bodyParser.urlencoded({ extended: false }))

app.use(bodyParser.json())

//全局设置密钥
var secretkey ="token"

//访问地址 http://localhost:80/ 就可以启动前端代码

app.get("/",(req,res,next)=>{
	//正常前端和后端demo的练习,都是解决跨域问题,因为域名 端口 协议等的经常会不同

     //设置允许跨域的域名,*代表允许任意域名跨域,这个时第一种方法解决跨域问题
     
     //res.header("Access-Control-Allow-Origin","*") 
     
     res.header("Access-Control-Allow-Headers","Content-Type,Content-length,Authorization,Accept,token,tokenText") 
	
	//请求头的内容格式设值,新添加自定义token,tokenText 

    res.sendFile( __dirname+"/token.html") //这是第二种解决跨域问题,通过响应文件的形式来启动前端代码
    
})
	app.post("/SetToken",(req,res)=>{
	
    //从请求头获取 tokenText转换对象格式
    var tokenText=JSON.parse(req.headers.tokentext)
    
    //签名生成token
    //因为从前端请求获取的数据都是字符串格式 所以要用“null” 或者使用JSON.parse(req.headers).token
    //null 是因为前端还没保存token值 所以为 null值,因此要生成token值
    if(req.headers.token=="null"){
        var token=jwt.sign(tokenText,secretkey,{expiresIn:"60S"})
        console.log("签名成功:"+token)
        res.send({
            "token":token, //响应token给前端 前端保存token 每次请求 在请求头保存token
            "hastoken":false //hastoken=false 表示前端没有保存token值 
        })
       
    }else{
    	//token解码
        jwt.verify(req.headers.token,secretkey,(err,data)=>{
            if(err){ //如果出现 err说明token值过期了,要
                console.log("过期了")
                res.send({
                    "hastoken":false,  //过期重新登录 重新生成token
                    "token":""
                })

            }else{
                res.send({
                    "token":token, 
                    "hastoken":true //hastoken=true 表示已经签名加密 不用跳到登录界面
                })
                //可以通过 解码获取的 data用户ip去访问数据库获取相应的数据
                console.log(data)
            }
        })
    }
})
console.log(new Date())
//创建 域名localhost 端口为 80的服务器
app.listen(80)

你可能感兴趣的:(前端,ajax,node.js)