瀏覽代碼

token parser

0x4a52466c696e74 2 月之前
父節點
當前提交
5b1b73b5ba
共有 6 個文件被更改,包括 35 次插入226 次删除
  1. 8 0
      request.go
  2. 3 16
      rest_http/rest.go
  3. 1 0
      rest_websocket/app_config.go
  4. 4 0
      rest_websocket/request.go
  5. 0 210
      rest_websocket/socket.goo
  6. 19 0
      server.go

+ 8 - 0
request.go

@@ -13,6 +13,8 @@ type (
 	RequestFiles map[string]IReadCloserLen
 	// TokenGenerateMethod - функция генерации токена авторизации
 	TokenGenerateMethod func(data json.Map, expire int64) (string, error)
+	// TokenParseMethod - функция для расшифровки токена
+	TokenParseMethod func(token string) (json.Map, error)
 )
 
 const (
@@ -90,6 +92,7 @@ type IRequestIn interface {
 	Auth() json.Map
 	SetAuth(json.Map)
 	GenerateToken(data json.Map, expire int64) (string, error)
+	ParseToken(token string) (json.Map, error)
 	ROwner() IOwner
 	RCore() any
 	OutSuccess(data json.Map, files RequestFiles) IRequestOut
@@ -103,6 +106,7 @@ type RequestIn struct {
 	Owner          IOwner
 	Core           any
 	GeneratorToken TokenGenerateMethod
+	ParserToken    TokenParseMethod
 }
 
 func (s *RequestIn) Auth() json.Map {
@@ -122,6 +126,10 @@ func (s *RequestIn) GenerateToken(data json.Map, expire int64) (string, error) {
 	return s.GeneratorToken(data, expire)
 }
 
+func (s *RequestIn) ParseToken(token string) (json.Map, error) {
+	return s.ParserToken(token)
+}
+
 func (s *RequestIn) ClientData(key string) (any, bool) {
 	if store, check := s.Owner.(IStream); check {
 		return store.ClientData(key)

+ 3 - 16
rest_http/rest.go

@@ -3,14 +3,12 @@ package rest_http
 import (
 	"bytes"
 	"encoding/json"
-	"fmt"
 	"log"
 	"net/http"
 	"strings"
 
 	mjson "git.ali33.ru/fcg-xvii/go-tools/json"
 	"git.ali33.ru/fcg-xvii/rest"
-	jwt "github.com/dgrijalva/jwt-go"
 )
 
 func New(app rest.IApplication, core any, responseHeaders map[string]string) *Rest {
@@ -68,6 +66,7 @@ func (s *Rest) handle(w http.ResponseWriter, r *http.Request) {
 				Files:   make(rest.RequestFiles),
 			},
 			GeneratorToken: s.server.TokenGenerate,
+			ParserToken:    s.server.TokenParse,
 			Core:           s.core,
 		},
 	}
@@ -76,21 +75,9 @@ func (s *Rest) handle(w http.ResponseWriter, r *http.Request) {
 	if authHeader != "" {
 		if parts := strings.Split(authHeader, " "); len(parts) == 2 && parts[0] == "Bearer" {
 			tokenString := parts[1]
-			token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
-				if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
-					return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
-				}
-				return s.server.Secret(), nil
-			})
-
+			auth, err := s.server.TokenParse(tokenString)
 			if err != nil {
-				log.Printf("Failed to parse JWT: %s", err)
-				http.Error(w, "Invalid token", http.StatusUnauthorized)
-				return
-			}
-
-			if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
-				rr.auth = mjson.Map(claims)
+				rr.auth = auth
 			}
 		}
 	}

+ 1 - 0
rest_websocket/app_config.go

@@ -12,4 +12,5 @@ type appConfig struct {
 	core           any
 	ctx            context.Context
 	tokenGenerator func(json.Map, int64) (string, error)
+	tokenParser    func(tokenString string) (json.Map, error)
 }

+ 4 - 0
rest_websocket/request.go

@@ -23,6 +23,10 @@ func (s *RequestIn) GenerateToken(data json.Map, expire int64) (string, error) {
 	return s.owner.appConf.tokenGenerator(data, expire)
 }
 
+func (s *RequestIn) ParseToken(tokenString string) (json.Map, error) {
+	return s.owner.appConf.tokenParser(tokenString)
+}
+
 func (s *RequestIn) ROwner() rest.IOwner {
 	return s.owner
 }

+ 0 - 210
rest_websocket/socket.goo

@@ -1,210 +0,0 @@
-package rest_websocket
-
-import (
-	"context"
-	"io"
-	"log"
-	"sync"
-	"sync/atomic"
-	"time"
-
-	"git.ali33.ru/fcg-xvii/go-tools/json"
-	"git.ali33.ru/fcg-xvii/rest"
-	"github.com/gorilla/websocket"
-)
-
-func newSocket(conn *websocket.Conn, appConf *appConfig) *Socket {
-	ctx, cancel := context.WithCancel(context.Background())
-	ws := &Socket{
-		conn:              conn,
-		waitMessages:      new(sync.Map),
-		ctx:               ctx,
-		cancel:            cancel,
-		sendLocker:        &sync.Mutex{},
-		appConf:           appConf,
-		chMessageIncoming: make(chan *Request, 10),
-	}
-	go ws.read()
-	return ws
-}
-
-type Socket struct {
-	conn              *websocket.Conn
-	ctx               context.Context
-	cancel            context.CancelFunc
-	sendLocker        *sync.Mutex
-	appConf           *appConfig
-	chMessageIncoming chan *Request
-	auth              json.Map
-	clientData        json.Map
-	waitMessages      *sync.Map
-	idCounter         atomic.Int64
-}
-
-func (s *Socket) IsSocket() bool {
-	return true
-}
-
-func (s *Socket) Context() context.Context {
-	return s.ctx
-}
-
-func (s *Socket) MessagesIncoming() <-chan *Request {
-	return s.chMessageIncoming
-}
-
-func (s *Socket) Close() {
-	s.cancel()
-	s.conn.Close()
-}
-
-func (s *Socket) ID() int64 {
-	return s.idCounter.Add(1)
-}
-
-func (s *Socket) NextWriter(messageType int) (w io.WriteCloser, err rest.IErrorArgs) {
-	s.sendLocker.Lock()
-	var wErr error
-	w, wErr = s.conn.NextWriter(websocket.TextMessage)
-	if wErr != nil {
-		err = rest.ErrorMessage("ErrWriterInit", err.Error())
-	}
-	s.sendLocker.Unlock()
-	return
-}
-
-func (s *Socket) SendMessage(msg rest.IRequestOut) rest.IErrorArgs {
-	if msg.RType() == rest.RequestTypeIn {
-		id := s.ID()
-		if req, check := msg.(*Request); check {
-			req.id = id
-		} else {
-			msg = &Request{
-				id:      id,
-				Timeout: time.Now().Add(time.Second * 5),
-				Request: &rest.Request{
-					Type:    rest.RequestTypeIn,
-					Command: msg.RCommand(),
-					Data:    msg.RData(),
-					Files:   msg.RFiles(),
-				},
-			}
-		}
-		s.waitMessages.Store(id, msg)
-	}
-	w, err := s.NextWriter(websocket.BinaryMessage)
-	if err != nil {
-		return err
-	}
-	err = msg.Write(w)
-	w.Close()
-	return err
-}
-
-func (s *Socket) execMessage(reqIn *RequestIn) {
-	defer reqIn.RClose()
-	log.Println("Message", reqIn)
-	var reqOut rest.IRequestOut
-	command, check := s.appConf.app.Executer(reqIn)
-	if !check {
-		reqOut = reqIn.OutError(rest.ErrorMessage("ErrNotFound", "command is not found"))
-	} else {
-		// serialize
-		if err := rest.Serialize(reqIn.RData(), command); err != nil {
-			log.Println("serialize error", err)
-			return
-		}
-		// validate
-		if validator, check := command.(rest.IValidator); check {
-			reqOut = validator.Validate(reqIn)
-			if reqOut != nil {
-
-				if err := s.SendMessage(reqOut); err != nil {
-					log.Println("socket send error", err.Map())
-				}
-				return
-			}
-		}
-		reqOut = command.Execute(reqIn)
-	}
-	log.Println("RESP", reqOut)
-	s.SendMessage(reqOut)
-	reqOut.RClose()
-}
-
-func (s *Socket) messageIncoming() chan<- *Request {
-	chIncoming := make(chan *Request, 100)
-	tClean := time.NewTicker(time.Second * 60)
-	defer tClean.Stop()
-	go func() {
-		for {
-			select {
-			case <-s.ctx.Done():
-				return
-			case req, ok := <-chIncoming:
-				if !ok {
-					return
-				}
-				log.Println("INCOMING!!!!!")
-				switch req.Type {
-				case rest.RequestTypeIn, rest.RequestTypeEvent:
-					reqIn := &RequestIn{
-						Request: req,
-						owner:   s,
-						core:    s.appConf.core,
-					}
-					s.execMessage(reqIn)
-				case rest.RequestTypeOut:
-					log.Println("ANSWER")
-				}
-			case <-tClean.C:
-				now := time.Now()
-				s.waitMessages.Range(func(key, value any) bool {
-					if value.(*Request).Timeout.Before(now) {
-						s.waitMessages.Delete(key)
-					}
-					return true
-				})
-			}
-		}
-	}()
-	return chIncoming
-}
-
-func (s *Socket) read() {
-	chIncoming := s.messageIncoming()
-	defer s.cancel()
-	for {
-		// Read message from server
-		mType, r, err := s.conn.NextReader()
-		if err != nil {
-			log.Println(err)
-			return
-		}
-		log.Println("MTYPE...", mType)
-		switch mType {
-		case websocket.TextMessage, websocket.BinaryMessage:
-			// Обработка текстового сообщения
-			mes, err := ReadRequest(r)
-			if err != nil {
-				log.Println("data error: ", err)
-				return
-			}
-			chIncoming <- mes
-		case websocket.PingMessage:
-			// Отправка Pong в ответ на Ping
-			log.Println("PING......")
-			s.sendLocker.Lock()
-			err := s.conn.WriteControl(websocket.PongMessage, nil, time.Now().Add(time.Second))
-			s.sendLocker.Unlock()
-			if err != nil {
-				log.Println("pong write:", err)
-				return
-			}
-		case websocket.CloseMessage:
-			// Обработка закрытия соединения
-			log.Println("websocket connection closed")
-			return
-		}
-	}
-}

+ 19 - 0
server.go

@@ -3,6 +3,7 @@ package rest
 import (
 	"context"
 	"errors"
+	"fmt"
 	"net/http"
 	"sync/atomic"
 	"time"
@@ -24,6 +25,8 @@ type IServer interface {
 	Listen(timeout time.Duration, ctxParent context.Context) error
 	// TokenGenerate - функция генерации токена авторизации
 	TokenGenerate(m json.Map, expire int64) (string, error)
+	// TokenParse - функция для расшифровки токена в карту значений
+	TokenParse(token string) (json.Map, error)
 	// Close останавливает прослушивание
 	Close() error
 	// Context возвращает контекст сервера
@@ -119,6 +122,22 @@ func (s *Server) TokenGenerate(m json.Map, expire int64) (string, error) {
 	return tokenString, err
 }
 
+func (s *Server) TokenParse(tokenString string) (json.Map, error) {
+	token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
+		if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
+			return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
+		}
+		return s.Secret(), nil
+	})
+	if err != nil {
+		return nil, err
+	}
+	if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
+		return json.Map(claims), nil
+	}
+	return nil, errors.New("invalid token")
+}
+
 // Addr возвращеат адрес, который сервер слушает
 func (s *Server) Addr() string {
 	return s.server.Addr