首页 > 后端开发 > Golang > 在 Go API 中实现 JWT 身份验证

在 Go API 中实现 JWT 身份验证

Susan Sarandon
发布: 2024-12-27 20:56:14
原创
431 人浏览过

Implementing JWT Authentication in Go API

JWT(JSON Web 令牌)是一种通过基于令牌的身份验证保护 API 的高效方法,确保只有经过身份验证的用户才能访问您的 API 端点。与传统的基于会话的方法不同,JWT 是无状态的,无需服务器端会话存储,这使其成为可扩展和高性能应用程序的理想选择。在本指南中,我们将引导您在 Go API 中实现 JWT 身份验证,从在用户登录时生成令牌到通过验证这些令牌来保护您的端点,最终增强应用程序数据和资源的安全性和稳健性。

先决条件

  • 去1.21

设置项目

go mod init app
go get github.com/gin-gonic/gin@v1.5.0
go get github.com/golang-jwt/jwt
go get github.com/joho/godotenv 
登录后复制

项目结构

├─ .env
├─ main.go
├─ middleware
│  └─ authenticate.go
└─ public
   ├─ index.html
   └─ login.html
登录后复制

项目文件

.env

jwt_secret = b0WciedNJvFCqFRbB2A1QhZoCDnutAOen5g1FEDO0HsLTwGINp04GXh2OXVpTqQL
登录后复制

此 .env 文件包含一个环境变量 jwt_secret,它保存用于在应用程序中签名和验证 JWT 令牌的密钥。

验证.go

package middleware

import (
    "net/http"
    "os"
    "strings"

    "github.com/gin-gonic/gin"
    "github.com/golang-jwt/jwt"
)

type Claims struct {
    Id int `json:"id"`
    Name string `json:"name"`
    jwt.StandardClaims
}

func Authenticate() gin.HandlerFunc {
    return func(c *gin.Context) {
        if c.Request.URL.Path == "/" || c.Request.URL.Path == "/login" {
            c.Next()
            return
        }
        authHeader := c.GetHeader("Authorization")
        if authHeader == "" {
            c.Status(http.StatusUnauthorized)
            c.Abort()
            return
        }
        tokenString := strings.TrimPrefix(authHeader, "Bearer ")
        token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (interface{}, error) {
            return []byte(os.Getenv("jwt_secret")), nil
        })
        if err != nil || !token.Valid {
            c.Status(http.StatusUnauthorized)
            c.Abort()
            return
        }
        if claims, ok := token.Claims.(*Claims); ok {
            c.Set("user", claims)
        } else {
            c.Status(http.StatusUnauthorized)
            c.Abort()
            return
        }
        c.Next()
    }
}
登录后复制

authenticate.go 中间件使用 Gin 框架在 Go API 中定义了用于 JWT 身份验证的函数。它检查请求是否针对 / 或 /login 路径,在这种情况下不需要身份验证。对于其他路由,它会检索授权标头,并期望获得承载令牌。使用 jwt 包和环境变量中的密钥来解析和验证令牌。如果令牌无效或丢失,请求将中止并显示 401 未经授权状态。如果有效,则会提取用户声明(例如 id 和名称)并将其添加到 Gin 上下文中,从而允许访问受保护的路由。

主程序

package main

import (
    "app/middleware"
    "net/http"
    "os"
    "time"

    "github.com/gin-gonic/gin"
    "github.com/golang-jwt/jwt"
    "github.com/joho/godotenv"
)

