Golang의 Echo에서 JWT

15512 단어 5JWT

Echo 준비



Docker에서 Golang 컨테이너를 사용합니다.
FROM golang:1.14.2-alpine3.11

WORKDIR /go/src

COPY ./src /go/src

ENV GOPATH ''

RUN apk update && apk add --no-cache git

docker-compose.yml
version: '3'
services:
  goecho:
    image: goecho
    build: .
    ports:
      - 8080:8080
    volumes:
      - ./src:/go/src
    tty: true
$ docker-compose up -d --build
$ docker-compose exec goecho go mod init src
$ docker-compose exec goecho go get github.com/labstack/echo/v4

src/main.go
package main

import (
  "net/http"
  "github.com/labstack/echo/v4"
  "github.com/labstack/echo/v4/middleware"
)

func main() {
  // Echo instance
  e := echo.New()

  // Middleware
  e.Use(middleware.Logger())
  e.Use(middleware.Recover())

  // Routes
  e.GET("/", hello)

  // Start server
  e.Logger.Fatal(e.Start(":8080"))
}

// Handler
func hello(c echo.Context) error {
  return c.String(http.StatusOK, "Hello, World!")
}
$ docker-compose exec goecho go run main.go



JWT 구현



JWT에 대한 설명은 생략합니다. 알고 싶은 분은 이하의 링크처를.

Echo에서 JWT 인증을 구현합니다. 글쎄 쿠북거리지만. .


src/main.go
package main

import (
  "net/http"
  "time"
  "github.com/dgrijalva/jwt-go"
  "github.com/labstack/echo/v4"
  "github.com/labstack/echo/v4/middleware"
)

func login(c echo.Context) error {
  username := c.FormValue("username")
  password := c.FormValue("password")

  // とりあえずのパスワード認証
  if username != "taro" || password != "shhh!" {
    return echo.ErrUnauthorized
  }

  // トークン作成
  token := jwt.New(jwt.SigningMethodHS256)

  claims := token.Claims.(jwt.MapClaims)
  claims["name"] = "Taro"
  claims["admin"] = true
  claims["exp"] = time.Now().Add(time.Hour * 24).Unix()

  t, err := token.SignedString([]byte("secret"))
  if err != nil {
    return err
  }

  return c.JSON(http.StatusOK, map[string]string{
    "token": t,
  })
}

func accessible(c echo.Context) error {
  return c.String(http.StatusOK, "Accessible")
}

func restricted(c echo.Context) error {
  user := c.Get("user").(*jwt.Token)
  claims := user.Claims.(jwt.MapClaims)
  name := claims["name"].(string)
  return c.String(http.StatusOK, "Welcome "+name+"!")
}

func main() {
  e := echo.New()

  e.Use(middleware.Logger())
  e.Use(middleware.Recover())

  // Login route
  e.POST("/login", login)

  // Unauthenticated route
  e.GET("/", accessible)

  // Restricted group
  r := e.Group("/restricted")
  r.Use(middleware.JWT([]byte("secret")))
  r.GET("", restricted)

  e.Logger.Fatal(e.Start(":8080"))
}

JWT 인증이 필요하지 않은 URL은 액세스할 수 있습니다.
$ curl localhost:8080
Accessiblesrc

JWT 인증이 필요한 URL에는 토큰이 필요합니다.
$ curl localhost:8080/restricted
{"message":"missing or malformed jwt"}

토큰을 가져옵니다.
$ curl -X POST -d 'username=taro' -d 'password=hoge' localhost:8080/login
{"message":"Unauthorized"}
$ curl -X POST -d 'username=taro' -d 'password=shhh!' localhost:8080/login
{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhZG1pbiI6dHJ1ZSwiZXhwIjoxNTg3NjI4NjI0LCJuYW1lIjoiVGFybyJ9.5mqtxA0XiNcslwC22n7gNL97KPl6zYdt6AhpF9PkIKk"}

획득한 토큰으로 인증할 수 있는지 확인합니다.
$ curl localhost:8080/restricted  -H "Authorization: Bearer hoge"
{"message":"invalid or expired jwt"}
$ curl localhost:8080/restricted  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhZG1pbiI6dHJ1ZSwiZXhwIjoxNTg3NjI4NjI0LCJuYW1lIjoiVGFybyJ9.5mqtxA0XiNcslwC22n7gNL97KPl6zYdt6AhpF9PkIKk"
Welcome Taro!

성공했습니다.
이제 상태 비저장 인증이 가능하네요

좋은 웹페이지 즐겨찾기