GoWeb开发-3.JWT

2023-11-10

1.导入依赖库

go get -u github.com/dgrijalva/jwt-go

2.生成token

import (
    "fmt"
    "github.com/gin-gonic/gin"
    jwt "github.com/dgrijalva/jwt-go"
    "net/http"
    "time"
)
var jwtSecret=[]byte("secret")
type  Claims struct {
    Username string `json:"username"`
    Password string `json:"password"`
    jwt.StandardClaims
}

//生成token
func createToken(username,password string)(string,error)  {
    nowtime := time.Now()
    expireTime := nowtime.Add(3*time.Hour)

    claims := Claims{
        username,
        password,
        jwt.StandardClaims{
            ExpiresAt: expireTime.Unix(),
            Issuer: "gin-blog",
        },
    }
    //
    tokenClaims:=jwt.NewWithClaims(jwt.SigningMethodHS256,claims)
    token,err:=tokenClaims.SignedString(jwtSecret)
    return token,err
}

3.解析token

//解析token
// 验证token的函数
func ParseToken(token string)(*Claims,error){
    tokenClaims,err:=jwt.ParseWithClaims(token,&Claims{},func(token *jwt.Token)(interface{},error){
        return jwtSecret,nil
    })

    if tokenClaims!=nil{
        if claims,ok:=tokenClaims.Claims.(*Claims);ok && tokenClaims.Valid{
            return claims,nil
        }
    }
    //
    return nil,err
}

4.在gin的应用

登录,获取token

func authHandler(c *gin.Context) {
    // 用户发送用户名和密码过来
    var user Claims
    err := c.ShouldBind(&user)
    if err != nil {
        c.JSON(http.StatusOK, gin.H{
            "code": 2001,
            "msg":  "无效的参数",
        })
        return
    }
    fmt.Println(&user)
    // 校验用户名和密码是否正确
    if user.Username == "admin" && user.Password == "123456" {
        // 生成Token
        tokenString, _ := createToken(user.Username,user.Password)
        c.JSON(http.StatusOK, gin.H{
            "code": 2000,
            "msg":  "success",
            "data": gin.H{"token": tokenString},
        })
        return
    }
    c.JSON(http.StatusOK, gin.H{
        "code": 2002,
        "msg":  "鉴权失败",
    })
    return
}

r.POST("/auth", authHandler)

在其他接口加上解析token验证

// JWTAuthMiddleware 基于JWT的认证中间件
func JWTAuthMiddleware() func(c *gin.Context) {
    return func(c *gin.Context) {
        // 客户端携带Token有三种方式 1.放在请求头 2.放在请求体 3.放在URI
        // 这里假设Token放在Header的Authorization中,并使用Bearer开头
        // 这里的具体实现方式要依据你的实际业务情况决定
        authHeader := c.Request.Header.Get("token")
        if authHeader == "" {
            c.JSON(http.StatusOK, gin.H{
                "code": 2003,
                "msg":  "请求头中auth为空",
            })
            c.Abort()
            return
        }
        // 按空格分割
        //parts := strings.SplitN(authHeader, " ", 2)
        //if !(len(parts) == 2 && parts[0] == "Bearer") {
        //    c.JSON(http.StatusOK, gin.H{
        //        "code": 2004,
        //        "msg":  "请求头中auth格式有误",
        //    })
        //    c.Abort()
        //    return
        //}
        // parts[1]是获取到的tokenString,我们使用之前定义好的解析JWT的函数来解析它
        mc, err := ParseToken(authHeader)
        if err != nil {
            c.JSON(http.StatusOK, gin.H{
                "code": 2005,
                "msg":  "无效的Token",
            })
            c.Abort()
            return
        }
        // 将当前请求的username信息保存到请求的上下文c上
        c.Set("username", mc.Username)
        c.Next() // 后续的处理函数可以用过c.Get("username")来获取当前请求的用户信息
    }
}




    r.POST("/auth1",JWTAuthMiddleware(), func(c *gin.Context) {
        username := c.MustGet("username").(string)
        c.JSON(http.StatusOK, gin.H{
            "code": 2000,
            "msg":  "success",
            "data": gin.H{"username": username},
        })
    })

