session
This commit is contained in:
parent
bfaf686ff0
commit
f6a914fd85
54
handle/yggdrasil/session.go
Normal file
54
handle/yggdrasil/session.go
Normal file
@ -0,0 +1,54 @@
|
||||
package yggdrasil
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
"github.com/julienschmidt/httprouter"
|
||||
"github.com/xmdhs/authlib-skin/model/yggdrasil"
|
||||
sutils "github.com/xmdhs/authlib-skin/service/utils"
|
||||
"github.com/xmdhs/authlib-skin/utils"
|
||||
)
|
||||
|
||||
func (y *Yggdrasil) SessionJoin() httprouter.Handle {
|
||||
return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
|
||||
ctx := r.Context()
|
||||
a, has := getAnyModel[yggdrasil.Session](ctx, w, r.Body, y.validate, y.logger)
|
||||
if !has {
|
||||
return
|
||||
}
|
||||
ip, err := utils.GetIP(r, y.config.RaelIP)
|
||||
if err != nil {
|
||||
y.logger.WarnContext(ctx, err.Error())
|
||||
handleYgError(ctx, w, yggdrasil.Error{ErrorMessage: err.Error()}, 500)
|
||||
return
|
||||
}
|
||||
err = y.yggdrasilService.SessionJoin(ctx, a, ip)
|
||||
if err != nil {
|
||||
if errors.Is(err, sutils.ErrTokenInvalid) {
|
||||
y.logger.DebugContext(ctx, err.Error())
|
||||
handleYgError(ctx, w, yggdrasil.Error{ErrorMessage: "Invalid token.", Error: "ForbiddenOperationException"}, 403)
|
||||
return
|
||||
}
|
||||
y.logger.WarnContext(ctx, err.Error())
|
||||
handleYgError(ctx, w, yggdrasil.Error{ErrorMessage: err.Error()}, 500)
|
||||
return
|
||||
}
|
||||
w.WriteHeader(204)
|
||||
}
|
||||
}
|
||||
|
||||
func (y *Yggdrasil) HasJoined() httprouter.Handle {
|
||||
return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
|
||||
ctx := r.Context()
|
||||
name := r.FormValue("username")
|
||||
serverId := r.FormValue("serverId")
|
||||
ip := r.FormValue("ip")
|
||||
if name == "" || serverId == "" {
|
||||
y.logger.DebugContext(ctx, "name 或 serverID 为空")
|
||||
w.WriteHeader(204)
|
||||
return
|
||||
}
|
||||
y.yggdrasilService.HasJoined(ctx, name, serverId, ip, r.Host)
|
||||
}
|
||||
}
|
@ -7,6 +7,7 @@ import (
|
||||
"net/http"
|
||||
|
||||
"github.com/go-playground/validator/v10"
|
||||
"github.com/xmdhs/authlib-skin/config"
|
||||
"github.com/xmdhs/authlib-skin/model/yggdrasil"
|
||||
yggdrasilS "github.com/xmdhs/authlib-skin/service/yggdrasil"
|
||||
"github.com/xmdhs/authlib-skin/utils"
|
||||
@ -16,13 +17,15 @@ type Yggdrasil struct {
|
||||
logger *slog.Logger
|
||||
validate *validator.Validate
|
||||
yggdrasilService *yggdrasilS.Yggdrasil
|
||||
config config.Config
|
||||
}
|
||||
|
||||
func NewYggdrasil(logger *slog.Logger, validate *validator.Validate, yggdrasilService *yggdrasilS.Yggdrasil) *Yggdrasil {
|
||||
func NewYggdrasil(logger *slog.Logger, validate *validator.Validate, yggdrasilService *yggdrasilS.Yggdrasil, config config.Config) *Yggdrasil {
|
||||
return &Yggdrasil{
|
||||
logger: logger,
|
||||
validate: validate,
|
||||
yggdrasilService: yggdrasilService,
|
||||
config: config,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -57,3 +57,9 @@ type UserProperties struct {
|
||||
Value string `json:"value"`
|
||||
Signature string `json:"signature,omitempty"`
|
||||
}
|
||||
|
||||
type Session struct {
|
||||
AccessToken string `json:"accessToken" validate:"required,jwt"`
|
||||
SelectedProfile string `json:"selectedProfile" validate:"required,uuid"`
|
||||
ServerID string `json:"serverId"`
|
||||
}
|
||||
|
@ -35,6 +35,9 @@ func newYggdrasil(r *httprouter.Router, handelY yggdrasil.Yggdrasil) error {
|
||||
r.GET("/api/yggdrasil/sessionserver/session/minecraft/profile/:uuid", warpHJSON(handelY.GetProfile()))
|
||||
r.POST("/api/yggdrasil/api/profiles/minecraft", warpHJSON(handelY.BatchProfile()))
|
||||
|
||||
r.POST("/api/yggdrasil/sessionserver/session/minecraft/join", warpHJSON(handelY.SessionJoin()))
|
||||
r.GET("/api/yggdrasil/sessionserver/session/minecraft/hasJoined", warpHJSON(handelY.SessionJoin()))
|
||||
|
||||
r.GET("/api/yggdrasil", func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
|
||||
w.Write([]byte(`{
|
||||
"meta": {
|
||||
|
@ -44,7 +44,7 @@ func InitializeRoute(ctx context.Context, c config.Config) (*http.Server, func()
|
||||
return nil, nil, err
|
||||
}
|
||||
yggdrasilYggdrasil := yggdrasil.NewYggdrasil(client, cache, c, privateKey)
|
||||
yggdrasil3 := yggdrasil2.NewYggdrasil(logger, validate, yggdrasilYggdrasil)
|
||||
yggdrasil3 := yggdrasil2.NewYggdrasil(logger, validate, yggdrasilYggdrasil, c)
|
||||
webService := service.NewWebService(c, client)
|
||||
handel := handle.NewHandel(webService, validate, c, logger)
|
||||
router, err := route.NewRoute(yggdrasil3, handel)
|
||||
|
64
service/yggdrasil/session.go
Normal file
64
service/yggdrasil/session.go
Normal file
@ -0,0 +1,64 @@
|
||||
package yggdrasil
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/samber/lo"
|
||||
"github.com/xmdhs/authlib-skin/db/ent/userprofile"
|
||||
"github.com/xmdhs/authlib-skin/model"
|
||||
"github.com/xmdhs/authlib-skin/model/yggdrasil"
|
||||
sutils "github.com/xmdhs/authlib-skin/service/utils"
|
||||
)
|
||||
|
||||
type sessionWithIP struct {
|
||||
user model.TokenClaims
|
||||
IP string
|
||||
}
|
||||
|
||||
func (y *Yggdrasil) SessionJoin(ctx context.Context, s yggdrasil.Session, ip string) error {
|
||||
t, err := sutils.Auth(ctx, yggdrasil.ValidateToken{
|
||||
AccessToken: s.AccessToken,
|
||||
}, y.client, &y.prikey.PublicKey, true)
|
||||
if err != nil {
|
||||
return fmt.Errorf("SessionJoin: %w", err)
|
||||
}
|
||||
if s.SelectedProfile != t.Subject {
|
||||
return fmt.Errorf("SessionJoin: %w", sutils.ErrTokenInvalid)
|
||||
}
|
||||
err = y.cache.Put([]byte("session"+s.ServerID), lo.Must1(json.Marshal(sessionWithIP{
|
||||
user: *t,
|
||||
IP: ip,
|
||||
})), time.Now().Add(30*time.Second))
|
||||
if err != nil {
|
||||
return fmt.Errorf("SessionJoin: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (y *Yggdrasil) HasJoined(ctx context.Context, username, serverId string, ip string, host string) (yggdrasil.UserInfo, error) {
|
||||
b := lo.Must1(y.cache.Get([]byte("session" + serverId)))
|
||||
sIP := sessionWithIP{}
|
||||
lo.Must0(json.Unmarshal(b, &sIP))
|
||||
|
||||
if ip != "" && ip != sIP.IP {
|
||||
return yggdrasil.UserInfo{}, fmt.Errorf("ip 不相同")
|
||||
}
|
||||
|
||||
up, err := y.client.UserProfile.Query().Where(userprofile.Name(username)).Only(ctx)
|
||||
if err != nil {
|
||||
return yggdrasil.UserInfo{}, fmt.Errorf("HasJoined: %w", err)
|
||||
}
|
||||
|
||||
if up.UUID != sIP.user.Subject {
|
||||
return yggdrasil.UserInfo{}, fmt.Errorf("uuid 不相同")
|
||||
}
|
||||
|
||||
u, err := y.GetProfile(ctx, up.UUID, false, host)
|
||||
if err != nil {
|
||||
return yggdrasil.UserInfo{}, fmt.Errorf("HasJoined: %w", err)
|
||||
}
|
||||
return u, nil
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user