
TL; DR: Ebben az oktatóanyagban megmutatom, mennyire egyszerű webalkalmazást építeni a Go és a Gin keretrendszerrel, és hozzáadni hitelesítést. Nézze meg a Github repóban a kódot, amelyet írni fogunk.
A Gin egy nagy teljesítményű mikrokeret. Nagyon minimalista keretrendszert nyújt, amely csak a webalkalmazások és a mikroszolgáltatások létrehozásához szükséges legfontosabb funkciókat, könyvtárakat és funkciókat tartalmazza. Ez megkönnyíti a kérelemkezelő csővezeték megépítését moduláris, újrafelhasználható darabokból. Ezt úgy teszi meg, hogy lehetővé teszi olyan köztes szoftverek írását, amelyek csatlakoztathatók egy vagy több kérelemkezelőhöz vagy kéréskezelők csoportjához.
Gin funkciók
A Gin egy gyors, egyszerű, mégis teljes körű szolgáltatásokat kínáló és nagyon hatékony webes keretrendszer a Go számára. Nézze meg az alábbi funkciókat, amelyek méltó keretet jelentenek a következő Golang-projekt szempontjából.
- Sebesség: A gint a sebesség érdekében építik. A keretrendszer Radix fa alapú útválasztást és kicsi memóriaterületet kínál. Nincs reflexió. Kiszámítható API teljesítmény.
- Összeomlásmentes : Gin képes lefutni összeomlásokat vagy pánikokat futás közben, és felépülhet ezekből. Így az alkalmazás mindig elérhető lesz.
- Útválasztás: A Gin egy útválasztási felületet biztosít, amely lehetővé teszi, hogy kifejezze, hogyan kell kinéznie a webalkalmazás vagy az API útvonalainak.
- JSON érvényesítés: A Gin könnyen elemezheti és érvényesítheti a JSON kéréseket, ellenőrizve a szükséges értékek meglétét.
- Hibakezelés: A Gin kényelmes módot kínál a HTTP-kérés során fellépő összes hiba összegyűjtésére. Végül egy köztes szoftver beírhatja őket egy naplófájlba vagy egy adatbázisba, és elküldheti a hálózaton keresztül.
- Beépített megjelenítés: A Gin könnyen használható API-t biztosít a JSON, XML és HTML megjelenítéshez.
Előfeltételek
Az oktatóanyag követéséhez telepítenie kell a Go szoftvert a számítógépére, egy webböngészőt az alkalmazás megtekintéséhez és egy parancssort a build parancsok végrehajtásához.
A Go vagy más néven a Golang egy programozási nyelv, amelyet a Google fejlesztett ki a modern szoftverek építésére. A Go egy olyan nyelv, amelynek célja a dolgok hatékony és gyors elvégzése. A Go legfontosabb előnyei a következők:
- Erősen gépelt és szemetet gyűjtöttek
- Lángoló gyors fordítási idők
- Beépített párhuzamosság
- Kiterjedt standard könyvtár
Lépjen a Go webhely letöltések szakaszába, hogy elindulhasson a Go számítógépén.
Alkalmazás építése Ginnel
Egy egyszerű vicclistázó alkalmazást építünk Ginnel . Az alkalmazásunk felsorol néhány buta apa viccet. Hozzá fogjuk adni a hitelesítést, hogy minden bejelentkezett felhasználó kiváltságot élvezhessen a poénok kedvelésére és megtekintésére.
Ez lehetővé teszi számunkra, hogy bemutassuk, hogyan használható a Gin webalkalmazások és / vagy API-k fejlesztésére.

