技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-9.登录功能(三):登录的token验证

45 篇文章 5 订阅
12 篇文章 3 订阅
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-9.登录功能(三):登录的token验证

相关文章:
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-1.工具和本地环境

技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-8.模型的关联——无限层级分类
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-9.登录功能(一):管理员功能的实现
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-9.登录功能(二):用户登录和密码验证
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-9.登录功能(三):登录的token验证
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-10.生产环境编译

1.生成token

go语言中生成token的方法被封装在了jwt中,gin框架使用jwt又进行了进一步封装,在"github.com/dgrijalva/jwt-go"里。
(1)安装jwt包:jwt-go

go get github.com/dgrijalva/jwt-go

在这里插入图片描述
(2)编写生成token方法

// 定义一个全局token密钥,token密钥随意定义一串字符串
var jwtkey = []byte("lskjdghfhkagflkagh")
// 定义字符串格式token,方便之后token的转化
var tokenString string

// 定义一个token模型,用于存放token信息,识别不同账号
type claims struct {
	UserId string
	jwt.StandardClaims
}

// 生成token
// 传入字符串格式用户id,输出字符串格式的token和错误值
func setToken(id string) (tokenString string, err error) {
	// 
	// 定义token过期时间,一天后过期
	expireTime := time.Now().Add(1 * 24 * time.Hour)
	claims := &claims{
		UserId: id,
		StandardClaims: jwt.StandardClaims{
			ExpiresAt: expireTime.Unix(), // 过期时间,用上方定义的过期时间
			IssuedAt: time.Now().Unix(), // 生效时间,生成token的这一刻起
			Issuer: "127.0.0.1", // 生成者,本域名
			Subject: "user token", // 生成主题
		},
	}
	// 生成token
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	// 根据之前定义的密钥,将token转化为加密字符串
	tokenString, err = token.SignedString(jwtkey)
	// 输出
	return
}

在这里插入图片描述
(2)编辑登录接口方法,在其中使用token方法获取token值
在这里插入图片描述
编译启动,测试:
在这里插入图片描述
成功获取token值。
(3)最后将token值保存到前端本地储存空间中,用于验证登录状态:
Login.vue:

async login() {
    const res = await this.$http.post('login', this.model)
    console.log(res)

    // 存储token值
    // sessionStorage是页面缓存存储,关闭页面后token值被清除,每次进入页面都需要进行账号登陆
    // localStorage是本地存储,关闭页面后token值不会被清除,只要不清理浏览器缓存就无需再次进行登录操作
    localStorage.token = res.data.token

    // 登录成功跳转到网站首页
    this.$router.push('/')
    // 使用vue效果在页面展示结果
    this.$message({
        type: 'success',
        message: '登陆成功'
    })
}

在这里插入图片描述
保存测试,跳转成功:
在这里插入图片描述
查找页面存储的token,可查询到:
在这里插入图片描述

2.验证token

我们需要将token值存入发送请求的请求头中,做到只要调用接口,就可以将token一并发送到后端,从而对token登陆状态进行比对验证。
(1)前端admin端通过请求头将token传值给后端
在http.js中全局设置获取token,将token值传入请求头Request
Headers中,然后后台接口中直接从请求头中获取token,从而实现验证。
这里使用axios里的Interceptors方法,详细可查阅axios手册
在这里插入图片描述
admin/http.js前端admin端将token传入请求头Request Header:

// 使用axios的interceptors拦截器,将http调用时拦截
http.interceptors.request.use(function(config){
    // 将token值传入请求头,"bearer + 空格"是代码规范,看到Bearer(持票人)大家就明白是对token的验证
    config.headers.Authorization = 'bearer ' + localStorage.token
    return config
}, function(error){
    // 错误处理
    return Promise.reject(error)
})

在这里插入图片描述
此时调用接口就可以将本地token传给请求头,测试:
在这里插入图片描述
(2)后端获取请求头中的token值,并解析token

