일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
Tags
- 스마트 컨트렉트 함수이름 중복
- 스마트컨트렉트 예약어 함수이름 중복
- ambiguous function description
- ethers v6
- vue기초
- 컨트렉트 동일한 함수이름 호출
- cloud hsm
- 스마트컨트렉트 함수이름 중복 호출
- 티스토리챌린지
- cloud hsm 서명
- 러스트기초
- 계정추상화
- redux toolkit 설명
- erc4337
- cloud hsm 사용하기
- redux 기초
- ethers typescript
- ethers websocket
- 머신러닝기초
- rust 기초
- 체인의정석
- erc4337 contract
- Vue
- ethers type
- git rebase
- 러스트 기초
- 오블완
- Vue.js
- 러스트 기초 학습
- SBT표준
Archives
- Today
- Total
체인의정석
Go) JWT 발급 및 인증 로직 (백엔드) 본문
728x90
서명 로직 이후에 지갑 서명이 확인되면 해당 지갑의 role을 읽어와서 JWT를 발급해주는 구조
지갑 서명이라는 검증 로직이 있기 때문에 Refresh Token은 생략
*핵심 로직만 함수화 시켰으며, 함수명 및 변수들은 모두 임의로 지정
기능구현
JWT 발급 함수 (발급 해주고 리턴)
import (
"github.com/golang-jwt/jwt/v5"
"time"
)
func GenerateJWT(secret string, userID string, role string, issuer string) (string, error) {
claims := jwt.MapClaims{
"user_id": userID, // 사용자 식별자
"role": role, // 권한: "viewer", "editor", "admin"
"exp": time.Now().Add(24 * time.Hour).Unix(), // 만료 시간
"iat": time.Now().Unix(), // 발급 시간
"iss": issuer, // 발급자
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
return token.SignedString([]byte(secret))
}
JWT 검증함수 (JWT 받아와서 유효성 검증)
import (
"fmt"
"github.com/golang-jwt/jwt/v5"
)
func ParseJWT(tokenStr string, secret string) (jwt.MapClaims, error) {
token, err := jwt.Parse(tokenStr, func(t *jwt.Token) (interface{}, error) {
if _, ok := t.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("unexpected signing method")
}
return []byte(secret), nil
})
if err != nil {
return nil, err
}
if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
return claims, nil
}
return nil, fmt.Errorf("invalid token")
}
Role 기반으로 JWT를 받아와서 각각의 Role이 적합한지 판단해주는 미들웨어 (인증 함수를 사용하여 JWT에 기록된 정보별로 유효성을 판단해주는 역할) Router 경로에 middleware로 따로 분류
import (
"github.com/gin-gonic/gin"
"net/http"
"strings"
)
func AuthMiddleware(secret string, allowedRoles ...string) gin.HandlerFunc {
return func(c *gin.Context) {
authHeader := c.GetHeader("Authorization")
if !strings.HasPrefix(authHeader, "Bearer ") {
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Missing or invalid Authorization header"})
return
}
tokenStr := strings.TrimPrefix(authHeader, "Bearer ")
claims, err := ParseJWT(tokenStr, secret)
if err != nil {
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Invalid or expired token"})
return
}
role, ok := claims["role"].(string)
if !ok {
c.AbortWithStatusJSON(http.StatusForbidden, gin.H{"error": "Role not found in token"})
return
}
for _, r := range allowedRoles {
if role == r {
c.Set("userClaims", claims)
c.Next()
return
}
}
c.AbortWithStatusJSON(http.StatusForbidden, gin.H{"error": "Insufficient permissions"})
}
}
API 호출 시 JWT를 검사해야 하기 때문에 해당 부분은 다음과 같이 사용, API 호출 시 입력된 롤을 받아와서 해당 롤이 JWT의 롤이랑 일치하는지 체크한다. API 별로 권한 체계가 다 다르다면 이에 맞게 여기서 다 지정해주면 된다.
account.GET("get_something", AuthRoleMiddleware(p.config, "role1", "role2", "role3"), ExampleController.GetSomeThing)
Swagger 테스트
JWT인증을 받은 후의 API 처리의 경우 Swagger에서 테스트를 하려면 아래와 같이 주석을 추가해 주어야 한다.
main.go 또는 router.go 상단:
// @securityDefinitions.apikey BearerAuth
// @in header
// @name Authorization
각 API 주석에 추가:
// @Security BearerAuth
위의 작업이 완료되면 아래와 같이 Authorize가 뜨게 되는데
리턴받은 JWT토큰이 있다면 Authorize 버튼을 클릭하고 아래처럼 입력한다:
Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
※ JWT토큰 앞에 Bearer 를 붙여야 정상 작동한다.
728x90
반응형
'개발 > backend(go)' 카테고리의 다른 글
go 응답 값 타입 any처럼 유연하게 지정하기 interface 사용법 (0) | 2025.06.11 |
---|---|
Go Gin으로 API 만들기: POST/GET 기본 구조 + Swagger 작성법 (1) | 2025.04.25 |
Go 언어로 메타 마스크 로그인 로직, Signature 검증 (백엔드) (0) | 2025.04.09 |
MongoDB+Go 에서의 Cursor를 활용한 다중 데이터 조회 (select all) (0) | 2025.04.08 |
Go Swagger, 패키지 관리, hash 함수 (2) | 2025.04.08 |
Comments