func main() {
    godotenv.Load()
    router := gin.Default()
    router.Use(middleware.Authenticate())
    router.LoadHTMLFiles("public/index.html", "public/login.html")

    router.GET("/", func(c *gin.Context) {
        c.HTML(http.StatusOK, "index.html", nil)
    })

    router.GET("/login", func(c *gin.Context) {
        c.HTML(http.StatusOK, "login.html", nil)
    })

    router.GET("/user", func(c *gin.Context) {
        user, _ := c.Get("user")
        claims := user.(*middleware.Claims)
        c.JSON(http.StatusOK, gin.H{"name": claims.Name})
    })

    router.POST("/login", func(c *gin.Context) {
        var login map[string]string
        c.BindJSON(&login)
        if login["name"] == "admin" && login["password"] == "1234" {
            token := jwt.NewWithClaims(jwt.SigningMethodHS256, &middleware.Claims{
                Id: 1,
                Name: login["name"],
                StandardClaims: jwt.StandardClaims{
                    IssuedAt: time.Now().Unix(),
                    ExpiresAt: time.Now().Add(24 * time.Hour).Unix(),
                },
            })
            tokenString, _ := token.SignedString([]byte(os.Getenv("jwt_secret")))
            c.JSON(http.StatusOK, gin.H{"token": tokenString})
        } else {
            c.Status(http.StatusBadRequest)
        }
    })
    router.Run()
}
登录后复制

main.go 文件使用 Gin 框架设置 Go Web 服务器来处理基于 JWT 身份验证的路由。它使用中间件进行身份验证,检查请求中的有效 JWT 令牌。服务器提供两个 HTML 页面:index.html 和 login.html,可通过 / 和 /login 路由访问。

对于 /user 路由,服务器从 JWT 声明中检索经过身份验证的用户名,并在响应中返回它。对于 /login POST 路由,服务器验证用户凭据(名称和密码),如果有效,则生成 JWT 令牌,使用密钥对其进行签名并将其发送回客户端。服务器配置为侦听请求并在默认端口上运行。

索引.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.3/css/bootstrap.min.css" rel="stylesheet">
    <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css" rel="stylesheet">
</head>
<body>
    <div>



<p>The index.html is a simple web page that provides a user interface for displaying the login status of a user. It uses Bootstrap for styling and Font Awesome for icons. On page load, it checks the user's authentication status by sending a request to the server with a JWT token stored in localStorage. If the user is logged in, it shows a success message with the user's name and a logout button. If not logged in, it shows a message indicating the user is not logged in and redirects them to the login page after a few seconds.</p>

<h3>
  
  
  login.html
</h3>



<pre class="brush:php;toolbar:false"><!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.3/css/bootstrap.min.css" rel="stylesheet">
    <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css" rel="stylesheet">
</head>
<body>
    <div>



<p>The login.html page provides a simple login form where users can input their username and password. It uses Bootstrap for styling and Font Awesome for icons. When the user submits the form, a JavaScript function login() sends a POST request to the /login endpoint with the entered credentials. If the login is successful, the server returns a JWT token, which is stored in localStorage. The page then redirects the user to the home page (/). If the login fails, an error message is displayed.</p>

<h2>
  
  
  Run project
</h2>



<pre class="brush:php;toolbar:false">go run main.go
登录后复制

打开网络浏览器并转到http://localhost:8080

你会发现这个测试页。

Implementing JWT Authentication in Go API

测试

几秒钟后,您将被重定向到登录页面。

Implementing JWT Authentication in Go API

点击登录按钮,您将登录到主页,主页上会显示登录用户的名字。

Implementing JWT Authentication in Go API

尝试刷新浏览器,您会看到您仍然处于登录状态。然后,按注销按钮,JWT 令牌将被删除,您将再次重定向到登录页面。

Implementing JWT Authentication in Go API

结论

总之,在 Go API 中实现 JWT 身份验证提供了一种安全且可扩展的方法来处理用户身份验证。通过使用 Gin 框架以及 golang-jwt/jwt 包,我们可以轻松地将基于令牌的身份验证集成到我们的应用程序中。 JWT 令牌是在登录期间生成的,用于安全地验证用户凭据并授予对受保护路由的访问权限。中间件通过验证令牌的有效性来确保只有经过身份验证的用户才能访问这些路由。这种无状态身份验证机制提供了增强的性能和灵活性,使其成为现代 API 架构的理想选择。

源代码:https://github.com/stackpuz/Example-JWT-Go

在几分钟内创建一个 CRUD Web 应用程序:https://stackpuz.com

以上是在 Go API 中实现 JWT 身份验证的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:dev.to
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板