In der modernen Internetarchitektur ist das API-Gateway zu einer wichtigen Komponente geworden und wird häufig in Unternehmens- und Cloud-Computing-Szenarien eingesetzt. Die Hauptfunktion des API-Gateways besteht darin, die API-Schnittstellen mehrerer Microservice-Systeme einheitlich zu verwalten und zu verteilen, Zugriffskontrolle und Sicherheitsschutz bereitzustellen und auch API-Dokumentenverwaltung, -überwachung und -protokollierung durchzuführen.
Um die Sicherheit und Skalierbarkeit des API-Gateways besser zu gewährleisten, wurden dem API-Gateway auch einige Zugriffskontroll- sowie Authentifizierungs- und Autorisierungsmechanismen hinzugefügt. Ein solcher Mechanismus kann die Legitimität zwischen Benutzern und Diensten sicherstellen und Angriffe und illegale Operationen verhindern.
In diesem Artikel stellen wir vor, wie Sie das Gin-Framework verwenden, um API-Gateway sowie Authentifizierungs- und Autorisierungsfunktionen zu implementieren.
1. Einführung in das Gin-Framework
Gin ist ein leichtes Web-Framework, das auf der Go-Sprache basiert. Sein Designziel besteht darin, ein leistungsstarkes Web-Framework bereitzustellen und gleichzeitig Einfachheit und Benutzerfreundlichkeit beizubehalten. Das Gin-Framework bietet allgemeine Webfunktionen wie Routing, Middleware, Vorlagen und Rendering. Es unterstützt auch benutzerdefinierte Middleware und HTTP-Fehlerbehandlungsmethoden, sodass Sie schnell Webanwendungen erstellen können, die Ihren Anforderungen entsprechen.
2. Erstellen Sie das Grundgerüst des API-Gateways
Zuerst müssen wir das Gin-Framework installieren und importieren, um eine grundlegende Webanwendung zu erstellen. Zuvor müssen wir die Go-Sprache in der lokalen Umgebung installieren und dann den folgenden Befehl ausführen, um das Gin-Framework zu installieren.
go get -u github.com/gin-gonic/gin
Als nächstes erstellen wir eine main.go-Datei als Einstiegsdatei des Programms.
package main import "github.com/gin-gonic/gin" func main() { router := gin.Default() router.Any("/", func(c *gin.Context) { c.JSON(200, gin.H{ "message": "Hello, Gin!", }) }) router.Run(":8080") }
Im obigen Code haben wir die Gin-Framework-Bibliothek importiert und eine Standardroute erstellt. Der Stammpfad der Route („/“) kann Antwortinformationen im JSON-Format für jede Anforderungsmethode (Any) zurückgeben. Schließlich haben wir den HTTP-Dienst über die Run-Methode gestartet und den lokalen Port 8080 abgehört.
Jetzt können wir den folgenden Befehl im Terminal eingeben, um das Programm zu starten und zu überprüfen, ob es normal funktionieren kann.
go run main.go
Wenn alles in Ordnung ist, sollten Sie in einem Browser oder einem anderen Client auf http://localhost:8080/ zugreifen und die folgende Antwort im JSON-Format sehen können.
{ "message": "Hello, Gin!" }
3. Implementierung des API-Gateways
Als nächstes implementieren wir das API-Gateway. Bevor wir das API-Gateway implementieren, müssen wir bestimmen, welche Dienste im API-Gateway enthalten sein werden. Dabei gehen wir davon aus, dass wir über ein Benutzerverwaltungssystem, ein Produktverwaltungssystem und ein Bestellverwaltungssystem verfügen und diese drei Systeme über eigene API-Schnittstellen verfügen.
Um die API-Schnittstellen dieser drei Systeme in das API-Gateway einzubinden, müssen wir Routen gruppieren und weiterleiten. Eine einfachere Möglichkeit besteht darin, verschiedene Microservices nach ihren Funktionen zu gruppieren. So kann beispielsweise das Routing definiert werden.
package main import ( "github.com/gin-gonic/gin" "net/http" ) func main() { router := gin.Default() userService := router.Group("/user-service") { userService.GET("/", func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"data": "User Service API"}) }) } productService := router.Group("/product-service") { productService.GET("/", func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"data": "Product Service API"}) }) } orderService := router.Group("/order-service") { orderService.GET("/", func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"data": "Order Service API"}) }) } router.Run(":8080") }
Im obigen Codebeispiel haben wir die Group-Methode des Gin-Frameworks verwendet, um die Routen verschiedener Dienste zu gruppieren und sie unter den drei Pfaden /user-service, /product-service und /order-service zu platzieren. Anschließend fügen wir Routen für verschiedene Dienste hinzu und geben jeweils unterschiedliche Antwortinformationen an. Hier werden nur einfache Zeichenfolgen zurückgegeben.
Wenn Sie das Programm jetzt starten und auf jeden Dienst zugreifen, sollten Sie die folgenden Informationen sehen.
http://localhost:8080/user-service/ gibt {"data": "User Service API"} zurück
http://localhost:8080/product-service/ gibt {"data": "Product Service API" zurück }
http://localhost:8080/order-service/ Gibt {"data": "Order Service API"}
Vier Implementierung von Authentifizierung und Autorisierung
Um die Sicherheit und Skalierbarkeit des API-Gateways zu gewährleisten, Wir müssen auch einen Authentifizierungs- und Autorisierungsmechanismus hinzufügen. Hier können wir JWT (JSON Web Token) verwenden, um Authentifizierungs- und Autorisierungsfunktionen zu implementieren. JWT ist eine einfache Authentifizierungs- und Autorisierungsmethode, die auf Webstandards basiert. Der JWT-Authentifizierungsprozess ist wie folgt.
Wir müssen außerdem die folgenden Bibliotheken installieren, um die Verwendung von JWT zu unterstützen.
go get -u github.com/dgrijalva/jwt-go
Als nächstes müssen wir eine JWT-Anspruchsstruktur definieren und einige notwendige Parameter hinzufügen, wie z. B. Benutzer-ID und Ablaufdatum. Hier wird UserID verwendet, um die eindeutige Identität des Benutzers aufzuzeichnen, und Expiry wird verwendet, um die Gültigkeitsdauer des Tokens aufzuzeichnen.
type CustomClaims struct { UserID string `json:"userID,omitempty"` jwt.StandardClaims }
Als nächstes werden wir drei Funktionen implementieren: genericToken, verifyToken und authMiddleware. Die Funktion „generateToken“ wird zum Generieren von JWT-Token verwendet. Die spezifische Implementierung ist wie folgt.
func generateToken(userID string) (string, error) { claims := CustomClaims{ userID, jwt.StandardClaims{ ExpiresAt: time.Now().Add(time.Hour * 24).Unix(), Issuer: "my-api-gateway", }, } token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) jwtSecret := []byte("my-secret-key") return token.SignedString(jwtSecret) }
Im obigen Code erstellen wir eine Instanz der CustomClaims-Struktur, verwenden die Benutzer-ID als Parameter von Claims und geben die Ablaufzeit und die Ausstellerinformationen des Ausstellers an. Dann verwenden wir den HS256-Algorithmus, um die Ansprüche zu signieren, rufen die SignedString-Methode auf, um das JWT-Token zu generieren, und geben es an den Client zurück.
Als nächstes implementieren wir die Funktion „VerifyToken“, um das Token zu überprüfen.
func verifyToken(tokenString string) (*CustomClaims, error) { jwtSecret := []byte("my-secret-key") token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) { return jwtSecret, nil }) if err != nil { return nil, err } if claims, ok := token.Claims.(*CustomClaims); ok && token.Valid { return claims, nil } return nil, errors.New("invalid token") }
在上面的代码中,我们首先定义了一个JWT Secret(这里我们使用字符串"my-secret-key"作为密钥),然后使用ParseWithClaims方法解析令牌,并将Claims参数设置为CustomClaims类型。然后,我们使用定义的JWT Secret对令牌进行验证,如果验证通过,我们将返回Claims结构体的实例。
最后一个函数是authMiddleware,用于检查请求头中是否携带有效的JWT令牌。如果没有携带或验证失败,中间件将会返回401错误给客户端。
func authMiddleware() gin.HandlerFunc { return func(c *gin.Context) { authHeader := c.GetHeader("Authorization") if authHeader == "" { c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"}) return } tokenString := strings.Replace(authHeader, "Bearer ", "", 1) claims, err := verifyToken(tokenString) if err != nil { c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"}) return } c.Set("userID", claims.UserID) c.Next() } }
在上面的代码中,我们首先从请求头中获取Authorization信息,并判断是否为空。如果为空,返回401错误。然后,我们使用strings.Replace方法将Token中的Bearer前缀进行删除,获取真正的JWT令牌。接着,我们调用verifyToken函数对JWT令牌进行验证,如果验证不通过,返回401错误。最后,我们将userID存储在Context中,以备其他中间件和路由使用。
为了演示JWT认证的功能,我们在/user-service服务中添加一个需要身份验证的路由,例如/user-service/profile,它返回用户的详细信息。修改后的main.go代码示例如下。
func main() { router := gin.Default() userService := router.Group("/user-service") { userService.GET("/", func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"data": "User Service API"}) }) userService.GET("/profile", authMiddleware(), func(c *gin.Context) { userID := c.MustGet("userID").(string) c.JSON(http.StatusOK, gin.H{"data": "User ID: " + userID}) }) } productService := router.Group("/product-service") { productService.GET("/", func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"data": "Product Service API"}) }) } orderService := router.Group("/order-service") { orderService.GET("/", func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"data": "Order Service API"}) }) } router.Run(":8080") }
以上代码中,我们在/user-service/profile路由中使用了authMiddleware中间件,来对身份进行验证。例如,如果你想要访问/user-service/profile接口,你需要在请求头中附带有效的JWT令牌,例如:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySURfaWQiOiIxMjM0NTY3ODkwIiwiZXhwIjoxNjMyMzMzNjE0LCJpc3MiOiJteS1hcGktZ2F0ZXdheSJ9OfXlna_Qb2giRByaev2x7w5zz0S2CJZnMMgZ6sVA
如果你尝试访问此路由,但请求头中没有附带有效的JWT令牌,或者令牌验证失败,你将会得到以下JSON格式的响应。
{ "error": "Unauthorized" }
如果你携带了有效的JWT令牌,你应该可以看到以下格式的响应。
{ "data": "User ID: 1234567890" }
五、总结
在本文中,我们介绍了如何使用Gin框架来实现API网关和认证授权功能。我们创建了一个基本的Web应用程序,并将多个微服务系统的API接口纳入到API网关当中。为了提高API网关的安全性和可扩展性,我们使用了JWT认证和授权的机制,通过设置Claims结构体参数来生成和验证JWT令牌,最后使用了AuthMiddleware来检查请求头中的JWT令牌。
Das obige ist der detaillierte Inhalt vonVerwenden Sie das Gin-Framework, um API-Gateway sowie Authentifizierungs- und Autorisierungsfunktionen zu implementieren. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!