跳转到主要内容

标签(标签)

资源精选(342) Go开发(108) Go语言(103) Go(99) angular(82) LLM(75) 大语言模型(63) 人工智能(53) 前端开发(50) LangChain(43) golang(43) 机器学习(39) Go工程师(38) Go程序员(38) Go开发者(36) React(33) Go基础(29) Python(24) Vue(22) Web开发(20) Web技术(19) 精选资源(19) 深度学习(19) Java(18) ChatGTP(17) Cookie(16) android(16) 前端框架(13) JavaScript(13) Next.js(12) 安卓(11) typescript(10) 资料精选(10) NLP(10) 第三方Cookie(9) Redwoodjs(9) LLMOps(9) Go语言中级开发(9) 自然语言处理(9) 聊天机器人(9) PostgreSQL(9) 区块链(9) mlops(9) 安全(9) 全栈开发(8) ChatGPT(8) OpenAI(8) Linux(8) AI(8) GraphQL(8) iOS(8) 软件架构(7) Go语言高级开发(7) AWS(7) C++(7) 数据科学(7) whisper(6) Prisma(6) 隐私保护(6) RAG(6) JSON(6) DevOps(6) 数据可视化(6) wasm(6) 计算机视觉(6) 算法(6) Rust(6) 微服务(6) 隐私沙盒(5) FedCM(5) 语音识别(5) Angular开发(5) 快速应用开发(5) 提示工程(5) Agent(5) LLaMA(5) 低代码开发(5) Go测试(5) gorm(5) REST API(5) 推荐系统(5) WebAssembly(5) GameDev(5) CMS(5) CSS(5) machine-learning(5) 机器人(5) 游戏开发(5) Blockchain(5) Web安全(5) Kotlin(5) 低代码平台(5) 机器学习资源(5) Go资源(5) Nodejs(5) PHP(5) Swift(5) 智能体(4) devin(4) Blitz(4) javascript框架(4) Redwood(4) GDPR(4) 生成式人工智能(4) Angular16(4) Alpaca(4) SAML(4) JWT(4) JSON处理(4) Go并发(4) kafka(4) 移动开发(4) 移动应用(4) security(4) 隐私(4) spring-boot(4) 物联网(4) nextjs(4) 网络安全(4) API(4) Ruby(4) 信息安全(4) flutter(4) 专家智能体(3) Chrome(3) CHIPS(3) 3PC(3) SSE(3) 人工智能软件工程师(3) LLM Agent(3) Remix(3) Ubuntu(3) GPT4All(3) 软件开发(3) 问答系统(3) 开发工具(3) 最佳实践(3) RxJS(3) SSR(3) Node.js(3) Dolly(3) 移动应用开发(3) 编程语言(3) 低代码(3) IAM(3) Web框架(3) CORS(3) 基准测试(3) Go语言数据库开发(3) Oauth2(3) 并发(3) 主题(3) Theme(3) earth(3) nginx(3) 软件工程(3) azure(3) keycloak(3) 生产力工具(3) gpt3(3) 工作流(3) C(3) jupyter(3) 认证(3) prometheus(3) GAN(3) Spring(3) 逆向工程(3) 应用安全(3) Docker(3) Django(3) R(3) .NET(3) 大数据(3) Hacking(3) 渗透测试(3) C++资源(3) Mac(3) 微信小程序(3) Python资源(3) JHipster(3) 大型语言模型(2) 语言模型(2) 可穿戴设备(2) JDK(2) SQL(2) Apache(2) Hashicorp Vault(2) Spring Cloud Vault(2) Go语言Web开发(2) Go测试工程师(2) WebSocket(2) 容器化(2) AES(2) 加密(2) 输入验证(2) ORM(2) Fiber(2) Postgres(2) Gorilla Mux(2) Go数据库开发(2) 模块(2) 泛型(2) 指针(2) HTTP(2) PostgreSQL开发(2) Vault(2) K8s(2) Spring boot(2) R语言(2) 深度学习资源(2) 半监督学习(2) semi-supervised-learning(2) architecture(2) 普罗米修斯(2) 嵌入模型(2) productivity(2) 编码(2) Qt(2) 前端(2) Rust语言(2) NeRF(2) 神经辐射场(2) 元宇宙(2) CPP(2) 数据分析(2) spark(2) 流处理(2) Ionic(2) 人体姿势估计(2) human-pose-estimation(2) 视频处理(2) deep-learning(2) kotlin语言(2) kotlin开发(2) burp(2) Chatbot(2) npm(2) quantum(2) OCR(2) 游戏(2) game(2) 内容管理系统(2) MySQL(2) python-books(2) pentest(2) opengl(2) IDE(2) 漏洞赏金(2) Web(2) 知识图谱(2) PyTorch(2) 数据库(2) reverse-engineering(2) 数据工程(2) swift开发(2) rest(2) robotics(2) ios-animation(2) 知识蒸馏(2) 安卓开发(2) nestjs(2) solidity(2) 爬虫(2) 面试(2) 容器(2) C++精选(2) 人工智能资源(2) Machine Learning(2) 备忘单(2) 编程书籍(2) angular资源(2) 速查表(2) cheatsheets(2) SecOps(2) mlops资源(2) R资源(2) DDD(2) 架构设计模式(2) 量化(2) Hacking资源(2) 强化学习(2) flask(2) 设计(2) 性能(2) Sysadmin(2) 系统管理员(2) Java资源(2) 机器学习精选(2) android资源(2) android-UI(2) Mac资源(2) iOS资源(2) Vue资源(2) flutter资源(2) JavaScript精选(2) JavaScript资源(2) Rust开发(2) deeplearning(2) RAD(2)