完整代码

package main

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

var jwtSecret=[]byte("secret")
type  Claims struct {
    Username string `json:"username"`
    Password string `json:"password"`
    jwt.StandardClaims
}

//生成token
func createToken(username,password string)(string,error)  {
    nowtime := time.Now()
    expireTime := nowtime.Add(3*time.Hour)

    claims := Claims{
        username,
        password,
        jwt.StandardClaims{
            ExpiresAt: expireTime.Unix(),
            Issuer: "gin-blog",
        },
    }
    //
    tokenClaims:=jwt.NewWithClaims(jwt.SigningMethodHS256,claims)
    token,err:=tokenClaims.SignedString(jwtSecret)
    return token,err
}

//解析token
// 验证token的函数
func ParseToken(token string)(*Claims,error){
    tokenClaims,err:=jwt.ParseWithClaims(token,&Claims{},func(token *jwt.Token)(interface{},error){
        return jwtSecret,nil
    })

    if tokenClaims!=nil{
        if claims,ok:=tokenClaims.Claims.(*Claims);ok && tokenClaims.Valid{
            return claims,nil
        }
    }
    //
    return nil,err
}

func authHandler(c *gin.Context) {
    // 用户发送用户名和密码过来
    var user Claims
    err := c.ShouldBind(&user)
    if err != nil {
        c.JSON(http.StatusOK, gin.H{
            "code": 2001,
            "msg":  "无效的参数",
        })
        return
    }
    fmt.Println(&user)
    // 校验用户名和密码是否正确
    if user.Username == "admin" && user.Password == "123456" {
        // 生成Token
        tokenString, _ := createToken(user.Username,user.Password)
        c.JSON(http.StatusOK, gin.H{
            "code": 2000,
            "msg":  "success",
            "data": gin.H{"token": tokenString},
        })
        return
    }
    c.JSON(http.StatusOK, gin.H{
        "code": 2002,
        "msg":  "鉴权失败",
    })
    return
}