A Gin által kínált következő funkciókat fogjuk használni:
- Középprogram
- útvonalválasztás
- Útvonalak csoportosítása
Vigyázz, kész, rajt
A teljes Go alkalmazásunkat main.go
fájlba fogjuk írni . Mivel ez egy kicsi alkalmazás, egyszerű lesz az alkalmazás építése go run
a terminálról.
Létrehozunk egy új könyvtárat golang-gin
a Go munkaterületünkön, majd egy main.go
fájlt benne:
$ mkdir -p $GOPATH/src/github.com/user/golang-gin $ cd $GOPATH/src/github.com/user/golang-gin $ touch main.go
A main.go
fájl tartalma:
package main import ( "net/http" "github.com/gin-gonic/contrib/static" "github.com/gin-gonic/gin" ) func main() { // Set the router as the default one shipped with Gin router := gin.Default() // Serve frontend static files router.Use(static.Serve("/", static.LocalFile("./views", true))) // Setup route group for the API api := router.Group("/api") { api.GET("/", func(c *gin.Context) { c.JSON(http.StatusOK, gin.H { "message": "pong", }) }) } // Start and run the server router.Run(":3000") }
Hozzon létre még néhány könyvtárat a statikus fájljainkhoz. main.go
Hozzunk létre egy views
mappát a fájllal azonos könyvtárban . A views
mappában hozzon létre egy js
mappát, és egy index.html
fájl sem.
A index.html
fájl egyelőre nagyon egyszerű lesz:
Jokeish App Welcome to the Jokeish App
Mielőtt tesztelnénk az eddigieket, telepítsük a hozzáadott függőségeket:
$ go get -u github.com/gin-gonic/gin $ go get -u github.com/gin-gonic/contrib/static
Ahhoz, hogy lássuk, mi működik, futtatással kell elindítanunk a szerverünket go run main.go
.

Miután az alkalmazás fut, navigáljon //localhost:3000
a böngészőben. Ha minden jól megy, akkor az 1. szintű fejléc Üdvözöljük a Jokeish App jelenik meg.

Az API meghatározása
Vegyünk fel még néhány kódot main.go
a fájlunkba az API meghatározásainkhoz. Frissítjük main
funkciónkat két útvonallal /jokes/
és /jokes/like/:jokeID
az útvonalcsoportra /api/
.
func main() { // ... leave the code above untouched... // Our API will consit of just two routes // /jokes - which will retrieve a list of jokes a user can see // /jokes/like/:jokeID - which will capture likes sent to a particular joke api.GET("/jokes", JokeHandler) api.POST("/jokes/like/:jokeID", LikeJoke) } // JokeHandler retrieves a list of available jokes func JokeHandler(c *gin.Context) { c.Header("Content-Type", "application/json") c.JSON(http.StatusOK, gin.H { "message":"Jokes handler not implemented yet", }) } // LikeJoke increments the likes of a particular joke Item func LikeJoke(c *gin.Context) { c.Header("Content-Type", "application/json") c.JSON(http.StatusOK, gin.H { "message":"LikeJoke handler not implemented yet", }) }
A main.go
fájl tartalmának így kell kinéznie:
package main import ( "net/http" "github.com/gin-gonic/contrib/static" "github.com/gin-gonic/gin" ) func main() { // Set the router as the default one shipped with Gin router := gin.Default() // Serve frontend static files router.Use(static.Serve("/", static.LocalFile("./views", true))) // Setup route group for the API api := router.Group("/api") { api.GET("/", func(c *gin.Context) { c.JSON(http.StatusOK, gin.H { "message": "pong", }) }) } // Our API will consit of just two routes // /jokes - which will retrieve a list of jokes a user can see // /jokes/like/:jokeID - which will capture likes sent to a particular joke api.GET("/jokes", JokeHandler) api.POST("/jokes/like/:jokeID", LikeJoke) // Start and run the server router.Run(":3000") } // JokeHandler retrieves a list of available jokes func JokeHandler(c *gin.Context) { c.Header("Content-Type", "application/json") c.JSON(http.StatusOK, gin.H { "message":"Jokes handler not implemented yet", }) } // LikeJoke increments the likes of a particular joke Item func LikeJoke(c *gin.Context) { c.Header("Content-Type", "application/json") c.JSON(http.StatusOK, gin.H { "message":"LikeJoke handler not implemented yet", }) }
Futtassuk újra az alkalmazást go run main.go
, és érjük el az útjainkat. fejléc választ ad //localhost:3000/api/jokes
vissza 200 OK
az üzenettel jokes handler not implemented yet
. A POST kérés //localhost:3000/api/jokes/like/1
a 200 OK
fejléc és az üzenet visszaadására szolgál Likejoke handler not implemented yet
.
Viccek adatai
Mivel már megvan az útvonalmeghatározásunk, amely csak egy dolgot hajt végre (visszaküldi a JSON-választ), egy kicsit megspékeljük kódbázisunkat azzal, hogy adunk hozzá még néhány kódot.
// ... leave the code above untouched... // Let's create our Jokes struct. This will contain information about a Joke // Joke contains information about a single Joke type Joke struct { ID int `json:"id" binding:"required"` Likes int `json:"likes"` Joke string `json:"joke" binding:"required"` } // We'll create a list of jokes var jokes = []Joke{ Joke{1, 0, "Did you hear about the restaurant on the moon? Great food, no atmosphere."}, Joke{2, 0, "What do you call a fake noodle? An Impasta."}, Joke{3, 0, "How many apples grow on a tree? All of them."}, Joke{4, 0, "Want to hear a joke about paper? Nevermind it's tearable."}, Joke{5, 0, "I just watched a program about beavers. It was the best dam program I've ever seen."}, Joke{6, 0, "Why did the coffee file a police report? It got mugged."}, Joke{7, 0, "How does a penguin build it's house? Igloos it together."}, } func main() { // ... leave this block untouched... } // JokeHandler retrieves a list of available jokes func JokeHandler(c *gin.Context) { c.Header("Content-Type", "application/json") c.JSON(http.StatusOK, jokes) } // LikeJoke increments the likes of a particular joke Item func LikeJoke(c *gin.Context) { // confirm Joke ID sent is valid // remember to import the `strconv` package if jokeid, err := strconv.Atoi(c.Param("jokeID")); err == nil { // find joke, and increment likes for i := 0; i < len(jokes); i++ { if jokes[i].ID == jokeid { jokes[i].Likes += 1 } } // return a pointer to the updated jokes list c.JSON(http.StatusOK, &jokes) } else { // Joke ID is invalid c.AbortWithStatus(http.StatusNotFound) } } // NB: Replace the JokeHandler and LikeJoke functions in the previous version to the ones above
Ha a kódunk jól néz ki, folytassuk és teszteljük az API-t. Tesztelhetünk a cURL
vagy gombbal postman
, majd küldhetünk egy GET
kérést //localhost:3000/jokes
a viccek teljes listájának megszerzéséhez, és egy POST
kérést a poénok //localhost:3000/jokes/like/{jokeid}
kedveléseinek növelésére.
$ curl //localhost:3000/api/jokes $ curl -X POST //localhost:3000/api/jokes/like/4
A felhasználói felület felépítése (React)
Megvan az API-nk, ezért készítsünk egy kezelőfelületet, amely bemutatja az API-junkból származó adatokat. Ehhez a React-et fogjuk használni. Nem fogunk túl mélyrehatóan belemenni a React-be, mivel az az oktatóanyag körén kívül esik. Ha többet szeretne megtudni a React-ról, nézze meg a hivatalos oktatóanyagot. A kezelőfelületet bármely olyan frontend keretrendszerrel implementálhatja, amelyiknek Önnek megfelelő.
Beállít
Szerkesztjük a index.html
fájlt, hogy hozzáadjuk a React futtatásához szükséges külső könyvtárakat. Ezután létre kell hoznunk egy app.jsx
fájlt a views/js
könyvtárban, amely tartalmazza a React kódunkat.
A index.html
fájlunknak így kell kinéznie:
Jokeish App
Összetevőink építése
A React-ben a nézetek komponensekre vannak bontva. Ki kell építenünk néhány összetevőt:
- egy
App
komponens, mint fő bejegyzés, amely elindítja az alkalmazást - egy olyan
Home
komponens, amely nem bejelentkezett felhasználókkal néz szembe - olyan
LoggedIn
alkatrész, amelynek tartalmát csak hitelesített felhasználók láthatják - és egy
Joke
komponens a viccek listájának megjelenítésére.
Mindezeket az összetevőket beírjuk a app.jsx
fájlba.
Az alkalmazás összetevője
Ez az összetevő indítja a teljes React alkalmazást. Az alapján dönt, hogy melyik összetevőt jelenítse meg, annak alapján, hogy a felhasználó hitelesített-e vagy sem. Csak az alapját kezdjük, majd később több funkcióval frissítjük.
class App extends React.Component { render() { if (this.loggedIn) { return (); } else { return (); } } }
A Home komponens
Ez az összetevő a nem bejelentkezett felhasználók számára jelenik meg, valamint egy gomb, amely megnyitja a Tárolt zárolási képernyőt, ahol regisztrálhatnak vagy bejelentkezhetnek. Később hozzáadjuk ezt a funkciót.
class Home extends React.Component { render() { return ( Jokeish
A load of Dad jokes XD
Sign in to get access
Sign In ) } }
LoggedIn komponens
Ez az összetevő akkor jelenik meg, amikor a felhasználó hitelesítésre kerül. A state
viccek tömbjében tárolja, amelyet az alkatrész felszerelésekor töltenek be.
class LoggedIn extends React.Component { constructor(props) { super(props); this.state = { jokes: [] } } render() { return (Log out
Jokeish
Let's feed you with some funny Jokes!!!
{this.state.jokes.map(function(joke, i){ return (); })} ) } }
A Joke komponens
Az Joke
összetevő információkat tartalmaz a megjelenítendő viccek válaszának minden eleméről.
class Joke extends React.Component { constructor(props) { super(props); this.state = { liked: "" } this.like = this.like.bind(this); } like() { // ... we'll add this block later } render() { return ( #{this.props.joke.id} {this.state.liked} {this.props.joke.joke} {this.props.joke.likes} Likes ) } }
Összeírtuk komponenseinket, ezért most mondjuk meg a Reactnek, hol kell megjeleníteni az alkalmazást. Az alábbi kódblokkot hozzáadjuk a app.jsx
fájlunk aljához .
ReactDOM.render(, document.getElementById('app'));
Indítsuk újra a Go szervert go run main.go
, és térjünk át alkalmazásunk URL-jére //localhost:3000/
. Látni fogja, hogy az Home
alkatrész megjelenik.

Viccjeink alkalmazásának biztosítása az Auth0 segítségével
Az Auth0 minden bejelentkezéskor kiadja a JSON web tokent a felhasználók számára. Ez azt jelenti, hogy szilárd identitás-infrastruktúrával rendelkezhet, beleértve az egyszeri bejelentkezést, a felhasználói kezelést, a közösségi identitás-szolgáltatók (Facebook, Github, Twitter stb.), A vállalati identitás-szolgáltatók (Active Directory, LDAP, SAML stb.) Támogatását. és saját felhasználói adatbázisa, csak néhány soros kóddal.
Könnyedén beállíthatjuk a hitelesítést a GIN alkalmazásunkban az Auth0 használatával. A rész követéséhez szükséged lesz egy fiókra. Ha még nincs Auth0-fiókja, regisztráljon most.
Jogi nyilatkozat: Ez nem szponzorált tartalom.Az API kliens létrehozása
Jelzőinket az Auth0 segítségével generáljuk, ezért az Auth0 irányítópultunkról létre kell hoznunk egy API-t és egy klienst. Ismét, ha még nem tette meg, regisztráljon Auth0 fiókot.
Új API létrehozásához lépjen az irányítópult API-k szakaszába, és kattintson az API létrehozása gombra.

Válasszon egy API nevet és egy azonosítót . Az azonosító lesz a köztes szoftver közönsége . Az aláíró algoritmusnak RS256- nak kell lennie .
Új kliens létrehozásához keresse meg az irányítópult kliensek szakaszát, majd kattintson az Ügyfél létrehozása gombra. Válassza ki a típust Regular Web Applications
.

Az ügyfél létrehozása után vegye tudomásul a client_id
és client_secret
, amire később szükségünk lesz.

Hozzá kell adnunk az API-nál szükséges hitelesítő adatokat egy környezeti változóhoz. Hozzon létre egy új fájlt a gyökérkönyvtárban, .env
és adja hozzá a következőket az Auth0 irányítópult részleteivel:
export export export AUTH0_DOMAIN="yourdomain.auth0.com" export
API-végpontjaink biztonsága
Jelenleg az API-nk nyitva áll a világ előtt. Biztosítanunk kell a végpontjainkat, így csak az arra jogosult felhasználók férhetnek hozzá.
Egy JWT köztes szoftvert fogunk használni, hogy ellenőrizzük a JSON Web Token érvényes érvényesítését minden egyes kérésből, amely eléri a végpontjainkat.
Készítsük el a köztes szoftvert:
// ... var jwtMiddleWare *jwtmiddleware.JWTMiddleware func main() { jwtMiddleware := jwtmiddleware.New(jwtmiddleware.Options{ ValidationKeyGetter: func(token *jwt.Token) (interface{}, error) { aud := os.Getenv("AUTH0_API_AUDIENCE") checkAudience := token.Claims.(jwt.MapClaims).VerifyAudience(aud, false) if !checkAudience { return token, errors.New("Invalid audience.") } // verify iss claim iss := os.Getenv("AUTH0_DOMAIN") checkIss := token.Claims.(jwt.MapClaims).VerifyIssuer(iss, false) if !checkIss { return token, errors.New("Invalid issuer.") } cert, err := getPemCert(token) if err != nil { log.Fatalf("could not get cert: %+v", err) } result, _ := jwt.ParseRSAPublicKeyFromPEM([]byte(cert)) return result, nil }, SigningMethod: jwt.SigningMethodRS256, }) // register our actual jwtMiddleware jwtMiddleWare = jwtMiddleware // ... the rest of the code below this function doesn't change yet } // authMiddleware intercepts the requests, and check for a valid jwt token func authMiddleware() gin.HandlerFunc { return func(c *gin.Context) { // Get the client secret key err := jwtMiddleWare.CheckJWT(c.Writer, c.Request) if err != nil { // Token not found fmt.Println(err) c.Abort() c.Writer.WriteHeader(http.StatusUnauthorized) c.Writer.Write([]byte("Unauthorized")) return } } }
A fenti kódban van egy új jwtMiddleWare
változó, amelyet a main
függvény inicializál . A authMiddleware
középső funkcióban használják.
Ha észreveszi, a kiszolgálóoldali hitelesítő adatainkat egy környezeti változóból (egy 12-faktoros alkalmazás egyik tétele közül) vesszük . Középprogramunk ellenőrzi és kap egy tokent egy kérésből, és meghívja a jwtMiddleWare.CheckJWT
módszert az elküldött token érvényesítésére.
Írjuk meg a függvényt is a JSON webkulcsok visszaadásához:
// ... the code above is untouched... // Jwks stores a slice of JSON Web Keys type Jwks struct { Keys []JSONWebKeys `json:"keys"` } type JSONWebKeys struct { Kty string `json:"kty"` Kid string `json:"kid"` Use string `json:"use"` N string `json:"n"` E string `json:"e"` X5c []string `json:"x5c"` } func main() { // ... the code in this method is untouched... } func getPemCert(token *jwt.Token) (string, error) { cert := "" resp, err := http.Get(os.Getenv("AUTH0_DOMAIN") + ".well-known/jwks.json") if err != nil { return cert, err } defer resp.Body.Close() var jwks = Jwks{} err = json.NewDecoder(resp.Body).Decode(&jwks) if err != nil { return cert, err } x5c := jwks.Keys[0].X5c for k, v := range x5c { if token.Header["kid"] == jwks.Keys[k].Kid { cert = "-----BEGIN CERTIFICATE-----\n" + v + "\n-----END CERTIFICATE-----" } } if cert == "" { return cert, errors.New("unable to find appropriate key.") } return cert, nil }
A JWT köztes szoftver használata
A köztes szoftver használata nagyon egyszerű. Csak átadjuk paraméterként az útvonalak meghatározásához.
... api.GET("/jokes", authMiddleware(), JokeHandler) api.POST("/jokes/like/:jokeID", authMiddleware(), LikeJoke) ...
A main.go
fájlunknak így kell kinéznie:
package main import ( "encoding/json" "errors" "fmt" "log" "net/http" "os" "strconv" jwtmiddleware "github.com/auth0/go-jwt-middleware" jwt "github.com/dgrijalva/jwt-go" "github.com/gin-gonic/contrib/static" "github.com/gin-gonic/gin" ) type Response struct { Message string `json:"message"` } type Jwks struct { Keys []JSONWebKeys `json:"keys"` } type JSONWebKeys struct { Kty string `json:"kty"` Kid string `json:"kid"` Use string `json:"use"` N string `json:"n"` E string `json:"e"` X5c []string `json:"x5c"` } type Joke struct { ID int `json:"id" binding:"required"` Likes int `json:"likes"` Joke string `json:"joke" binding:"required"` } /** we'll create a list of jokes */ var jokes = []Joke{ Joke{1, 0, "Did you hear about the restaurant on the moon? Great food, no atmosphere."}, Joke{2, 0, "What do you call a fake noodle? An Impasta."}, Joke{3, 0, "How many apples grow on a tree? All of them."}, Joke{4, 0, "Want to hear a joke about paper? Nevermind it's tearable."}, Joke{5, 0, "I just watched a program about beavers. It was the best dam program I've ever seen."}, Joke{6, 0, "Why did the coffee file a police report? It got mugged."}, Joke{7, 0, "How does a penguin build it's house? Igloos it together."}, } var jwtMiddleWare *jwtmiddleware.JWTMiddleware func main() { jwtMiddleware := jwtmiddleware.New(jwtmiddleware.Options{ ValidationKeyGetter: func(token *jwt.Token) (interface{}, error) { aud := os.Getenv("AUTH0_API_AUDIENCE") checkAudience := token.Claims.(jwt.MapClaims).VerifyAudience(aud, false) if !checkAudience { return token, errors.New("Invalid audience.") } // verify iss claim iss := os.Getenv("AUTH0_DOMAIN") checkIss := token.Claims.(jwt.MapClaims).VerifyIssuer(iss, false) if !checkIss { return token, errors.New("Invalid issuer.") } cert, err := getPemCert(token) if err != nil { log.Fatalf("could not get cert: %+v", err) } result, _ := jwt.ParseRSAPublicKeyFromPEM([]byte(cert)) return result, nil }, SigningMethod: jwt.SigningMethodRS256, }) jwtMiddleWare = jwtMiddleware // Set the router as the default one shipped with Gin router := gin.Default() // Serve the frontend router.Use(static.Serve("/", static.LocalFile("./views", true))) api := router.Group("/api") { api.GET("/", func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "message": "pong", }) }) api.GET("/jokes", authMiddleware(), JokeHandler) api.POST("/jokes/like/:jokeID", authMiddleware(), LikeJoke) } // Start the app router.Run(":3000") } func getPemCert(token *jwt.Token) (string, error) { cert := "" resp, err := http.Get(os.Getenv("AUTH0_DOMAIN") + ".well-known/jwks.json") if err != nil { return cert, err } defer resp.Body.Close() var jwks = Jwks{} err = json.NewDecoder(resp.Body).Decode(&jwks) if err != nil { return cert, err } x5c := jwks.Keys[0].X5c for k, v := range x5c { if token.Header["kid"] == jwks.Keys[k].Kid { cert = "-----BEGIN CERTIFICATE-----\n" + v + "\n-----END CERTIFICATE-----" } } if cert == "" { return cert, errors.New("unable to find appropriate key") } return cert, nil } // authMiddleware intercepts the requests, and check for a valid jwt token func authMiddleware() gin.HandlerFunc { return func(c *gin.Context) { // Get the client secret key err := jwtMiddleWare.CheckJWT(c.Writer, c.Request) if err != nil { // Token not found fmt.Println(err) c.Abort() c.Writer.WriteHeader(http.StatusUnauthorized) c.Writer.Write([]byte("Unauthorized")) return } } } // JokeHandler returns a list of jokes available (in memory) func JokeHandler(c *gin.Context) { c.Header("Content-Type", "application/json") c.JSON(http.StatusOK, jokes) } func LikeJoke(c *gin.Context) { // Check joke ID is valid if jokeid, err := strconv.Atoi(c.Param("jokeID")); err == nil { // find joke and increment likes for i := 0; i < len(jokes); i++ { if jokes[i].ID == jokeid { jokes[i].Likes = jokes[i].Likes + 1 } } c.JSON(http.StatusOK, &jokes) } else { // the jokes ID is invalid c.AbortWithStatus(http.StatusNotFound) } }
Telepítsük a jwtmiddleware
könyvtárakat:
$ go get -u github.com/auth0/go-jwt-middleware $ go get -u github.com/dgrijalva/jwt-go
Forrjuk meg a környezeti fájlt, és indítsuk újra az alkalmazásszerverünket:
$ source .env $ go run main.go
Ha megpróbálunk elérni bármelyik végpontot, akkor 401 Unauthorized
hibával szembesülünk . Ez azért van, mert a tokennel együtt el kell küldenünk egy kérelmet.
Bejelentkezés az Auth0 és a React
Vezessünk be egy bejelentkezési rendszert, hogy a felhasználók bejelentkezhessenek vagy fiókokat hozzanak létre, és hozzáférhessenek vicceinkhez. app.jsx
Fájlunkhoz hozzáadjuk a következő Auth0 hitelesítő adatokat:
AUTH0_CLIENT_ID
AUTH0_DOMAIN
AUTH0_CALLBACK_URL
- Az alkalmazásod URL-jeAUTH0_API_AUDIENCE
AUTH0_CLIENT_ID
, AUTH0_DOMAIN
és AUTH0_API_AUDIENCE
az adatokat a Auth0 menedzsment műszerfalon.
Be kell állítanunk egy, callback
amelyre az Auth0 átirányít. Navigáljon az irányítópult Ügyfelek szakaszához. A beállításokban állítsuk a visszahívást //localhost:3000
:

A hitelesítő adatokkal frissítsük a React összetevőket.
APP komponens
const AUTH0_CLIENT_ID = "aIAOt9fkMZKrNsSsFqbKj5KTI0ObTDPP"; const AUTH0_DOMAIN = "hakaselabs.auth0.com"; const AUTH0_CALLBACK_URL = location.href; const AUTH0_API_AUDIENCE = "golang-gin"; class App extends React.Component { parseHash() { this.auth0 = new auth0.WebAuth({ domain: AUTH0_DOMAIN, clientID: AUTH0_CLIENT_ID }); this.auth0.parseHash(window.location.hash, (err, authResult) => { if (err) { return console.log(err); } if ( authResult !== null && authResult.accessToken !== null && authResult.idToken !== null ) { localStorage.setItem("access_token", authResult.accessToken); localStorage.setItem("id_token", authResult.idToken); localStorage.setItem( "profile", JSON.stringify(authResult.idTokenPayload) ); window.location = window.location.href.substr( 0, window.location.href.indexOf("#") ); } }); } setup() { $.ajaxSetup({ beforeSend: (r) => { if (localStorage.getItem("access_token")) { r.setRequestHeader( "Authorization", "Bearer " + localStorage.getItem("access_token") ); } } }); } setState() { let idToken = localStorage.getItem("id_token"); if (idToken) { this.loggedIn = true; } else { this.loggedIn = false; } } componentWillMount() { this.setup(); this.parseHash(); this.setState(); } render() { if (this.loggedIn) { return ; } return ; } }
Frissítettük az App komponens három komponens módszerekkel ( setup
, parseHash
és setState
), és az életciklus módszer componentWillMount
. A parseHash
módszer inicializálja az auth0
webAuth
ügyfelet, és a kivonatot olvashatóbb formátumba elemzi, elmentve őket a localSt-be. A zárolási képernyő megjelenítéséhez rögzítse és tárolja a felhasználói tokent, és adja hozzá a helyes hitelesítési fejlécet az API kéréseinkhez
Otthoni alkatrész
A Home komponensünk frissül. Hozzáadjuk a authenticate
módszer funkcionalitását , amely elindítja a hosztolt zárképernyő megjelenítését, és lehetővé teszi felhasználóink számára a bejelentkezést vagy a regisztrációt.
class Home extends React.Component { constructor(props) { super(props); this.authenticate = this.authenticate.bind(this); } authenticate() { this.WebAuth = new auth0.WebAuth({ domain: AUTH0_DOMAIN, clientID: AUTH0_CLIENT_ID, scope: "openid profile", audience: AUTH0_API_AUDIENCE, responseType: "token id_token", redirectUri: AUTH0_CALLBACK_URL }); this.WebAuth.authorize(); } render() { return ( Jokeish
A load of Dad jokes XD
Sign in to get access
Sign In ); } }
LoggedIn komponens
Frissítjük az LoggedIn
összetevőt, hogy kommunikálhassunk az API-val, és minden viccet behúzunk. Minden viccet átad a- prop
nak az Joke
összetevőnek, amely rendszertöltő panelt jelenít meg. Írjuk ezeket:
class LoggedIn extends React.Component { constructor(props) { super(props); this.state = { jokes: [] }; this.serverRequest = this.serverRequest.bind(this); this.logout = this.logout.bind(this); } logout() { localStorage.removeItem("id_token"); localStorage.removeItem("access_token"); localStorage.removeItem("profile"); location.reload(); } serverRequest() { $.get("//localhost:3000/api/jokes", res => { this.setState({ jokes: res }); }); } componentDidMount() { this.serverRequest(); } render() { return (Log out
Jokeish
Let's feed you with some funny Jokes!!!
{this.state.jokes.map(function(joke, i) { return ; })} ); } }
Vicc komponens
Frissítjük az Joke
összetevőt úgy is, hogy megformázzuk a Szülő-összetevőtől ( LoggedIn
) átadott minden viccelemet . Hozzáadunk egy like
módszert is, amely növeli a viccek tetszését.
class Joke extends React.Component { constructor(props) { super(props); this.state = { liked: "", jokes: [] }; this.like = this.like.bind(this); this.serverRequest = this.serverRequest.bind(this); } like() { let joke = this.props.joke; this.serverRequest(joke); } serverRequest(joke) { $.post( "//localhost:3000/api/jokes/like/" + joke.id, { like: 1 }, res => { console.log("res... ", res); this.setState({ liked: "Liked!", jokes: res }); this.props.jokes = res; } ); } render() { return ( #{this.props.joke.id}{" "} {this.state.liked} {this.props.joke.joke} {this.props.joke.likes} Likes ) } }
Összedobva az egészet
Az UI és az API elkészültével tesztelhetjük az alkalmazásunkat. Először a szerver indításával source .env && go run main.go
indulunk, majd //localhost:3000
bármelyik böngészőből navigálunk. Látnia kell az Home
összetevőt egy bejelentkezési gombbal. A bejelentkezés gombra kattintva átirányít egy hosztolt zár oldalra (hozzon létre fiókot vagy bejelentkezési adatot) az alkalmazás folytatásához.
Itthon:

Auth0 tárolt zárolási képernyő:

Bejelentkezett alkalmazás nézetben:

Következtetés
Gratula! Megtanulta, hogyan kell egy alkalmazást és egy API-t felépíteni a Go és a Gin keretrendszerrel.
Hiányzott valami fontos dolog? Tudassa velem a kommentekben.
Sziasztok nekem a Twitteren @codehakase