草庐IT

GO语言gin框架实战-02-Jwt和登录认证

开发运维玄德公 2023-12-02 原文

1. 相关函数

创建如下函数:

  • 登录函数:登录接口调用该函数
  • 身份验证:其他函数调用该函数,用token判断身份是否合法
  • 刷新token:登录接口调用该函数,如果token验证通过则发放新token
  • 验证token:需要验证身份的服务调用该函数判断token是否合法
  • 生成token: 其他函数调用该函数,用以生成新token
package router

import (
    "github.com/dgrijalva/jwt-go"
    "github.com/gin-gonic/gin"
    "time"
)

type LoginInfo struct {
    UserName string  `json:"user_name"`
    Password string `json:"password"`
}


type JWTClaims struct { // token里面添加用户信息,验证token后可能会用到用户信息
    jwt.StandardClaims
    UserID      int      `json:"user_id"`
    Password    string   `json:"password"`
    Username    string   `json:"username"`
    FullName    string   `json:"full_name"`
    Permissions []string `json:"permissions"`
}

var (
    Secret     = "LiuBei" // 加盐
    ExpireTime = 3600*24        // token有效期
)

//登录
func Login(c *gin.Context) {

    var loginRequest LoginInfo
    err := c.Bind(&loginRequest)
    if err != nil {
        c.JSON(400,err.Error())
        return
    }
    //模拟用户认证
    if loginRequest.UserName != "liuBei" || loginRequest.Password != "liubei@161" {
        c.JSON(401,gin.H{"err":"账号或密码错误"})
        return
    }

    claims := &JWTClaims{
        UserID:      1,
        Username:    loginRequest.UserName,
        Password:    loginRequest.Password,
        FullName:    loginRequest.UserName,
        Permissions: []string{},
    }
    claims.IssuedAt = time.Now().Unix()
    claims.ExpiresAt = time.Now().Add(time.Second * time.Duration(ExpireTime)).Unix()
    signedToken,err:=getToken(claims)

    if err!=nil {
        c.JSON(400,err.Error())
        return
    }
    //fmt.Printf(signedToken)
    c.JSON(200, gin.H{"token": signedToken})
}


//身份验证

func Verify(c *gin.Context)(result bool,userName string,err error) {
    strToken,err := c.Cookie("Crow")
    if strToken == ""{
        result = false
        return result,"",nil
    }
    claim,err := verifyAction(strToken)
    if err != nil {
        result = false
        return result,"",nil
    }
    result = true
    userName = claim.Username
    return result,userName,nil
}

//刷新token
func Refresh(c *gin.Context) {
    strToken,err := c.Cookie("Crow")
    claims,err := verifyAction(strToken)
    if err != nil {
        c.JSON(400,gin.H{"err":err.Error()})
        return
    }
    claims.ExpiresAt = time.Now().Unix() + (claims.ExpiresAt - claims.IssuedAt)
    signedToken,err:=getToken(claims)
    if err!=nil{
        c.JSON(400,gin.H{"err":err.Error()})
        return
    }
    c.JSON(200,gin.H{"data": signedToken })
}

//验证token是否存在,存在则获取信息
func verifyAction(strToken string) (claims *JWTClaims,err error) {
    token, err := jwt.ParseWithClaims(strToken, &JWTClaims{}, func(token *jwt.Token) (interface{}, error) {
        return []byte(Secret), nil
    })
    if err != nil {
        return nil, err
    }
    claims, ok := token.Claims.(*JWTClaims)
    if !ok {
        return nil, err
    }
    if err := token.Claims.Valid(); err != nil {
        return nil, err
    }
    return claims, nil
}

//生成token
func getToken(claims *JWTClaims)(signedToken string,err error){
    token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
    signedToken, err = token.SignedString([]byte(Secret))
    if err != nil {
        return "",err
    }
    return signedToken,nil
}


2. router对其调用

    loginGroup := r.Group("/api/v1/login")
    {
        loginGroup.POST("/", Login) //登录服务器
        loginGroup.POST("/refresh", Refresh) //生成新token
    }

3. 其他接口身份验证

以上一章k8s服务的 查询deployment接口为例,开头添加如下内容:


func GetDeployment(c *gin.Context)  {
    //身份认证
    checkUser,_,err := Verify(c) //第二个值是用户名,这里没有使用
    if err != nil{
        c.JSON(400,gin.H{"err":err.Error()})
        return
    }
    if checkUser == false {
        c.JSON(400,gin.H{"err":"身份认证失败"})
        return
    }

    //查询开始
    ……
}

4. postman 测试

4.1 测试登录接口

image.png

登录成功获取到token。

4.2 postman设置Cookies

image.png

注意:Crow这个 key的名字是刚才我们在代码里边指定的

4.3 其他接口调用身份验证测试

  • 成功的情况

我们可以看到Headers里多了我们刚才添加的Cookie,是我们刚才添加的Crow

image.png
  • 验证失败的情况

我们把刚才的Cookie改成错的,然后再测试:

image.png