// JWTAuthMiddleware 基于JWT的认证中间件
func JWTAuthMiddleware() func(c *gin.Context) {
    return func(c *gin.Context) {
        // 客户端携带Token有三种方式 1.放在请求头 2.放在请求体 3.放在URI
        // 这里假设Token放在Header的Authorization中,并使用Bearer开头
        // 这里的具体实现方式要依据你的实际业务情况决定
        authHeader := c.Request.Header.Get("token")
        if authHeader == "" {
            c.JSON(http.StatusOK, gin.H{
                "code": 2003,
                "msg":  "请求头中auth为空",
            })
            c.Abort()
            return
        }
        // 按空格分割
        //parts := strings.SplitN(authHeader, " ", 2)
        //if !(len(parts) == 2 && parts[0] == "Bearer") {
        //    c.JSON(http.StatusOK, gin.H{
        //        "code": 2004,
        //        "msg":  "请求头中auth格式有误",
        //    })
        //    c.Abort()
        //    return
        //}
        // parts[1]是获取到的tokenString,我们使用之前定义好的解析JWT的函数来解析它
        mc, err := ParseToken(authHeader)
        if err != nil {
            c.JSON(http.StatusOK, gin.H{
                "code": 2005,
                "msg":  "无效的Token",
            })
            c.Abort()
            return
        }
        // 将当前请求的username信息保存到请求的上下文c上
        c.Set("username", mc.Username)
        c.Next() // 后续的处理函数可以用过c.Get("username")来获取当前请求的用户信息
    }
}
func main() {
    r := gin.Default()
    r.POST("/auth", authHandler)
    r.POST("/auth1",JWTAuthMiddleware(), func(c *gin.Context) {
        username := c.MustGet("username").(string)
        c.JSON(http.StatusOK, gin.H{
            "code": 2000,
            "msg":  "success",
            "data": gin.H{"username": username},
        })
    })
    r.Run(":9090")
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

GoWeb开发-3.JWT 的相关文章

  • HTTP 状态 400 验证与验证

    虽然RFC 7231 https www rfc editor org rfc rfc7231目的是为了清晰起见 但它显然给状态代码 400 带来了歧义 请注意这一点所以答案和评论 https stackoverflow com a 329
  • gradle - 从 url 下载并解压文件

    从 url 下载和解压文件的正确 gradle 方法是什么 http 如果可能的话 我想防止每次运行任务时重新下载 在ant get可以通过以下方式实现skipexisting true 我当前的解决方案是 task foo ant get
  • iPhone Mobile Safari,最大并行 http 连接数是多少?

    我想在 iPhone Mobile Safari OS4 中使用并行 AJAX HTTP 请求 最大并行连接数是多少 如果我没记错的话 Safari 最多使用 4 个到同一服务器的连接 但您可以使用以下命令自行测试这个小测试用例 http
  • 使用 php 和 jquery 的简单彗星示例

    谁能给我一个使用 PHP 的彗星技术的简单好例子 我只需要一个使用持久 HTTP 连接或类似连接的示例 我不想使用轮询技术 因为我已经设置了类似的东西 并且不仅难以使用和管理它的大量资源 另外我使用的是 IIS7 而不是 Apache 一个
  • RxJS Angular2 在 Observable.forkjoin 中处理 404

    我目前正在链接一堆 http 请求 但是在订阅之前我无法处理 404 错误 My code 在模板中 service getData subscribe data gt this items data err gt console log
  • 如果 POST 成功但没有创建任何新内容,我们应该返回什么状态代码?

    我们有一个端点 当您发布创建新版本的资源时 它会返回 201 和新创建的资源的位置 它根据当前版本和发布的版本 使用类似 semver 的规则集 的比较来确定新版本号 如果您发布的版本与现有版本相同 则不会更新版本号 在这种情况下我们应该返
  • 在电子邮件中使用协议相对 URL 安全吗?

    关于在 HTML 中使用协议相对 URL 已有讨论 1 但是电子邮件呢 电子邮件客户端或 Gmail 等服务提供商在 HTML 电子邮件中使用时是否会删除或修改协议相对 URL 1 我可以将所有 http 链接更改为 吗 https sta
  • HTTP-DELETE-请求是否允许响应主体?

    我假设响应代码 200 始终允许响应主体 但我找不到任何明确提及删除请求的响应主体 这里明确提到了RFC http www w3 org Protocols rfc2616 rfc2616 sec9 html sec9 7 简短的回答是 Y
  • 如何在 Android 中从服务器检索数据时更新滚动的 ListView?

    目前 我正在使用 AsyncTask 来处理 Http 连接并以 JSON 格式检索数据 加载所有数据很简单 但会消耗太多时间 因此我决定使用一次加载 10 个项目LIMIT OFFSET mysql 接下来我设置事件onScroll为我的
  • HTTP 查询字符串和 []

    PHP 使用 在查询参数名称中 以确保多次出现的参数都出现在 GET超全局变量 否则只出现最后一次出现的情况 还有其他软件可以做到这一点吗 但从RFC 3986 https www rfc editor org rfc rfc3986 以及
  • 内容长度标头与分块编码

    我正在尝试权衡设置的利弊Content LengthHTTP 标头与使用分块编码从我的服务器返回 可能 大文件的比较 使用持久连接需要其中之一来符合 HTTP 1 1 规范 我看到了的优点Content Length标头是 下载对话框可以显
  • 如何让 NSURLRequest 获取 Twitter 请求令牌?

    我正在尝试使用以下代码从 Twitter 获取请求令牌 NSMutableURLRequest mURLRequest NSMutableURLRequest alloc initWithURL NSURL URLWithString ht
  • Spring webflow 应用程序:HTTP 302 暂时移动

    我的 java 应用程序中的每个请求都会生成另外 2 个带有 HTTP 302 错误的请求 例如 如果请求查看名为板 html 这个请求是从首页 html 我收到按以下顺序生成的 3 个请求 POST home html 302 Moved
  • Vertx HttpClient getNow 不工作

    我的 vertx HttpClient 有问题 下面的代码显示使用 vertx 和纯 java 测试 GET Vertx vertx Vertx vertx HttpClientOptions options new HttpClientO
  • 如何测试“If-Modified-Since”HTTP 标头支持

    使用 PHP 如何准确测试远程网站supports If Modified Since HTTP 标头 据我所知 如果您获取的远程文件自标头请求中指定的日期以来已被修改 它应该返回 200 OK 状态 如果尚未修改 则应返回 304 Not
  • Golang 优雅地关闭 HTTP 服务器并进行错误处理

    我正在让我的 HTTP 服务器正常关闭 我从帖子中获取了提示here https stackoverflow com questions 39320025 how to stop http listenandserve 并且到目前为止已经像
  • asp.net core http 如果没有内容类型标头,则删除 `FromBody` 忽略

    我在 http 中使用 bodyDELETE要求 我知道目前删除主体是非标准的 但是允许的 使用时出现问题HttpClient它不允许删除请求的正文 我知道我可以使用SendAsync 但我宁愿让我的 API 更加灵活 我希望这个机构是可选
  • 如何使用 http 将 Android 中的文件从移动设备发送到服务器?

    在android中 如何使用http将文件 数据 从移动设备发送到服务器 很简单 您可以使用 Post 请求并将文件作为二进制 字节数组 提交 String url http yourserver File file new File En
  • .net core 2.0代理请求总是导致http 407(需要代理身份验证)

    我正在尝试通过 net core 2 0 Web 应用程序中的 WebProxy 发出 HTTP 请求 我得到的代码在 net框架中运行良好 所以我知道 相信 这不是环境问题 我也尝试使用两者来发出请求HttpWebRequest and
  • iOS 上的多个 HTTP 请求与单个 TCP 连接

    我正在开发一个 iPhone 应用程序 它使用我控制的基于 Web 的 API 连接到持续打开的 TCP 端口并通过 TCP API 发出请求 或者为我想要获取的所有数据发出新的 HTTP 请求 会更快或更高效吗 我认为差异可以忽略不计 但

随机推荐

  • mysql-mmm集群

    一 Mysql mmm集群技术概述 概述 MMM Master Master replication manager for MySQL 是一套支持双主故障切换和双主日常管理的脚本程序 MMM使用Perl语言开发 主要用来监控和管理MySQ
  • RecyclerView(一)—— ListView的使用

    ListView ListView在过去绝对可以称得上是Android中最常用的控件之一 几乎所有的应用程序都会用到它 由于手机屏幕空间比较有限 能够一次性在屏幕上显示的内容并不多 当我们的程序中有大量的数据需要展示的时候 就可以借助Lis
  • vscode给某行代码添加标签

    只有你习惯于一种编程工具风格 vscode几乎都能给你做的 Numbered Bookmarks 数字标签跳转类似与webstrom 定义 Ctrl SHIFT 数字 跳转 Ctrl 数字 vscode给某行代码添加标签 标注 用于代码间快
  • Qt使用QJSEngine执行脚本

    有时候需要进行一些计算 程序是使用c 来实现的 使用c 来进行计算不是很灵活 这时候可以使用脚本来进行计算 这样灵活 且易于扩展 写了一个简单的Demo进行验证 具体例子如下 include
  • Java - 带参的异常处理模块try(xxx){...}

    带资源的try语句 try with resource 的最简形式为 try Resource res xxx 可指定多个资源 do something try块退出时 会自动调用res close 方法 关闭资源 其实这样做的原因 主要是
  • mysql24,Mysql24之事务隔离级别和MVCC

    TOC 事前准备 为了故事的顺利发展 我们需要创建一个表 CREATE TABLE hero number INT name VARCHAR 100 country varchar 100 PRIMARY KEY number Engine
  • mmdetection 中 Mask Rcnn检测结果可视化(DICE计算、PR曲线绘制等)

    mmdetection中的Mask Rcnn是一个很不错的检测网络 既可以实现目标检测 也可以实现语义分割 官方也有很详细的doc指导 但是对新手来说并不友好 刚好之前笔者写的mmlab系列里面关于可视化都还没有一个详细的文档 也在此一并介
  • 逆向破解之破解补丁与劫持Dll

    破解补丁 前言 破解补丁的作用是修改程序内存地址的硬编码 以此来实现破解软件 这是常见的JE跳转用来判断注册码是否正确 若401108位置的汇编指令给Nop掉就能实现破解 编写代码 1 C语言 运行程序后输入要破解的程序进程ID inclu
  • yolov5源码解读--训练策略

    yolov5源码解读 训练策略 超参数解读 命令行参数 train 模型迭代 测试 超参数解读 hyp scratch yaml lr0 0 0032 初始学习率 lrf 0 12 使用余弦函数动态降低学习率 lr0 lrf momentu
  • spark入门小例子

    来源 我是码农 转载请保留出处和链接 本文链接 http www 54manong com id 1221 1 pyspark 2 spark shell spark网页管理页面 http 127 0 0 1 4040 jobs 3 设置日
  • Redis常见数据结构的常用命令及引用

    String 1 常用命令 字符串常用操作 SET key value 存入字符串键值对 MSET key value key value 批量存储字符串键值对 SETNX key value 存入一个不存在的字符串键值对 GET key
  • AVLTree-平衡二叉树-coming soon

  • php验证用户账号密码正确,php-检查用户名和密码是否正确

    因为我的代码是正确的 所以我总是得到回显 Username Passwordcorrect 用户名 密码是否匹配 我的问题是 我在下面的代码中为PHP总是回显 用户名 密码错误 而做错了什么 require privstuff dbinfo
  • jupyter notebook使用基础及其快捷键,包括对文档操作、cell操作、快捷键、markdown

    目录 Jupyter Notebook介绍 使用原因 基本操作 新建notebook文档 对文档的操作 cell操作 什么是cell Jupyter支持两种模式 鼠标操作 Jupyter快捷键操作 markdown演示 手动建导航 Jupy
  • 网络编程 - Java SSLSocketFactory 创建方式

    SSL TLS 认证需要服务端提供 KeyStore jks TrustStore jks 实现方式 优缺点 服务端提供 CA Client CRT Client Key 文件 缺点 服务端提供原始签名 不安全不建议采用 服务端提供 Key
  • linux $0命令,Linux:awk命令详解

    简单使用 awk 对于文件中一行行的独处来执行操作 awk F print 1 4 使用 来分割这一行 把这一行的第一第四个域打印出来 AWK命令介绍 awk语言的最基本功能是在文件或字符串中基于指定规则浏览和抽取信息 awk抽取信息后 才
  • 2023最新pycharm详细安装教程,小白必看

    一 python官网 Python官网主要有python的About 简介 Downloads 下载 Documentation 文档 Community 团体 Success Stories 成功案例 News 新闻 Events 事件动
  • 贪吃蛇智能版(专家)

    在高级版本的基础之上 主要针对以下问题进行了处理 当长度逐渐变成 超过100之后 随机wander 追尾有比较大的随机性 弄不好就把自己围死了 这个时候已经不能再看到实物马上就去吃了 在吃之前必须先调整好自身的状态 等到认为调整的差不多的时
  • 如何在sqlserver建立新用户并关联相应的数据库

    我们经常需要在数据库上建立有权限的用户 该用户只能去操作某个特定的数据库 比如该用户只能去读 去写等等 那么我们应该怎么在sqlserver上设置呢 下面的步骤有点长 只要一步一步跟着设置就行 方法 步骤 如果你没有开通sqlserver身
  • GoWeb开发-3.JWT

    1 导入依赖库 go get u github com dgrijalva jwt go 2 生成token import fmt github com gin gonic gin jwt github com dgrijalva jwt