注意 - 本教程的完整源代码可以在这里找到:TutorialEdge/go-jwt-tutorial

JWT,或者更正式地称为 JSON Web 令牌,是一种紧凑的、URL 安全的方式,用于表示要在两方之间传输的声明。这本质上是一种令人困惑的说法,即 JWT 允许您以无状态但安全的方式将信息从客户端传输到服务器。

先决条件


在您阅读本文之前,您将需要以下内容:

  • 您需要在开发机器上安装 Go 版本 1.11+。

介绍


JWT 标准使用 HMAC 算法的密钥或使用 RSA 或 ECDSA 的公钥/私钥对。

注意 - 如果您对 JWT 的正式定义感兴趣,那么我建议您查看 RFC:RFC-7519

这些在单页应用程序 (SPA) 中被大量用作安全通信的手段,因为它们允许我们做两件关键的事情:

  • 身份验证 - 最常用的做法。一旦用户登录到您的应用程序或以某种方式进行身份验证,然后代表用户从客户端发送的每个请求都将包含 JWT。
  • 信息交换——JWT 的第二个用途是在不同系统之间安全地传输信息。这些 JWT 可以使用公钥/私钥对进行签名,因此您可以以安全的方式验证此事务中的每个系统,并且 JWT 包含防篡改机制,因为它们是基于标头和有效负载进行签名的。

因此,如果您现在还没有猜到,在本教程中,我们将确切了解构建使用 JSON Web 令牌进行通信的基于 Go 的安全 REST API 需要什么!

视频教程


本教程以视频格式提供,如果您想支持我和我的工作,请随时点赞并订阅我的频道以获取我的内容!

https://youtu.be/-Scg9INymBs

一个简单的 REST API


因此,我们将使用我的另一篇文章中的代码,在 Go 中创建一个简单的 REST API,让我们开始。这将具有一个非常简单的 Hello World 风格的端点,它将在端口 8081 上运行。

package main

import (
    "fmt"
    "log"
    "net/http"
)

func homePage(w http.ResponseWriter, r *http.Request){
    fmt.Fprintf(w, "Hello World")
    fmt.Println("Endpoint Hit: homePage")
}

func handleRequests() {
    http.HandleFunc("/", homePage)
    log.Fatal(http.ListenAndServe(":8081", nil))
}

func main() {
    handleRequests()
}

当我们尝试访问我们的主页时,在 http://localhost:8081/ 上运行,我们应该在浏览器中看到消息 Hello World。

JWT 认证


所以,既然我们有了一个简单的 API,我们现在可以使用签名的 JWT 令牌来保护它,让我们构建一个客户端 API,它将尝试从这个原始 API 请求数据。

为此,我们可以使用已使用安全密钥签名的 JWT,我们的客户端和服务器都将知道该密钥。让我们来看看它是如何工作的:

  • 我们的客户将根据我们的共享密码生成一个签名的 JWT。
  • 当我们的客户端访问我们的服务器 API 时,它将包含这个 JWT 作为请求的一部分。
  • 我们的服务器将能够读取此 JWT 并使用相同的密码验证令牌。
  • 如果 JWT 有效,则将高度机密的 hello world 消息返回给客户端,否则将返回未授权。