有关GO语言gin框架实战-02-Jwt和登录认证的更多相关文章

  1. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  2. ruby - 寻找通过阅读代码确定编程语言的ruby gem? - 2

    几个月前,我读了一篇关于ruby​​gem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:

  3. Unity 热更新技术 | (三) Lua语言基本介绍及下载安装 - 2

    ?博客主页:https://xiaoy.blog.csdn.net?本文由呆呆敲代码的小Y原创,首发于CSDN??学习专栏推荐:Unity系统学习专栏?游戏制作专栏推荐:游戏制作?Unity实战100例专栏推荐:Unity实战100例教程?欢迎点赞?收藏⭐留言?如有错误敬请指正!?未来很长,值得我们全力奔赴更美好的生活✨------------------❤️分割线❤️-------------------------

  4. 7个大一C语言必学的程序 / C语言经典代码大全 - 2

    嗨~大家好,这里是可莉!今天给大家带来的是7个C语言的经典基础代码~那一起往下看下去把【程序一】打印100到200之间的素数#includeintmain(){ inti; for(i=100;i 【程序二】输出乘法口诀表#includeintmain(){inti;for(i=1;i 【程序三】判断1000年---2000年之间的闰年#includeintmain(){intyear;for(year=1000;year 【程序四】给定两个整形变量的值,将两个值的内容进行交换。这里提供两种方法来进行交换,第一种为创建临时变量来进行交换,第二种是不创建临时变量而直接进行交换。1.创建临时变量来

  5. postman——集合——执行集合——测试脚本——pm对象简单示例02 - 2

    //1.验证返回状态码是否是200pm.test("Statuscodeis200",function(){pm.response.to.have.status(200);});//2.验证返回body内是否含有某个值pm.test("Bodymatchesstring",function(){pm.expect(pm.response.text()).to.include("string_you_want_to_search");});//3.验证某个返回值是否是100pm.test("Yourtestname",function(){varjsonData=pm.response.json

  6. 微信小程序开发入门与实战(Behaviors使用) - 2

    @作者:SYFStrive @博客首页:HomePage📜:微信小程序📌:个人社区(欢迎大佬们加入)👉:社区链接🔗📌:觉得文章不错可以点点关注👉:专栏连接🔗💃:感谢支持,学累了可以先看小段由小胖给大家带来的街舞👉微信小程序(🔥)目录自定义组件-behaviors    1、什么是behaviors    2、behaviors的工作方式    3、创建behavior    4、导入并使用behavior    5、behavior中所有可用的节点    6、同名字段的覆盖和组合规则总结最后自定义组件-behaviors    1、什么是behaviorsbehaviors是小程序中,用于实现

  7. TimeSformer:抛弃CNN的Transformer视频理解框架 - 2

    Transformers开始在视频识别领域的“猪突猛进”,各种改进和魔改层出不穷。由此作者将开启VideoTransformer系列的讲解,本篇主要介绍了FBAI团队的TimeSformer,这也是第一篇使用纯Transformer结构在视频识别上的文章。如果觉得有用,就请点赞、收藏、关注!paper:https://arxiv.org/abs/2102.05095code(offical):https://github.com/facebookresearch/TimeSformeraccept:ICML2021author:FacebookAI一、前言Transformers(VIT)在图

  8. 牛客网专项练习30天Pytnon篇第02天 - 2

    1.在Python3中,下列关于数学运算结果正确的是:(B)a=10b=3print(a//b)print(a%b)print(a/b)A.3,3,3.3333...B.3,1,3.3333...C.3.3333...,3.3333...,3D.3.3333...,1,3.3333...解析:    在Python中,//表示地板除(向下取整),%表示取余,/表示除(Python2向下取整返回3)2.如下程序Python2会打印多少个数:(D)k=1000whilek>1:    print(k)k=k/2A.1000 B.10C.11D.9解析:    按照题意每次循环K/2,直到K值小于等

  9. ruby - token 认证 - 2

    简单代码require'net/http'url=URI.parse('getjson/otherdatahere[link]')req=Net::HTTP::Get.new(url.to_s)res=Net::HTTP.start(url.host,url.port){|http|http.request(req)}putsres.body只是想知道如何在phpcURL中放置身份验证token,我是这样做的    curl_setopt($ch,CURLOPT_HTTPHEADER,array('Authorization:Bearerxxx'));//Bearertokenfora

  10. ruby - sinatra 框架的 MVC 模式 - 2

    我想开始使用“Sinatra”框架进行编码,但我找不到该框架的“MVC”模式。是“MVC-Sinatra”模式或框架吗? 最佳答案 您可能想查看Padrino这是一个围绕Sinatra构建的框架,可为您的项目提供更“类似Rails”的感觉,但没有那么多隐藏的魔法。这是使用Sinatra可以做什么的一个很好的例子。虽然如果您需要开始使用这很好,但我个人建议您将它用作学习工具,以对您来说最有意义的方式使用Sinatra构建您自己的应用程序。写一些测试/期望,写一些代码,通过测试-重复:)至于ORM,你还应该结帐Sequel其中(imho

随机推荐