Dans l'architecture Internet moderne, la passerelle API est devenue un composant important et est largement utilisée dans les scénarios d'entreprise et de cloud computing. La fonction principale de la passerelle API est de gérer et de distribuer uniformément les interfaces API de plusieurs systèmes de microservices, de fournir un contrôle d'accès et une protection de sécurité, et peut également effectuer la gestion, la surveillance et la journalisation des documents API.
Afin de mieux assurer la sécurité et l'évolutivité de la passerelle API, certains mécanismes de contrôle d'accès et d'authentification et d'autorisation ont également été ajoutés à la passerelle API. Un tel mécanisme peut garantir la légitimité entre les utilisateurs et les services et prévenir les attaques et les opérations illégales.
Dans cet article, nous présenterons comment utiliser le framework Gin pour implémenter la passerelle API et les fonctions d'authentification et d'autorisation.
1. Introduction au framework Gin
Gin est un framework Web léger développé sur la base du langage Go. Son objectif de conception est de fournir un framework Web performant tout en conservant simplicité et facilité d'utilisation. Le framework Gin fournit des fonctions Web courantes telles que le routage, le middleware, les modèles et le rendu. Il prend également en charge les méthodes de middleware personnalisées et de gestion des erreurs HTTP, vous permettant de créer rapidement des applications Web qui répondent à vos besoins.
2. Construisez le framework de base de la passerelle API
Tout d'abord, nous devons installer et importer le framework Gin pour créer une application Web de base. Avant cela, nous devons installer le langage Go dans l'environnement local, puis exécuter la commande suivante pour installer le framework Gin.
go get -u github.com/gin-gonic/gin
Ensuite, nous créons un fichier main.go comme fichier d'entrée du programme.
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") }
Dans le code ci-dessus, nous avons importé la bibliothèque du framework Gin et créé une route par défaut. Le chemin racine de la route ("/") peut renvoyer des informations de réponse au format JSON pour n'importe quelle méthode de requête (Any). Enfin, nous avons démarré le service HTTP via la méthode Run et écouté le port local 8080.
Maintenant, nous pouvons saisir la commande suivante dans le terminal pour démarrer le programme et vérifier s'il peut fonctionner normalement.
go run main.go
Si tout va bien, vous devriez pouvoir accéder à http://localhost:8080/ dans un navigateur ou un autre client et voir la réponse suivante au format JSON.
{ "message": "Hello, Gin!" }
3. Implémentation de la passerelle API
Ensuite, nous implémenterons la passerelle API. Avant de mettre en œuvre la passerelle API, nous devons déterminer quels services seront inclus dans la passerelle API. Ici, nous supposons que nous disposons d'un système de gestion des utilisateurs, d'un système de gestion des produits et d'un système de gestion des commandes, et ces trois systèmes ont leurs propres interfaces API.
Afin d'incorporer les interfaces API de ces trois systèmes dans la passerelle API, nous devons regrouper et transférer les routes. Un moyen plus simple consiste à regrouper différents microservices en fonction de leurs fonctions. Par exemple, le routage peut être défini comme ceci.
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") }
Dans l'exemple de code ci-dessus, nous avons utilisé la méthode Group du framework Gin pour regrouper les itinéraires de différents services et les avons placés sous les trois chemins de /user-service, /product-service et /order-service. Ensuite, nous ajoutons des routes pour différents services et spécifions respectivement différentes informations de réponse. Ici, seules des chaînes simples sont renvoyées.
Si vous lancez le programme maintenant et accédez à chaque service, vous devriez voir les informations suivantes.
http://localhost:8080/user-service/ renvoie {"data": "API du service utilisateur"}
http://localhost:8080/product-service/ renvoie {"data": "API du service produit" }
http://localhost:8080/order-service/ Returns {"data": "Order Service API"}
Quatre Mise en œuvre de l'authentification et de l'autorisation
Afin d'assurer la sécurité et l'évolutivité de la passerelle API, nous également Un mécanisme d'authentification et d'autorisation doit être ajouté. Ici, nous pouvons utiliser JWT (JSON Web Token) pour implémenter des fonctions d'authentification et d'autorisation. JWT est une méthode légère d'authentification et d'autorisation basée sur les standards du Web. Le processus d'authentification JWT est le suivant.
Nous devons également installer les bibliothèques suivantes pour prendre en charge l'utilisation de JWT.
go get -u github.com/dgrijalva/jwt-go
Ensuite, nous devons définir une structure de réclamations JWT et ajouter certains paramètres nécessaires, tels que l'ID utilisateur et les informations d'expiration. Ici, UserID est utilisé pour enregistrer l'identité unique de l'utilisateur, et Expiry est utilisé pour enregistrer la période de validité du jeton.
type CustomClaims struct { UserID string `json:"userID,omitempty"` jwt.StandardClaims }
Ensuite, nous implémenterons trois fonctions, generateToken, verifyToken et authMiddleware. La fonction generateToken est utilisée pour générer des jetons JWT. L'implémentation spécifique est la suivante.
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) }
Dans le code ci-dessus, nous créons une instance de la structure CustomClaims, utilisons userID comme paramètre de Claims et spécifions le délai d'expiration et les informations sur l'émetteur. Ensuite, nous utilisons l'algorithme HS256 pour signer les revendications, appelons la méthode SignedString pour générer le jeton JWT et le renvoyons au client.
Ensuite, nous implémenterons la fonction verifyToken pour vérifier le jeton.
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令牌。
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!