我们的架构图最终看起来有点像这样:

架构图

architecture-diagram

 

我们的服务器


所以,让我们看看这个,让我们创建一个非常简单的服务器:

package main

import (
    "fmt"
    "log"
    "net/http"

    jwt "github.com/dgrijalva/jwt-go"
)

var mySigningKey = []byte("captainjacksparrowsayshi")

func homePage(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello World")
    fmt.Println("Endpoint Hit: homePage")

}

func isAuthorized(endpoint func(http.ResponseWriter, *http.Request)) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

        if r.Header["Token"] != nil {

            token, err := jwt.Parse(r.Header["Token"][0], func(token *jwt.Token) (interface{}, error) {
                if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
                    return nil, fmt.Errorf("There was an error")
                }
                return mySigningKey, nil
            })

            if err != nil {
                fmt.Fprintf(w, err.Error())
            }

            if token.Valid {
                endpoint(w, r)
            }
        } else {

            fmt.Fprintf(w, "Not Authorized")
        }
    })
}

func handleRequests() {
    http.Handle("/", isAuthorized(homePage))
    log.Fatal(http.ListenAndServe(":9000", nil))
}

func main() {
    handleRequests()
}

让我们分解一下。 我们创建了一个非常简单的 API,它具有一个单独的端点,它受到我们的 isAuthorized 中间件装饰器的保护。 在这个 isAuthorized 函数中,我们检查传入请求是否包含请求中的 Token 标头,然后我们随后根据我们的私有 mySigningKey 检查令牌是否有效。

如果这是一个有效的令牌,我们就会为受保护的端点提供服务。

注意 - 这个例子使用了装饰器,如果你对 Go 中装饰器的概念不满意,那么我建议你在这里查看我的另一篇文章:Go 中的装饰器入门

我们的客户


现在我们有了一个具有 JWT 安全端点的服务器,让我们构建一些可以与之交互的东西。

我们将构建一个简单的客户端应用程序,它将尝试调用我们服务器的 / 端点。

package main

import (
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
    "time"

    jwt "github.com/dgrijalva/jwt-go"
)

var mySigningKey = []byte("captainjacksparrowsayshi")

func homePage(w http.ResponseWriter, r *http.Request) {
    validToken, err := GenerateJWT()
    if err != nil {
        fmt.Println("Failed to generate token")
    }

    client := &http.Client{}
    req, _ := http.NewRequest("GET", "http://localhost:9000/", nil)
    req.Header.Set("Token", validToken)
    res, err := client.Do(req)
    if err != nil {
        fmt.Fprintf(w, "Error: %s", err.Error())
    }

    body, err := ioutil.ReadAll(res.Body)
    if err != nil {
        fmt.Println(err)
    }
    fmt.Fprintf(w, string(body))
}

func GenerateJWT() (string, error) {
    token := jwt.New(jwt.SigningMethodHS256)

    claims := token.Claims.(jwt.MapClaims)

    claims["authorized"] = true
    claims["client"] = "Elliot Forbes"
    claims["exp"] = time.Now().Add(time.Minute * 30).Unix()

    tokenString, err := token.SignedString(mySigningKey)

    if err != nil {
        fmt.Errorf("Something Went Wrong: %s", err.Error())
        return "", err
    }

    return tokenString, nil
}

func handleRequests() {
    http.HandleFunc("/", homePage)

    log.Fatal(http.ListenAndServe(":9001", nil))
}

func main() {
    handleRequests()
}

让我们分解上面代码中发生的事情。 同样,我们定义了一个非常简单的 API,它具有单个端点。 该端点在触发时会使用我们的安全 mySigningKey 生成一个新的 JWT,然后它会创建一个新的 http 客户端并将 Token 标头设置为我们刚刚生成的 JWT 字符串。

然后它会尝试使用这个签名的 JWT 令牌访问我们在 http://localhost:9000 上运行的服务器应用程序。 然后,我们的服务器验证我们在客户端生成的令牌,并继续为我们提供超级机密的 Hello World 消息。

结论


希望本教程有助于揭开使用 JSON Web 令牌保护 Go 应用程序和 REST API 的神秘面纱。 写这篇文章很有趣,我希望它对你的 Go 开发之旅有所帮助。

如果您喜欢本教程,请在下面的评论部分告诉我,或者在社交媒体上分享这篇文章,它真的对我和我的网站有帮助!

文章链接