// 解析token
func getToken() gin.HandlerFunc {
	return func(ctx *gin.Context) {
		// 从请求头获取token值
		tokenString := ctx.GetHeader("Authorization")
			
		// 判断如果没有token
		if tokenString == "" {
			ctx.JSON(http.StatusUnauthorized, gin.H{"code": 401, "msg": "您未登录"})
			// 中间件中使用next()就执行下一步,如果执行abort()就不会执行下一步
			ctx.Abort()
			// return
		}

		// 去除authorization中的"bearer"
		tokenString = strings.Trim(tokenString, "bearer")
		// 去除authorization中的空格
		tokenString = strings.Replace(tokenString, " ", "", -1)
		fmt.Println(tokenString)

		// 判断token是否失效
		token, claims, err := ParseToken(tokenString)
		if err != nil || !token.Valid{
			ctx.JSON(http.StatusUnauthorized, gin.H{"code": 401, "msg": "权限失效,请重新登录"})
			ctx.Abort()
			// return
		}

		// 打印userid,既然定义这个值就必须使用,留下来以备以后的需要
		fmt.Println(claims.UserId)
		if claims.UserId != "" {
			// 如果没有token没问题,则退出中间件执行下一步
			ctx.Next()
		}
	}
	
}
// 解析字符串token中的信息
func ParseToken(tokenString string) (*jwt.Token, *claims, error) {
    claims := &claims{}
    token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (i interface{}, err error) {
        return jwtkey, nil
    })
    return token, claims, err
}

在这里插入图片描述
此时,删除本地token:
在这里插入图片描述
刷新页面,进行token判断:
在这里插入图片描述
此时接口无法调用,这里是因为我们删除了本地存储的token,如果本地有token,但仍然错误,就是因为之前token设定的时间过期了:
在这里插入图片描述
同时报错中显示为空白,我们需要让它显示出来报错原因,修改两处:
(1)将报错返回的json值return返回:
在这里插入图片描述
(2)修改前端页面的vue拦截信息,我们返回的错误是msg:
在这里插入图片描述
此时再次刷新页面:
在这里插入图片描述
既然报错,则跳转到登陆页面:
在这里插入图片描述
刷新页面,此时跳转到登录页面:
在这里插入图片描述
登录进入页面测试,无法登录:
在这里插入图片描述
这事因为我们的token判断中间件,同样作用于login接口,所以需要进行改动后端接口路由:
在这里插入图片描述
将登录接口放在token解析中间件上方,中间件就不会对登录接口作用了,只会作用于下方接口,保存编译测试:
在这里插入图片描述
到此,登录的token解析功能实现。

3.解析token总结

只要我们确立好实现token验证的过程方向后就可以完成这个功能。登录的token验证过程非常简单,就是调用接口→发送token→接收token→判断token→将token判断结果传给前端→如已登录运行接口(若未登录跳转登录页)→返回数据,我们的搭建过程就是对每个步骤进行逐一寻找找方法、解决。

4.导航守卫

此时我们只要调用接口就会解析token,但是进入没有接口的页面就不会跳转。如果我们不想让用户在不登陆的状态下访问我们的所有网页,就需要在前端也设置token判断,做到只要不登录,就无法访问所有页面。
这里我们就需要用到Vue的导航守卫
大家可以查看我之前的文章进行设置,纯前端操作,不涉及后端:

技能学习:学习使用Node.js + Vue.js,开发前端全栈网站-12-4.登陆的前端vue-router路由验证(导航守卫)

到此就完成了一个简单的全栈项目,大家可以参照学习过程研究更多功能,下篇文章将admin端放入server端,通过server端进行项目的访问,将前后端分离状态合并成一个完整的独立项目(改为待上线模式,还是前后端分离)。

更多设计、功能的学习经验,大家也可以去我的公众号查看!

————
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

最强的森

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值