You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

153 lines
3.6 KiB

package logic
import (
"context"
"encoding/base64"
"errors"
"github.com/bytedance/sonic"
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
"net"
"sonet/api/gen/auth"
"sonet/internal/auth/data"
"sonet/pkg/config"
"sonet/pkg/grpc/discovery"
"sonet/pkg/utils/logger"
"sonet/pkg/utils/security"
"time"
)
type AuthServer struct {
auth.UnimplementedAuthServer
aesTokenKey []byte
userDao *data.AuthUserDao
}
func NewAuthServer(aesTokenKey string, userDao *data.AuthUserDao) *AuthServer {
keyBytes, err := base64.StdEncoding.DecodeString(aesTokenKey)
if err != nil {
panic(err)
}
return &AuthServer{
aesTokenKey: keyBytes,
userDao: userDao,
}
}
func (s *AuthServer) Run(conf config.GrpcConfig, register *discovery.Register) (err error) {
server := grpc.NewServer(
config.GetGrpcOptions(conf)...,
)
if !conf.NoReflection {
// 注册反射服务
reflection.Register(server)
}
auth.RegisterAuthServer(server, s)
listen, err := net.Listen("tcp", conf.Address)
if err != nil {
return
}
// registry discovery
reg := conf.Register
if reg.Name == "" {
reg.Name = auth.Auth_ServiceDesc.ServiceName
}
if reg.Addr == "" {
reg.Addr, err = discovery.RegisterAddress(conf.Address)
if err != nil {
return
}
}
if err = register.Register(reg); err != nil {
return
}
// run serve
logger.Infof("%s grpc server running %s\n", reg.Name, listen.Addr().String())
err = server.Serve(listen)
return
}
func (s *AuthServer) Login(ctx context.Context, req *auth.ReqLogin) (*auth.ResLogin, error) {
user, err := s.userDao.FindByAccount(req.Account)
if err != nil {
return nil, err
}
if user == nil {
// 不存在注册
now := time.Now()
uid, err := s.userDao.NextUid()
if err != nil {
return nil, err
}
user = &data.User{
Uid: uid,
Account: req.Account,
Username: req.Account,
Password: req.Password,
CreateAt: &now,
UpdateAt: &now,
}
err = s.userDao.Create(user)
if err != nil {
return nil, err
}
// return nil, errors.New("not found account " + req.Account)
}
// verify password login
if req.Password != user.Password {
return nil, errors.New("account or password error")
}
// generate token
subject := &auth.Subject{Uid: user.Uid, Username: user.Username, Time: time.Now().UnixMilli()}
bytes, err := sonic.Marshal(subject)
if err != nil {
return nil, err
}
encode, err := security.EncryptAesCBC(bytes, s.aesTokenKey)
if err != nil {
return nil, err
}
token := base64.URLEncoding.EncodeToString(encode)
res := &auth.ResLogin{Token: token, Subject: subject}
return res, nil
}
func (s *AuthServer) Verify(ctx context.Context, req *auth.ReqVerify) (*auth.Subject, error) {
bytes, err := base64.URLEncoding.DecodeString(req.Token)
if err != nil {
return nil, errors.New("token decode fail: " + err.Error())
}
decode, err := security.DecryptAesCBC(bytes, s.aesTokenKey)
if err != nil {
return nil, errors.New("invalidate token: " + err.Error())
}
subject := &auth.Subject{}
err = sonic.Unmarshal(decode, subject)
if err != nil {
return nil, errors.New("token payload decode fail: " + err.Error())
}
return subject, nil
}
func (s *AuthServer) Registry(ctx context.Context, req *auth.ReqRegistry) (*auth.Subject, error) {
return nil, errors.New("can not registry")
}
func (s *AuthServer) FindByUid(ctx context.Context, req *auth.ReqFindByUid) (subject *auth.Subject, err error) {
sub, err := s.userDao.FindByUid(req.Uid)
if err != nil || sub == nil {
return
}
subject = &auth.Subject{
Uid: sub.Uid,
Username: sub.Username,
Time: time.Now().UnixMilli(),
Extra: map[string]string{"avatar": sub.Avatar},
}
return
}