ในขอบเขตของการพัฒนาเว็บไซต์สมัยใหม่ การสร้างขั้นตอนการตรวจสอบสิทธิ์ผู้ใช้ที่ปลอดภัยและมีประสิทธิภาพเป็นสิ่งสำคัญยิ่ง ด้วยการเพิ่มขึ้นของไมโครเซอร์วิสและสถาปัตยกรรมแบบกระจาย การใช้กลยุทธ์การรับรองความถูกต้องที่มีประสิทธิภาพจึงมีความสำคัญมากยิ่งขึ้น
รูปแบบการตรวจสอบสิทธิ์ Backend for Frontend (BFF) เป็นวิธีการออกแบบที่มุ่งเน้นไปที่การจัดหาแบ็กเอนด์เฉพาะเพื่อจัดการและจัดการกับข้อกำหนดในการตรวจสอบสิทธิ์และความท้าทายทั้งหมดของแอปพลิเคชันส่วนหน้า (SPA)
วัตถุประสงค์
วัตถุประสงค์หลักของบล็อกเทคโนโลยีคือการให้ความรู้แก่ผู้อ่านเกี่ยวกับรูปแบบการตรวจสอบสิทธิ์ Backend for Frontend (BFF) และการนำไปใช้ในภาษาการเขียนโปรแกรม Go บล็อกนี้จะให้ภาพรวมที่ครอบคลุมของรูปแบบ คุณประโยชน์ของรูปแบบ และความท้าทายที่แก้ไขในบริบทของการสร้างระบบการตรวจสอบสิทธิ์สำหรับแอปพลิเคชันส่วนหน้า
ประวัติ
โดยทั่วไปแล้ว SPA จะใช้การรับรองความถูกต้องโดยใช้โทเค็น เช่น JSON Web Tokens (JWT) เพื่อรับรองความถูกต้องและให้สิทธิ์ผู้ใช้ อย่างไรก็ตาม การจัดการโทเค็นอย่างปลอดภัยใน SPA อาจเป็นเรื่องที่ท้าทาย การจัดเก็บโทเค็นในพื้นที่จัดเก็บข้อมูลฝั่งไคลเอ็นต์ (เช่น พื้นที่จัดเก็บในเครื่องหรือคุกกี้) อาจทำให้โทเค็นถูกโจมตีได้ เช่น การปลอมแปลงคำขอข้ามไซต์ (CSRF) นักพัฒนาต้องใช้มาตรการรักษาความปลอดภัยที่เข้มงวดเพื่อปกป้องโทเค็นและป้องกันการเข้าถึงหรือการใช้ในทางที่ผิดโดยไม่ได้รับอนุญาต
รูปแบบ BFF แก้ปัญหานี้โดยการแนะนำเลเยอร์ระดับกลาง — แบ็กเอนด์สำหรับส่วนหน้า เลเยอร์นี้ทำหน้าที่เป็นพร็อกซีระหว่างไคลเอ็นต์ส่วนหน้าและบริการแบ็กเอนด์หลัก จัดการข้อกังวลที่เกี่ยวข้องกับการรับรองความถูกต้อง และจัดเตรียมอินเทอร์เฟซการรับรองความถูกต้องแบบพิเศษ
แผนภาพการไหล
1. เมื่อส่วนหน้าจำเป็นต้องตรวจสอบสิทธิ์ผู้ใช้ ระบบจะเรียกจุดสิ้นสุด API (/login) บน BFF เพื่อเริ่มการจับมือเข้าสู่ระบบ
2. BFF ใช้ OAuth2 Authorization Code Flow เพื่อเชื่อมต่อกับ Auth0 เพื่อตรวจสอบสิทธิ์และให้สิทธิ์ผู้ใช้ และรับ ID และโทเค็นการเข้าถึง
3. แบ็กเอนด์เก็บโทเค็นของผู้ใช้ไว้ในแคช
4. มีการออกคุกกี้ที่เข้ารหัสสำหรับส่วนหน้าที่แสดงถึงเซสชันการตรวจสอบสิทธิ์ผู้ใช้
5. เมื่อส่วนหน้าจำเป็นต้องเรียกใช้ API ภายนอก ส่วนหน้าจะส่งผ่านคุกกี้ที่เข้ารหัสไปยัง BFF พร้อมด้วย URL และข้อมูลเพื่อเรียกใช้ API
6. BFF ดึงโทเค็นการเข้าถึงจากแคชและทำการเรียกไปยัง API แบ็กเอนด์ รวมถึงโทเค็นนั้นบนส่วนหัวของการอนุญาต
7. เมื่อ API ภายนอกส่งคืนการตอบกลับไปยัง BFF API นี้จะส่งต่อการตอบกลับนั้นกลับไปยังส่วนหน้า
การนำไปปฏิบัติ
ข้อกำหนดเบื้องต้น
ตามข้อกำหนดเบื้องต้นในการทำความเข้าใจโซลูชันที่นำเสนออย่างถ่องแท้ ฉันขอแนะนำให้คุณทำความเข้าใจเกี่ยวกับหัวข้อต่อไปนี้ หากยังไม่ทราบหัวข้อเหล่านี้
1. ลงทะเบียนแอปพลิเคชันเว็บปกติใน Auth0
2. “งาน Iris Web Frame”
โครงสร้างโครงการ
เริ่ม
เพื่อเริ่มต้นกระบวนการนำไปใช้งาน ฉันอ้างอิงถึง Auth0 Guide เพื่อลงทะเบียนเว็บแอปพลิเคชันของฉัน ตามคำแนะนำ ฉันตั้งค่าการตรวจสอบสิทธิ์ผู้ใช้สำหรับเว็บแอปพลิเคชันโดยใช้ Auth0 ได้สำเร็จ ด้วยฟังก์ชันการตรวจสอบสิทธิ์เริ่มต้น ฉันจึงดำเนินการแก้ไขโค้ดเพื่อรวมรูปแบบการตรวจสอบสิทธิ์ Backend for Frontend (BFF) router.go
เราเตอร์.go
ใน router.go ฉันกำหนดเส้นทางทั้งหมดที่จำเป็นในการตรวจสอบสิทธิ์และอนุญาตผู้ใช้
- `/login`: จุดสิ้นสุดนี้จะถูกทริกเกอร์เมื่อผู้ใช้คลิกที่ปุ่มเข้าสู่ระบบในส่วนหน้า
- `/logout`: ส่วนหน้ากำหนดเส้นทางไปยังปลายทางนี้เมื่อผู้ใช้คลิกที่ปุ่มออกจากระบบ
- `/callback`: ตำแหน่งข้อมูลนี้รับผิดชอบกระบวนการแลกเปลี่ยนโทเค็นด้วยรหัสอนุญาต
- `/shorten`: นี่เป็นหนึ่งใน API แบ็กเอนด์ที่ส่วนหน้าจะใช้
type router struct{} func (router *router) InitRouter(auth *authenticator.Authenticator, redis interfaces.IRedisLayer) *iris.Application { app := iris.New() loginHandler := controller.LoginHandler{Auth: auth} callbackHandler := controller.CallbackHandler{Auth: auth, RedisClient: redis} logoutHandler := controller.LogoutHandler{RedisClient: redis} backendApiHandler := controller.BackendApiHandler{RedisClient: redis} middlewareHandler := middleware.MiddlewareHandler{RedisClient: redis} app.Get("/login", loginHandler.Login) app.Get("/callback", callbackHandler.Callback) app.Get("/logout", logoutHandler.Logout) // Backend Api app.Post("/shorten", middlewareHandler.IsAuthenticated, backendApiHandler.WriterRedirect) return app }
สิ่งสำคัญที่ควรทราบคือการใช้ตัวจัดการ middlewareHandler.IsAuthenticated ในเส้นทาง API แบ็กเอนด์ ตัวจัดการนี้มีบทบาทสำคัญในการตรวจสอบโปรไฟล์การเข้าสู่ระบบของผู้ใช้ คุณสามารถดูรายละเอียดการใช้งานได้ในส่วนมิดเดิลแวร์
คอนโทรลเลอร์
ในคอนโทรลเลอร์ ฉันได้สรุปตรรกะสำหรับเส้นทางทั้งหมดที่กล่าวถึงก่อนหน้านี้ นี่คือที่ที่มีการกำหนดและจัดการรายละเอียดการใช้งานสำหรับแต่ละเส้นทาง
- login.go
ในเส้นทางการเข้าสู่ระบบ ตัวจัดการจะเปลี่ยนเส้นทางผู้ใช้ไปยังหน้าเข้าสู่ระบบสากลของ Identity Provider (IDP) หน้านี้อนุญาตให้ผู้ใช้ดำเนินการลงชื่อเพียงครั้งเดียวและให้ความยินยอม
หลังจากที่ผู้ใช้ให้ความยินยอมในหน้าเข้าสู่ระบบ IDP Universal หน้าเว็บจะถูกเปลี่ยนเส้นทางกลับไปยังตำแหน่งข้อมูล /callback พร้อมด้วยรหัสอนุญาต
type LoginHandler struct { Auth *authenticator.Authenticator } func (l *LoginHandler) Login(ctx iris.Context) { ctx.Redirect(l.Auth.AuthCodeURL(state, oauth2.SetAuthURLParam("audience", config.EnvVariables.Auth0Audience)), http.StatusTemporaryRedirect) }
พารามิเตอร์ผู้ชมมีบทบาทสำคัญในการอ้างสิทธิ์ผู้ชมภายในเพย์โหลด ซึ่งช่วยในการอนุญาตผู้ใช้ เพื่อความเข้าใจที่ละเอียดยิ่งขึ้น ขอแนะนำให้อ้างอิงถึง "แหล่งข้อมูลเพิ่มเติม"
ความท้าทายที่สำคัญคือการรวมพารามิเตอร์ URL ผู้ชมไว้ในฟังก์ชัน l.Auth.AuthCodeURL() เมื่อตรวจสอบ "ซอร์สโค้ด" ของ "แพ็คเกจ oauth2" และทำความเข้าใจการใช้งาน ฉันได้รับข้อมูลเชิงลึกเกี่ยวกับวิธีส่งพารามิเตอร์ผู้ชมโดยใช้ oauth2.SetAuthURLParam()
- callback.go
หลังจากที่ผู้ใช้เยี่ยมชมเส้นทาง /login แล้ว URL /callback จะถูกเรียก โดยส่งสถานะและรหัสการอนุญาตเป็นพารามิเตอร์
ตัวจัดการที่รับผิดชอบ /callback URL จะตรวจสอบค่าของพารามิเตอร์ state เพื่อให้มั่นใจในความสมบูรณ์และความปลอดภัย
เมื่อค่าสถานะได้รับการตรวจสอบเรียบร้อยแล้ว ตัวจัดการจะดำเนินการแลกเปลี่ยนรหัสการอนุญาตสำหรับโทเค็นการเข้าถึง
นอกเหนือจากการแลกเปลี่ยนโทเค็นแล้ว ตัวจัดการยังดำเนินขั้นตอนที่จำเป็นเพื่อบันทึกโทเค็นและข้อมูลโปรไฟล์ผู้ใช้ใน Redis ซึ่งเป็นที่เก็บข้อมูลที่ใช้กันทั่วไปสำหรับการแคชและการจัดการเซสชัน
type CallbackHandler struct { Auth *authenticator.Authenticator RedisClient interfaces.IRedisLayer } func (c *CallbackHandler) Callback(ctx iris.Context) { if ctx.URLParam("state") != state { ctx.StopWithJSON(http.StatusBadRequest, "Invalid state parameter.") return } // Exchange an authorization code for a token. token, err := c.Auth.Exchange(ctx.Request().Context(), ctx.URLParam("code")) if err != nil { ctx.StopWithJSON(http.StatusUnauthorized, "Failed to convert an authorization code into a token.") return } idToken, err := c.Auth.VerifyIDToken(ctx.Request().Context(), token) if err != nil { ctx.StopWithJSON(http.StatusInternalServerError, "Failed to verify ID Token.") return } var profile map[string]interface{} if err := idToken.Claims(&profile); err != nil { ctx.StopWithError(http.StatusInternalServerError, err) return } err = c.RedisClient.SetKeyValue(profile["email"].(string)+"_token", token.AccessToken, 24*time.Hour) if err != nil { ctx.StopWithError(http.StatusInternalServerError, err) return } err = c.RedisClient.HSetKeyValue(profile["email"].(string)+"_profile", profile, 24*time.Hour) if err != nil { ctx.StopWithError(http.StatusInternalServerError, err) return } ctx.SetCookieKV("logged_id_email", profile["email"].(string)) // Redirect to logged in page. ctx.Redirect(config.EnvVariables.FrontendURL, http.StatusTemporaryRedirect) }
เพื่อจัดเก็บโทเค็นและข้อมูลโปรไฟล์ ฉันได้ติดตั้ง "Redis" เป็นเลเยอร์แคช ฉันสร้างคีย์สำหรับผู้ใช้แต่ละคนโดยนำหน้าด้วยที่อยู่อีเมลเพื่อให้แน่ใจว่าไม่ซ้ำกันและดึงข้อมูลได้ง่าย
นอกจากนี้ ฟังก์ชัน ctx.SetCookieKV() ยังใช้เพื่อตั้งค่าการเข้ารหัส คุกกี้ "HTTP เท่านั้น" ฟรอนต์เอนด์จะส่งคุกกี้นี้ในภายหลังเมื่อทำการเรียกไปยัง API แบ็กเอนด์
- logout.go
เมื่อผู้ใช้คลิกที่ปุ่มออกจากระบบ ตัวจัดการการออกจากระบบจะดำเนินการหลักสองประการ ประการแรก จะล้างค่าที่แคชไว้ทั้งหมด เพื่อให้แน่ใจว่าโทเค็นที่เก็บไว้หรือข้อมูลโปรไฟล์ผู้ใช้จะถูกลบออก ประการที่สอง เริ่มต้นกระบวนการออกจากระบบด้วย Auth0 (IDP) ซึ่งจะออกจากระบบผู้ใช้จากผู้ให้บริการข้อมูลประจำตัวอย่างมีประสิทธิภาพ
type LogoutHandler struct { RedisClient interfaces.IRedisLayer } func (l *LogoutHandler) Logout(ctx iris.Context) { userCookie := ctx.GetCookie("logged_id_email") if userCookie == "" { ctx.StopWithError(iris.StatusUnauthorized, errors.New("please make sure user is logged in")) return } // delete token key err := l.RedisClient.DeleteKey(userCookie + "_token") if err != nil { ctx.StopWithError(http.StatusInternalServerError, err) return } // delete profile key err = l.RedisClient.DeleteKey(userCookie + "_profile") if err != nil { ctx.StopWithError(http.StatusInternalServerError, err) return } logoutUrl, err := url.Parse("https://" + config.EnvVariables.Auth0Domain + "/v2/logout") if err != nil { ctx.StopWithError(http.StatusInternalServerError, err) return } returnTo, err := url.Parse(config.EnvVariables.ShortifyFrontendDomain) if err != nil { ctx.StopWithError(http.StatusInternalServerError, err) return } // remove the logged_id_email http-only cookie from context ctx.RemoveCookie("logged_id_email") parameters := url.Values{} parameters.Add("returnTo", returnTo.String()) parameters.Add("client_id", config.EnvVariables.Auth0ClientID) logoutUrl.RawQuery = parameters.Encode() ctx.Redirect(logoutUrl.String(), http.StatusTemporaryRedirect) }
หากต้องการลบข้อมูลที่แคชไว้ รวมถึงโปรไฟล์ผู้ใช้และโทเค็นที่จัดเก็บไว้ใน Redis ฉันใช้ฟังก์ชัน RedisClient.DeleteKey() เพื่อให้แน่ใจว่าข้อมูลที่เกี่ยวข้องจะถูกลบออกจากแคช นอกจากนี้ การเรียก /v2/logout API ของ Auth0 ยังช่วยให้เราออกจากระบบผู้ใช้จาก Auth0 ได้อย่างมีประสิทธิภาพอีกด้วย
หากต้องการลบคุกกี้เฉพาะ ctx.RemoveCookie() ถูกใช้ ฟังก์ชันนี้กำหนดเป้าหมายและลบคุกกี้ 'logged_id_email' โดยเฉพาะ ซึ่งตั้งค่าไว้ตั้งแต่แรกในระหว่างตัวจัดการ /callback
- backendApi.go
เมื่อฟรอนต์เอนด์ส่งคำขอไปยัง API แบ็กเอนด์ตัวใดตัวหนึ่ง แบ็กเอนด์สำหรับฟรอนต์เอนด์ (BFF) จะทำให้แน่ใจว่าจะดึงโทเค็นผู้ใช้จาก แคช โทเค็นนี้จำเป็นสำหรับวัตถุประสงค์ในการตรวจสอบสิทธิ์และการอนุญาต
จากนั้น BFF จะเพิ่มโทเค็นที่ดึงข้อมูลไปยังส่วนหัวการอนุญาตของคำขอและส่งต่อไปยัง API แบ็กเอนด์
เมื่อ API แบ็กเอนด์ประมวลผลคำขอและสร้าง การตอบสนอง BFF ทำหน้าที่เป็นพร็อกซีและส่งการตอบกลับกลับไปยังส่วนหน้า ทำให้สามารถสื่อสารได้อย่างราบรื่นระหว่างส่วนหน้าและส่วนหลัง
type BackendApiHandler struct { RedisClient interfaces.IRedisLayer } func (w *BackendApiHandler) WriterRedirect(ctx iris.Context) { raw, err := ctx.User().GetRaw() if err != nil { ctx.StopWithError(500, err) return } profile := raw.(map[string]string) email := profile["email"] token, err := w.RedisClient.GetKeyValue(email + "_token") if err != nil { ctx.StopWithError(500, err) return } client := &http.Client{} req, err := http.NewRequest(ctx.Request().Method, config.EnvVariables.BackendApi, ctx.Request().Body) if err != nil { ctx.StopWithError(500, err) return } req.Header.Add("Authorization", "Bearer "+token) req.Header.Add("Content-Type", "application/json") res, err := client.Do(req) if err != nil { ctx.StopWithError(500, err) return } defer res.Body.Close() body, err := io.ReadAll(res.Body) if err != nil { ctx.StopWithError(500, err) return } var respBody map[string]interface{} err = json.Unmarshal(body, &respBody) if err != nil { ctx.StopWithError(500, err) return } ctx.StopWithJSON(res.StatusCode, respBody) }
โปรดทราบว่า ctx.User().GetRaw() จะดึงข้อมูลโปรไฟล์ผู้ใช้ที่ตั้งค่าระหว่างมิดเดิลแวร์ ตัวจัดการ IsAuthenticated() ที่กำหนดไว้ด้านล่าง ด้วยความช่วยเหลือของอีเมลจาก ctx.User() ฉันได้รับโทเค็นจากแคช Redis และเพิ่มส่วนหัวการอนุญาต
มิดเดิลแวร์
มิดเดิลแวร์มีบทบาทสำคัญในการตรวจสอบความถูกต้องของคุกกี้ที่เข้ารหัสที่ส่งจากฟรอนต์เอนด์พร้อมกับคำขอ API และยังตรวจสอบว่าผู้ใช้เข้าสู่ระบบหรือไม่
- isAuhtenticated.go
type MiddlewareHandler struct { RedisClient interfaces.IRedisLayer } // IsAuthenticated is a middleware that checks if // the user has already been authenticated previously. func (m *MiddlewareHandler) IsAuthenticated(ctx iris.Context) { userCookie := ctx.GetCookie("logged_id_email") if userCookie == "" { ctx.StopWithError(iris.StatusUnauthorized, errors.New("please make sure user is logged in")) return } value, err := m.RedisClient.HGetKeyValue(userCookie + "_profile") if err != nil || value == nil { ctx.StopWithError(iris.StatusUnauthorized, errors.New("please make sure user is logged in")) return } ctx.SetUser(value) ctx.Next() }
ด้วยการใช้ ctx.SetUser() ข้อมูลโปรไฟล์ผู้ใช้จะถูกจัดเก็บไว้ในบริบทของ Iris ข้อมูลนี้จะสามารถเข้าถึงได้และสามารถใช้งานได้โดยตัวจัดการ API แบ็กเอนด์ในระหว่างการประมวลผลคำขอ
ตัวรับรองความถูกต้อง
Authenticator เริ่มต้นอินสแตนซ์ใหม่ของผู้ให้บริการ Oauth2
// Authenticator is used to authenticate our users. type Authenticator struct { *oidc.Provider oauth2.Config } // New instantiates the *Authenticator. func New() (*Authenticator, error) { provider, err := oidc.NewProvider( context.Background(), "https://"+config.EnvVariables.Auth0Domain+"/", ) if err != nil { return nil, err } conf := oauth2.Config{ ClientID: config.EnvVariables.Auth0ClientID, ClientSecret: config.EnvVariables.Auth0ClientSecret, RedirectURL: config.EnvVariables.Auth0CallbackURL, Endpoint: provider.Endpoint(), Scopes: []string{oidc.ScopeOpenID, "profile", "email"}, } return &Authenticator{ Provider: provider, Config: conf, }, nil } // VerifyIDToken verifies that an *oauth2.Token is a valid *oidc.IDToken. func (a *Authenticator) VerifyIDToken(ctx context.Context, token *oauth2.Token) (*oidc.IDToken, error) { rawIDToken, ok := token.Extra("id_token").(string) if !ok { return nil, errors.New("no id_token field in oauth2 token") } oidcConfig := &oidc.Config{ ClientID: a.ClientID, } return a.Verifier(oidcConfig).Verify(ctx, rawIDToken) }
จำเป็นอย่างยิ่งที่จะต้องตรวจสอบให้แน่ใจว่าตัวแปรสภาพแวดล้อมทั้งหมดของแอปพลิเคชัน Auth0 ได้รับการกำหนดค่าและตั้งค่าอย่างเหมาะสม ขั้นตอนนี้จำเป็นในการเริ่มต้นผู้ให้บริการ OAuth2 ได้สำเร็จ
เกี่ยวกับ โฟลว์
นี่คือสิ่งที่จะเกิดขึ้นเมื่อผู้ใช้ตรวจสอบสิทธิ์กับแอปพลิเคชัน:
- ผู้ใช้คลิกที่ปุ่มเข้าสู่ระบบบน UI ส่วนหน้า
- ส่วนหน้าเปลี่ยนเส้นทางผู้ใช้ไปยังปลายทาง /login ใน Backend for Frontend (BFF)
- BFF จะเปลี่ยนเส้นทางผู้ใช้ไปยังหน้าเข้าสู่ระบบสากลของ Auth0 เพิ่มเติม
- ผู้ใช้ให้ข้อมูลประจำตัวและความยินยอมต่อกระบวนการตรวจสอบสิทธิ์
- หลังจากการตรวจสอบสิทธิ์สำเร็จ คำขอโทรกลับจะถูกส่งกลับไปยังปลายทาง /callback ในแอปพลิเคชัน
- ตัวจัดการการเรียกกลับตรวจสอบพารามิเตอร์สถานะที่ได้รับ เพื่อให้มั่นใจในความสมบูรณ์และความปลอดภัย
- ตัวจัดการการเรียกกลับจะแลกเปลี่ยนรหัสอนุญาตที่ได้รับสำหรับโทเค็นการเข้าถึงผ่านช่องทางที่ปลอดภัย
- โทเค็นการเข้าถึงที่ได้รับได้รับการตรวจสอบแล้ว
- โทเค็นการเข้าถึงและข้อมูลโปรไฟล์ที่เกี่ยวข้องจะถูกแยกและแคชไว้ในเซิร์ฟเวอร์ Redis
- ตัวจัดการจะเปลี่ยนเส้นทางผู้ใช้กลับไปที่ UI ส่วนหน้า พร้อมด้วยคุกกี้ HTTP เท่านั้น
- เมื่อผู้ใช้ทำการเรียก API แบ็กเอนด์จากฟรอนต์เอนด์ในภายหลัง คุกกี้จะรวมอยู่ในคำขอ
- คุกกี้ได้รับการตรวจสอบโดยตัวจัดการมิดเดิลแวร์ ซึ่งจะตรวจสอบสถานะการเข้าสู่ระบบของผู้ใช้ และตรวจสอบความพร้อมใช้งานของข้อมูลโปรไฟล์ในแคช
- ตัวจัดการ API แบ็กเอนด์จัดการโฟลว์ แยกโทเค็นการเข้าถึง JWT ออกจากแคช และเพิ่มลงในส่วนหัวการอนุญาตของคำขอที่ส่งต่อ
- จากนั้นคำขอจะถูกส่งต่อไปยัง API แบ็กเอนด์
- เมื่อได้รับการตอบสนองจากส่วนหลัง ก็จะถูกส่งต่อกลับไปยังส่วนหน้า
บทสรุป
โดยสรุป รูปแบบการตรวจสอบสิทธิ์ Backend for Frontend (BFF) ใน Go มอบแนวทางที่มีประสิทธิภาพและยืดหยุ่นในการสร้างระบบการตรวจสอบสิทธิ์สำหรับแอปพลิเคชันส่วนหน้า ด้วยการแยกข้อกังวลในการรับรองความถูกต้องออกเป็นบริการแบ็คเอนด์เฉพาะที่ปรับให้เหมาะกับไคลเอนต์ส่วนหน้าแต่ละราย นักพัฒนาสามารถสร้างระบบการรับรองความถูกต้องที่แข็งแกร่ง ปรับขนาดได้ และปลอดภัย ซึ่งตรงตามข้อกำหนดเฉพาะของแอปพลิเคชันของตน
ฉันหวังว่าบล็อกเทคโนโลยีนี้จะให้ข้อมูลเชิงลึกอันมีค่าและคำแนะนำเชิงปฏิบัติสำหรับการใช้รูปแบบการตรวจสอบสิทธิ์ BFF ใน Go ขอให้สนุกกับการเขียนโค้ด!
ซอร์สโค้ดของตัวอย่างนี้มีอยู่ที่ mehulgohil/go-bffauth