Create & Init Project...

This commit is contained in:
2019-04-22 18:49:16 +08:00
commit fc4fa37393
25440 changed files with 4054998 additions and 0 deletions

View File

@@ -0,0 +1,25 @@
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//app/service/main/passport-auth/api/grpc/v1:all-srcs",
"//app/service/main/passport-auth/cmd:all-srcs",
"//app/service/main/passport-auth/conf:all-srcs",
"//app/service/main/passport-auth/dao:all-srcs",
"//app/service/main/passport-auth/http:all-srcs",
"//app/service/main/passport-auth/model:all-srcs",
"//app/service/main/passport-auth/rpc/client:all-srcs",
"//app/service/main/passport-auth/rpc/grpc:all-srcs",
"//app/service/main/passport-auth/rpc/server:all-srcs",
"//app/service/main/passport-auth/service:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,28 @@
#### Version 1.2.1
> 1. add param validate
#### Version 1.2.0
> 1. token query three month
> 2. del unused code
#### Version 1.1.3
> 1. add dao ut
#### Version 1.1.2
> 1. add addOldToken
> 2. add oldTokenInfo
#### Version 1.1.1
> 1. mv gRPC from api to api/grpc
> 2. add gRPC client
#### Version 1.1.0
> 1.add grpc
> 2.add refresh token info
> 3.add empty cache for cookieInfo and tokenInfo
#### Version 1.0.1
> 1.修复addOldCookie
# v1.0.0
1.

View File

@@ -0,0 +1,10 @@
# Owner
wanghuan01
wutao
# Author
wanghuan01
chenjunxi
# Reviewer
wanghuan01

View File

@@ -0,0 +1,15 @@
# See the OWNERS docs at https://go.k8s.io/owners
approvers:
- chenjunxi
- wanghuan01
- wutao
labels:
- main
- service
- service/main/passport-auth
options:
no_parent_owners: true
reviewers:
- chenjunxi
- wanghuan01

View File

@@ -0,0 +1,13 @@
# passport-auth
# 项目简介
1.
# 编译环境
# 依赖包
# 编译执行

View File

@@ -0,0 +1,57 @@
load(
"@io_bazel_rules_go//proto:def.bzl",
"go_proto_library",
)
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
proto_library(
name = "v1_proto",
srcs = ["api.proto"],
tags = ["automanaged"],
deps = ["@gogo_special_proto//github.com/gogo/protobuf/gogoproto"],
)
go_proto_library(
name = "v1_go_proto",
compilers = ["@io_bazel_rules_go//proto:gogofast_grpc"],
importpath = "go-common/app/service/main/passport-auth/api/grpc/v1",
proto = ":v1_proto",
tags = ["automanaged"],
deps = ["@com_github_gogo_protobuf//gogoproto:go_default_library"],
)
go_library(
name = "go_default_library",
srcs = ["client.go"],
embed = [":v1_go_proto"],
importpath = "go-common/app/service/main/passport-auth/api/grpc/v1",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//library/net/rpc/warden:go_default_library",
"@com_github_gogo_protobuf//gogoproto:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library",
"@org_golang_google_grpc//:go_default_library",
"@org_golang_x_net//context:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,53 @@
// 此服务为账号内部服务,禁止所有外部服务调用
// 账号外部业务请使用identify service
syntax = "proto3";
package passport.service.auth.v1;
option go_package = "v1";
import "github.com/gogo/protobuf/gogoproto/gogo.proto";
// GetCookieInfoReq request param for rpc CookieInfo
message GetCookieInfoReq {
// all user cookie of HTTP request
// example: 'SESSDATA=DEE4597D836A5A9DA29DFC1AB1EFFDEB;sid=exampleSID'
string cookie = 1;
}
// GetCookieInfoReply reply val for rpc CookieInfo
message GetCookieInfoReply {
// 用户是否登录
bool is_login = 1 [(gogoproto.jsontag) = "is_login"];
// user mid
int64 mid = 2 [(gogoproto.jsontag) = "mid"];
// cookie csrf
// when token reqest this field is empty
string csrf = 3 [(gogoproto.jsontag) = "csrfToken"];
// expire time(unix timestamp)
int64 expires = 4 [(gogoproto.jsontag) = "expires"];
}
// GetTokenInfoReq request param for rpc TokenInfo
message GetTokenInfoReq {
// user access token
string token = 1;
}
// GetTokenInfoReply reply val for rpc TokenInfo
message GetTokenInfoReply {
// 用户是否登录
bool is_login = 1 [(gogoproto.jsontag) = "is_login"];
// user mid
int64 mid = 2 [(gogoproto.jsontag) = "mid"];
// cookie csrf
// when token reqest this field is empty
string csrf = 3 [(gogoproto.jsontag) = "csrfToken"];
// expire time(unix timestamp)
int64 expires = 4 [(gogoproto.jsontag) = "expires"];
}
service Auth {
// GetCookieInfo verify user info by cookie.
rpc GetCookieInfo (GetCookieInfoReq) returns (GetCookieInfoReply);
// GetTokenInfo verify user info by token.
rpc GetTokenInfo (GetTokenInfoReq) returns (GetTokenInfoReply);
}

View File

@@ -0,0 +1,22 @@
package v1
import (
"context"
"google.golang.org/grpc"
"go-common/library/net/rpc/warden"
)
// AppID unique app id for service discovery
const AppID = "passport.service.auth"
// NewClient new auth gRPC client
func NewClient(cfg *warden.ClientConfig, opts ...grpc.DialOption) (AuthClient, error) {
client := warden.NewClient(cfg, opts...)
conn, err := client.Dial(context.Background(), "discovery://default/"+AppID)
if err != nil {
return nil, err
}
return NewAuthClient(conn), nil
}

View File

@@ -0,0 +1,48 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
)
go_binary(
name = "cmd",
embed = [":go_default_library"],
tags = ["automanaged"],
)
go_library(
name = "go_default_library",
srcs = ["main.go"],
data = [
"passport-auth-service.toml",
"passport-auth-service-uat.toml",
],
importpath = "go-common/app/service/main/passport-auth/cmd",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/passport-auth/conf:go_default_library",
"//app/service/main/passport-auth/http:go_default_library",
"//app/service/main/passport-auth/rpc/grpc:go_default_library",
"//app/service/main/passport-auth/rpc/server:go_default_library",
"//app/service/main/passport-auth/service:go_default_library",
"//library/log:go_default_library",
"//library/net/trace:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,53 @@
package main
import (
"context"
"flag"
"os"
"os/signal"
"syscall"
"time"
"go-common/app/service/main/passport-auth/conf"
"go-common/app/service/main/passport-auth/http"
"go-common/app/service/main/passport-auth/rpc/grpc"
rpc "go-common/app/service/main/passport-auth/rpc/server"
"go-common/app/service/main/passport-auth/service"
"go-common/library/log"
"go-common/library/net/trace"
)
func main() {
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
log.Init(conf.Conf.Xlog)
defer log.Close()
trace.Init(conf.Conf.Tracer)
defer trace.Close()
svr := service.New(conf.Conf)
// rpc server init
rpcSvr := rpc.New(conf.Conf, svr)
ws := grpc.New(conf.Conf.WardenServer, svr)
http.Init(conf.Conf, svr)
// signal handler
log.Info("passport-auth-service start")
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
for {
s := <-c
log.Info("passport-auth-service get a signal %s", s.String())
switch s {
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
ws.Shutdown(context.Background())
rpcSvr.Close()
time.Sleep(time.Second * 2)
log.Info("passport-auth-service exit")
return
case syscall.SIGHUP:
default:
return
}
}
}

View File

@@ -0,0 +1,45 @@
[rpcServer2]
[[rpcServer2.servers]]
proto = "tcp"
addr = "0.0.0.0:9009"
weight = 10
[rpcServer2.zookeeper]
root = "/microservice/passport-auth-service/"
addrs = ["172.18.33.50:2199","172.18.33.51:2199","172.18.33.52:2199"]
timeout = "1s"
[mysql]
addr = "172.22.34.101:3308"
dsn = "auth:ABQ3ewVrxyZsLpWb0EkJuCvN9M8aidf7@tcp(172.22.34.101:3308)/passport_auth?timeout=200ms&readTimeout=200ms&writeTimeout=200ms&parseTime=true&loc=Local&charset=utf8,utf8mb4"
readDSN = ["auth_reader:3odEZJ7YlOLpNzt4XVDxHTw9bi08C1M2@tcp(172.22.34.101:3308)/passport_auth?timeout=200ms&readTimeout=200ms&writeTimeout=200ms&parseTime=true&loc=Local&charset=utf8,utf8mb4"]
active = 10
idle = 10
idleTimeout ="4h"
queryTimeout = "100ms"
execTimeout = "100ms"
tranTimeout = "200ms"
[mysql.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[memcache]
name = "passport-auth-service"
proto = "tcp"
addr = ""
idle = 10
active = 10
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "10s"
expire = "24h"
[dc]
num = 1
desc = "data center 1"
[switch]
supportOld = true

View File

@@ -0,0 +1,47 @@
# This is a TOML document. Boom.
[rpcServer2]
[[rpcServer2.servers]]
proto = "tcp"
addr = "0.0.0.0:7579"
weight = 10
[rpcServer2.zookeeper]
root = "/microservice/passport-auth-service/"
addrs = ["172.18.33.172:2181"]
timeout = "1s"
[mysql]
#addr = "172.16.33.205:3309"
#dsn = "auth:Ftqx1hwV3WoGX7Ms9udTAzmbkgR5ZHyl@tcp(172.16.33.205:3309)/passport_auth?timeout=5s&readTimeout=5s&writeTimeout=5s&parseTime=true&loc=Local&charset=utf8,utf8mb4"
addr = "127.0.0.1:3306"
dsn = "root:root@tcp(127.0.0.1:3306)/passport-auth?timeout=5s&readTimeout=5s&writeTimeout=5s&parseTime=true&loc=Local&charset=utf8,utf8mb4"
active = 5
idle = 2
IdleTimeout ="4h"
queryTimeout = "100ms"
execTimeout = "100ms"
tranTimeout = "200ms"
[mysql.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[Memcache]
name = "passport-auth-service"
proto = "tcp"
#addr = "172.16.33.54:11211"
addr = "127.0.0.1:11211"
idle = 1000
active = 1000
dialTimeout = "10s"
readTimeout = "10s"
writeTimeout = "10s"
idleTimeout = "30s"
[dc]
num = 1
desc = "data center 1"
[switch]
supportOld = true

View File

@@ -0,0 +1,41 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["conf.go"],
importpath = "go-common/app/service/main/passport-auth/conf",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//library/cache/memcache:go_default_library",
"//library/conf:go_default_library",
"//library/database/sql:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/net/http/blademaster/middleware/verify:go_default_library",
"//library/net/rpc:go_default_library",
"//library/net/rpc/warden:go_default_library",
"//library/net/trace:go_default_library",
"//library/time:go_default_library",
"//vendor/github.com/BurntSushi/toml:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,119 @@
package conf
import (
"errors"
"flag"
"go-common/library/cache/memcache"
"go-common/library/conf"
"go-common/library/database/sql"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/middleware/verify"
"go-common/library/net/rpc"
"go-common/library/net/rpc/warden"
"go-common/library/net/trace"
xtime "go-common/library/time"
"github.com/BurntSushi/toml"
)
// Conf global variable.
var (
Conf = &Config{}
client *conf.Client
confPath string
)
// Config login conf
type Config struct {
// tracer
Tracer *trace.Config
// xlog
Xlog *log.Config
// Identify
VerifyConfig *verify.Config
// db
Mysql *sql.Config
// mc
Memcache *Memcache
// app
App *bm.App
// BM
BM *bm.ServerConfig
// RPC
RPCServer *rpc.ServerConfig
// grpc
WardenServer *warden.ServerConfig
DC *DC
ServiceConf *ServiceConf
}
// ServiceConf Switch
type ServiceConf struct {
SupportOld bool
Permit map[string]string
}
// DC DC
type DC struct {
Num int
Desc string
}
// Memcache cache
type Memcache struct {
*memcache.Config
Expire xtime.Duration
}
func local() (err error) {
_, err = toml.DecodeFile(confPath, &Conf)
return
}
func remote() (err error) {
if client, err = conf.New(); err != nil {
return
}
if err = load(); err != nil {
return
}
go func() {
for range client.Event() {
log.Info("config reload")
if load() != nil {
log.Error("config reload error (%v)", err)
}
}
}()
return
}
func load() (err error) {
var (
s string
ok bool
tmpConf *Config
)
if s, ok = client.Value("passport-auth-service.toml"); !ok {
return errors.New("load config center error")
}
if _, err = toml.Decode(s, &tmpConf); err != nil {
return errors.New("could not decode config")
}
*Conf = *tmpConf
return
}
func init() {
flag.StringVar(&confPath, "conf", "", "default config path")
}
// Init int config
func Init() error {
if confPath != "" {
return local()
}
return remote()
}

View File

@@ -0,0 +1,61 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"cookie_test.go",
"dao_test.go",
"mc_test.go",
"refresh_test.go",
"token_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/service/main/passport-auth/conf:go_default_library",
"//app/service/main/passport-auth/model:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"cookie.go",
"dao.go",
"mc.go",
"refresh.go",
"token.go",
],
importpath = "go-common/app/service/main/passport-auth/dao",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/passport-auth/conf:go_default_library",
"//app/service/main/passport-auth/model:go_default_library",
"//library/cache/memcache:go_default_library",
"//library/database/sql:go_default_library",
"//library/log:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,34 @@
package dao
import (
"context"
"encoding/hex"
"fmt"
"time"
"go-common/app/service/main/passport-auth/model"
xsql "go-common/library/database/sql"
"go-common/library/log"
)
const (
_getCookieSessionSQL = "SELECT mid,session,csrf,type,expires FROM user_cookie_%s where session = ? limit 1"
)
// Cookie get cookie by session
func (d *Dao) Cookie(c context.Context, sd []byte, ct time.Time) (res *model.Cookie, session []byte, err error) {
row := d.db.QueryRow(c, fmt.Sprintf(_getCookieSessionSQL, formatSuffix(ct)), sd)
res = new(model.Cookie)
var csrf []byte
if err = row.Scan(&res.Mid, &session, &csrf, &res.Type, &res.Expires); err != nil {
if err == xsql.ErrNoRows {
res = nil
err = nil
} else {
log.Error("row.Scan() error(%v)", err)
}
return
}
res.CSRF = hex.EncodeToString(csrf)
return
}

View File

@@ -0,0 +1,32 @@
package dao
import (
"context"
"testing"
"time"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoCookie(t *testing.T) {
var (
c = context.TODO()
sd = []byte("5ebd8ebb,1530838806,2c8d0678")
sdNotExist = []byte("9f1c9145,1536117849,c9fb62a2")
ct, _ = time.Parse("01/02/2006", "07/27/2018")
)
convey.Convey("Cookie", t, func(ctx convey.C) {
res, session, err := d.Cookie(c, sd, ct)
ctx.Convey("Then err should be nil.res,session should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(session, convey.ShouldNotBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
res2, session2, err2 := d.Cookie(c, sdNotExist, ct)
ctx.Convey("Then err should be nil.res,session should be nil.", func(ctx convey.C) {
ctx.So(err2, convey.ShouldBeNil)
ctx.So(session2, convey.ShouldBeNil)
ctx.So(res2, convey.ShouldBeNil)
})
})
}

View File

@@ -0,0 +1,47 @@
package dao
import (
"context"
"time"
"go-common/app/service/main/passport-auth/conf"
"go-common/library/cache/memcache"
"go-common/library/database/sql"
)
// Dao dao struct
type Dao struct {
db *sql.DB
mc *memcache.Pool
mcExpire int32
c *conf.Config
}
// New create new dao
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
db: sql.NewMySQL(c.Mysql),
mc: memcache.NewPool(c.Memcache.Config),
mcExpire: int32(time.Duration(c.Memcache.Expire) / time.Second),
}
return
}
// Ping check db and mc health.
func (d *Dao) Ping(c context.Context) (err error) {
if err = d.db.Ping(c); err != nil {
return
}
return d.pingMC(c)
}
// Close close connections of mc, redis, db.
func (d *Dao) Close() {
if d.mc != nil {
d.mc.Close()
}
if d.db != nil {
d.db.Close()
}
}

View File

@@ -0,0 +1,35 @@
package dao
import (
"flag"
"go-common/app/service/main/passport-auth/conf"
"os"
"testing"
)
var (
d *Dao
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.passport.passport-auth-service")
flag.Set("conf_token", "3f34a05a9bf3bc0add9c135c1f83ff2f")
flag.Set("tree_id", "35706")
flag.Set("conf_version", "docker-1")
flag.Set("deploy_env", "uat")
flag.Set("conf_host", "config.bilibili.co")
flag.Set("conf_path", "/tmp")
flag.Set("region", "sh")
flag.Set("zone", "sh001")
} else {
flag.Set("conf", "/Users/bilibili/gopath/src/go-common/app/service/main/passport-auth/cmd/passport-auth-service.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
d = New(conf.Conf)
m.Run()
os.Exit(0)
}

View File

@@ -0,0 +1,199 @@
package dao
import (
"context"
"fmt"
"go-common/app/service/main/passport-auth/model"
"go-common/library/cache/memcache"
"go-common/library/log"
)
func ckKey(session string) string {
return fmt.Sprintf("ck_%s", session)
}
func akKey(token string) string {
return fmt.Sprintf("ak_%s", token)
}
func rkKey(refresh string) string {
return fmt.Sprintf("rk_%s", refresh)
}
// SetCookieCache set cookie info to cache
func (d *Dao) SetCookieCache(c context.Context, session string, res *model.Cookie) (err error) {
key := ckKey(session)
conn := d.mc.Get(c)
defer conn.Close()
if res.Expires < 0 {
log.Error("auth expire error(expires:%d)", res.Expires)
return
}
item := &memcache.Item{Key: key, Object: res, Flags: memcache.FlagProtobuf, Expiration: int32(res.Expires)}
if err = conn.Set(item); err != nil {
log.Error("auth set error(%s,%d,%v)", key, res.Expires, err)
}
return
}
// CookieCache get cookie info from cache
func (d *Dao) CookieCache(c context.Context, session string) (res *model.Cookie, err error) {
key := ckKey(session)
conn := d.mc.Get(c)
defer conn.Close()
var item *memcache.Item
if item, err = conn.Get(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
log.Error("conn.Get(%s) error(%v)", key, err)
return
}
res = new(model.Cookie)
if err = conn.Scan(item, res); err != nil {
log.Error("conn.Scan(%v) error(%v)", string(item.Value), err)
}
return
}
// DelCookieCache del cache.
func (d *Dao) DelCookieCache(c context.Context, session string) (err error) {
conn := d.mc.Get(c)
defer conn.Close()
if err = conn.Delete(ckKey(session)); err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
log.Error("conn.Delete(%s) error(%v)", ckKey(session), err)
}
return
}
// SetTokenCache set token to cache
func (d *Dao) SetTokenCache(c context.Context, k string, res *model.Token) (err error) {
key := akKey(k)
conn := d.mc.Get(c)
defer conn.Close()
if res.Expires < 0 {
log.Error("auth expire error(expires:%d)", res.Expires)
return
}
if err = conn.Set(&memcache.Item{
Key: key,
Object: res,
Flags: memcache.FlagProtobuf,
Expiration: int32(res.Expires),
}); err != nil {
log.Error("set token cache error(%s,%d,%v)", key, res.Expires, err)
}
return
}
// TokenCache get token from cache
func (d *Dao) TokenCache(c context.Context, sd string) (res *model.Token, err error) {
key := akKey(sd)
conn := d.mc.Get(c)
defer conn.Close()
r, err := conn.Get(key)
if err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
log.Error("conn.Get(%s) error(%v)", key, err)
return
}
res = new(model.Token)
if err = conn.Scan(r, res); err != nil {
log.Error("conn.Scan(%v) error(%v)", string(r.Value), err)
}
return
}
// DelTokenCache del cache.
func (d *Dao) DelTokenCache(c context.Context, token string) (err error) {
key := akKey(token)
conn := d.mc.Get(c)
defer conn.Close()
if err = conn.Delete(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
log.Error("conn.Delete(%s) error(%v)", key, err)
}
return
}
// SetRefreshCache set refresh token to cache .
func (d *Dao) SetRefreshCache(c context.Context, refresh *model.Refresh) (err error) {
key := rkKey(refresh.Refresh)
conn := d.mc.Get(c)
defer conn.Close()
if refresh.Expires < 0 {
log.Error("auth expire error(expires:%d)", refresh.Expires)
return
}
if err := conn.Set(&memcache.Item{
Key: key,
Object: refresh,
Flags: memcache.FlagProtobuf,
Expiration: int32(refresh.Expires),
}); err != nil {
log.Error("auth set error(%s,%d,%v)", key, refresh.Expires, err)
}
return
}
// RefreshCache get refresh token from cache
func (d *Dao) RefreshCache(c context.Context, refresh string) (res *model.Refresh, err error) {
key := rkKey(refresh)
conn := d.mc.Get(c)
defer conn.Close()
r, err := conn.Get(key)
if err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
log.Error("conn.Get(%s) error(%v)", key, err)
return
}
res = new(model.Refresh)
if err = conn.Scan(r, res); err != nil {
log.Error("conn.Scan(%v) error(%v)", string(r.Value), err)
}
return
}
// DelRefreshCache del refresh token from cache
func (d *Dao) DelRefreshCache(c context.Context, refresh string) (err error) {
key := akKey(refresh)
conn := d.mc.Get(c)
defer conn.Close()
if err = conn.Delete(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
log.Error("conn.Delete(%s) error(%v)", key, err)
}
return
}
// pingMC ping memcache.
func (d *Dao) pingMC(c context.Context) (err error) {
conn := d.mc.Get(c)
defer conn.Close()
if err = conn.Set(&memcache.Item{
Key: "ping",
Value: []byte{1},
Expiration: d.mcExpire,
}); err != nil {
log.Error("conn.Set(ping, 1) error(%v)", err)
}
return
}

View File

@@ -0,0 +1,185 @@
package dao
import (
"context"
"go-common/app/service/main/passport-auth/model"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaockKey(t *testing.T) {
var (
session = "9f1c9145,1536117849,c9fb62a9"
)
convey.Convey("ckKey", t, func(ctx convey.C) {
p1 := ckKey(session)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaoakKey(t *testing.T) {
var (
token = "b8b544c602557c27d454911d7ecc006c"
)
convey.Convey("akKey", t, func(ctx convey.C) {
p1 := akKey(token)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaorkKey(t *testing.T) {
var (
refresh = "5f263d1297aa40ea0252c0963e29c6eb"
)
convey.Convey("rkKey", t, func(ctx convey.C) {
p1 := rkKey(refresh)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaoSetCookieCache(t *testing.T) {
var (
c = context.TODO()
session = "9f1c9145,1536117849,c9fb62a9"
res = &model.Cookie{}
)
convey.Convey("SetCookieCache", t, func(ctx convey.C) {
err := d.SetCookieCache(c, session, res)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoCookieCache(t *testing.T) {
var (
c = context.TODO()
session = "9f1c9145,1536117849,c9fb62a9"
)
convey.Convey("CookieCache", t, func(ctx convey.C) {
res, err := d.CookieCache(c, session)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestDaoDelCookieCache(t *testing.T) {
var (
c = context.TODO()
session = "9f1c9145,1536117849,c9fb62a9"
)
convey.Convey("DelCookieCache", t, func(ctx convey.C) {
err := d.DelCookieCache(c, session)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoSetTokenCache(t *testing.T) {
var (
c = context.TODO()
k = "5f263d1297aa40ea0252c0963e29c6eb"
res = &model.Token{}
)
convey.Convey("SetTokenCache", t, func(ctx convey.C) {
err := d.SetTokenCache(c, k, res)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoTokenCache(t *testing.T) {
var (
c = context.TODO()
sd = "5f263d1297aa40ea0252c0963e29c6eb"
)
convey.Convey("TokenCache", t, func(ctx convey.C) {
res, err := d.TokenCache(c, sd)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestDaoDelTokenCache(t *testing.T) {
var (
c = context.TODO()
token = "5f263d1297aa40ea0252c0963e29c6eb"
)
convey.Convey("DelTokenCache", t, func(ctx convey.C) {
err := d.DelTokenCache(c, token)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoSetRefreshCache(t *testing.T) {
var (
c = context.TODO()
refresh = &model.Refresh{
Mid: 123,
AppID: 430,
Token: "b8b544c602557c27d454911d7ecc006c",
Refresh: "5f263d1297aa40ea0252c0963e29c6e1",
Expires: 1850953187,
}
)
convey.Convey("SetRefreshCache", t, func(ctx convey.C) {
err := d.SetRefreshCache(c, refresh)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoRefreshCache(t *testing.T) {
var (
c = context.TODO()
refresh = "5f263d1297aa40ea0252c0963e29c6e1"
)
convey.Convey("RefreshCache", t, func(ctx convey.C) {
res, err := d.RefreshCache(c, refresh)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestDaoDelRefreshCache(t *testing.T) {
var (
c = context.TODO()
refresh = "5f263d1297aa40ea0252c0963e29c6e0"
)
convey.Convey("DelRefreshCache", t, func(ctx convey.C) {
err := d.DelRefreshCache(c, refresh)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaopingMC(t *testing.T) {
var (
c = context.TODO()
)
convey.Convey("pingMC", t, func(ctx convey.C) {
err := d.pingMC(c)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}

View File

@@ -0,0 +1,46 @@
package dao
import (
"context"
"encoding/hex"
"fmt"
"time"
"go-common/app/service/main/passport-auth/model"
xsql "go-common/library/database/sql"
"go-common/library/log"
)
const (
_getRefreshSQL = "SELECT mid,appid,refresh,token,expires FROM user_refresh_%s WHERE refresh = ? limit 1"
)
// Refresh get token by access_token
func (d *Dao) Refresh(c context.Context, rk []byte, ct time.Time) (res *model.Refresh, err error) {
row := d.db.QueryRow(c, fmt.Sprintf(_getRefreshSQL, formatRefreshSuffix(ct)), rk)
res = new(model.Refresh)
var refresh, token []byte
if err = row.Scan(&res.Mid, &res.AppID, &refresh, &token, &res.Expires); err != nil {
if err == xsql.ErrNoRows {
res = nil
err = nil
} else {
log.Error("row.Scan() error(%v)", err)
}
return
}
res.Refresh = hex.EncodeToString(refresh)
res.Token = hex.EncodeToString(token)
return
}
func formatRefreshSuffix(t time.Time) string {
return formatByDate(t.Year(), int(t.Month()))
}
func formatByDate(year, month int) string {
if month%2 == 1 {
return fmt.Sprintf("%4d%02d", year, month)
}
return fmt.Sprintf("%4d%02d", year, month-1)
}

View File

@@ -0,0 +1,56 @@
package dao
import (
"context"
"encoding/hex"
"testing"
"time"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoRefresh(t *testing.T) {
var (
c = context.TODO()
rk, _ = hex.DecodeString("5f1813d287eb4238f2eadf225bda5d84")
rkNotExist, _ = hex.DecodeString("5f1813d287eb4238f2eadf225bda5d81")
ct, _ = time.Parse("01/02/2006", "08/27/2018")
)
convey.Convey("Refresh", t, func(ctx convey.C) {
res, err := d.Refresh(c, rk, ct)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
res2, err2 := d.Refresh(c, rkNotExist, ct)
ctx.Convey("Then err should be nil.res should be nil.", func(ctx convey.C) {
ctx.So(err2, convey.ShouldBeNil)
ctx.So(res2, convey.ShouldBeNil)
})
})
}
func TestDaoformatRefreshSuffix(t *testing.T) {
var (
no = time.Now()
)
convey.Convey("formatRefreshSuffix", t, func(ctx convey.C) {
p1 := formatRefreshSuffix(no)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaoformatByDate(t *testing.T) {
var (
year = int(2018)
month = int(8)
)
convey.Convey("formatByDate", t, func(ctx convey.C) {
p1 := formatByDate(year, month)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,38 @@
package dao
import (
"context"
"encoding/hex"
"fmt"
"time"
"go-common/app/service/main/passport-auth/model"
xsql "go-common/library/database/sql"
"go-common/library/log"
)
const (
_getTokenSQL = "SELECT mid,appid,token,expires,type FROM user_token_%s where token = ? limit 1"
)
// Token get token by access_token
func (d *Dao) Token(c context.Context, token []byte, ct time.Time) (res *model.Token, err error) {
row := d.db.QueryRow(c, fmt.Sprintf(_getTokenSQL, formatSuffix(ct)), token)
res = new(model.Token)
var tokenByte []byte
if err = row.Scan(&res.Mid, &res.AppID, &tokenByte, &res.Expires, &res.Type); err != nil {
if err == xsql.ErrNoRows {
res = nil
err = nil
} else {
log.Error("row.Scan() error(%v)", err)
}
return
}
res.Token = hex.EncodeToString(tokenByte)
return
}
func formatSuffix(t time.Time) string {
return t.Format("200601")
}

View File

@@ -0,0 +1,43 @@
package dao
import (
"context"
"encoding/hex"
"testing"
"time"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoToken(t *testing.T) {
var (
c = context.TODO()
token, _ = hex.DecodeString("baa3443180f346db244780ba6d0c6f6c")
tokenNotExist, _ = hex.DecodeString("baa3443180f346db244780ba6d0c6f61")
ct, _ = time.Parse("01/02/2006", "10/27/2018")
)
convey.Convey("Token", t, func(ctx convey.C) {
res, err := d.Token(c, token, ct)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
res2, err2 := d.Token(c, tokenNotExist, ct)
ctx.Convey("Then err should be nil.res should be nil.", func(ctx convey.C) {
ctx.So(err2, convey.ShouldBeNil)
ctx.So(res2, convey.ShouldBeNil)
})
})
}
func TestDaoformatSuffix(t *testing.T) {
var (
no = time.Now()
)
convey.Convey("formatSuffix", t, func(ctx convey.C) {
p1 := formatSuffix(no)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,40 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"cookie.go",
"http.go",
"token.go",
],
importpath = "go-common/app/service/main/passport-auth/http",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/passport-auth/conf:go_default_library",
"//app/service/main/passport-auth/service:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/net/http/blademaster/middleware/verify:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,19 @@
package http
import (
"go-common/library/ecode"
bm "go-common/library/net/http/blademaster"
)
func cookieInfo(c *bm.Context) {
session := c.Request.Form.Get("session")
if session == "" {
c.JSON(nil, ecode.RequestErr)
return
}
res, err := svr.CookieInfo(c, session)
if err == nil {
c.Set("mid", res.Mid)
}
c.JSON(res, err)
}

View File

@@ -0,0 +1,45 @@
package http
import (
"go-common/app/service/main/passport-auth/conf"
"go-common/app/service/main/passport-auth/service"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/middleware/verify"
)
var (
svr *service.Service
vfy *verify.Verify
)
// Init init config
func Init(c *conf.Config, srv *service.Service) {
initService(c, srv)
engineOut := bm.DefaultServer(c.BM)
outerRouter(engineOut)
if err := engineOut.Start(); err != nil {
log.Error("bm.DefaultServer error(%v)", err)
}
}
func initService(c *conf.Config, srv *service.Service) {
svr = srv
vfy = verify.New(c.VerifyConfig)
}
// outerRouter init outer router
func outerRouter(e *bm.Engine) {
e.GET("/monitor/ping", ping)
group := e.Group("/x/internal/passport-auth", vfy.Verify)
{
group.GET("/cookie_info", cookieInfo)
group.GET("/token_info", tokenInfo)
group.GET("/refresh_info", refreshInfo)
group.GET("/old_token_info", oldTokenInfo)
}
}
func ping(c *bm.Context) {
}

View File

@@ -0,0 +1,45 @@
package http
import (
"go-common/library/ecode"
bm "go-common/library/net/http/blademaster"
)
func tokenInfo(c *bm.Context) {
ak := c.Request.Form.Get("access_token")
if len(ak) != 32 {
c.JSON(nil, ecode.RequestErr)
return
}
res, err := svr.TokenInfo(c, ak)
if err == nil {
c.Set("mid", res.Mid)
}
c.JSON(res, err)
}
func refreshInfo(c *bm.Context) {
rk := c.Request.Form.Get("refresh_token")
if len(rk) != 32 {
c.JSON(nil, ecode.RequestErr)
return
}
res, err := svr.RefreshInfo(c, rk)
if res != nil {
c.Set("mid", res.Mid)
}
c.JSON(res, err)
}
func oldTokenInfo(c *bm.Context) {
ak := c.Request.Form.Get("access_token")
if len(ak) != 32 {
c.JSON(nil, ecode.RequestErr)
return
}
res, err := svr.OldTokenInfo(c, ak)
if res != nil {
c.Set("mid", res.Mid)
}
c.JSON(res, err)
}

View File

@@ -0,0 +1,58 @@
load(
"@io_bazel_rules_go//proto:def.bzl",
"go_proto_library",
)
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
proto_library(
name = "model_proto",
srcs = ["auth.proto"],
tags = ["automanaged"],
deps = ["@gogo_special_proto//github.com/gogo/protobuf/gogoproto"],
)
go_proto_library(
name = "model_go_proto",
compilers = ["@io_bazel_rules_go//proto:gogofast_proto"],
importmap = "go-common/app/service/main/passport-auth/model",
importpath = "go-common/app/service/main/passport-auth/model",
proto = ":model_proto",
tags = ["automanaged"],
deps = ["@com_github_gogo_protobuf//gogoproto:go_default_library"],
)
go_library(
name = "go_default_library",
srcs = [
"model.go",
"rpc.go",
],
embed = [":model_go_proto"],
importpath = "go-common/app/service/main/passport-auth/model",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"@com_github_gogo_protobuf//gogoproto:go_default_library",
"@com_github_golang_protobuf//proto:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,44 @@
syntax = "proto3";
package passport.service.auth;
option go_package = "model";
import "github.com/gogo/protobuf/gogoproto/gogo.proto";
// AuthReply auth reply
message AuthReply {
// if cookie or token in life time, login is true
// else login is false and mid csrf expires is empty
bool Login = 1 [(gogoproto.jsontag) = "login"];
// user identify id
int64 Mid = 2 [(gogoproto.jsontag) = "mid"];
// use cookie request this field will return
// use token request ignore this field
string CSRF = 3 [(gogoproto.jsontag) = "csrf_token"];
// expiration date
// unix timestamp
int64 Expires = 4 [(gogoproto.jsontag) = "expires"];
}
message Cookie {
int64 Mid = 1 [(gogoproto.jsontag) = "mid"];
string Session = 2 [(gogoproto.jsontag) = "session"];
string CSRF = 3 [(gogoproto.jsontag) = "csrf"];
int64 Type = 4 [(gogoproto.jsontag) = "type"];
int64 Expires = 5 [(gogoproto.jsontag) = "expires"];
}
message Token {
int64 Mid = 1 [(gogoproto.jsontag) = "mid"];
int32 AppID = 2 [(gogoproto.jsontag) = "appid"];
string Token = 3 [(gogoproto.jsontag) = "token"];
int64 Type = 4 [(gogoproto.jsontag) = "type"];
int64 Expires = 5 [(gogoproto.jsontag) = "expires"];
}
message Refresh {
int64 Mid = 1 [(gogoproto.jsontag) = "mid"];
int32 AppID = 2 [(gogoproto.jsontag) = "appid"];
string Refresh = 3 [(gogoproto.jsontag) = "refresh"];
string Token = 4 [(gogoproto.jsontag) = "token"];
int64 Expires = 5 [(gogoproto.jsontag) = "expires"];
}

View File

@@ -0,0 +1,17 @@
package model
// RefreshTokenResp refreshToken response
type RefreshTokenResp struct {
Mid int64 `json:"mid"`
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
Expires int64 `json:"expires"`
}
// CookieResp cookie response
type CookieResp struct {
Mid int64 `json:"mid"`
Session string `json:"session"`
CSRF string `json:"csrf"`
Expires int64 `json:"expires"`
}

View File

@@ -0,0 +1,7 @@
#! /bin/sh
# proto.sh
gopath=$GOPATH/src
gogopath=$GOPATH/src/go-common/vendor/github.com/gogo/protobuf
protoc --gofast_out=. --proto_path=$gopath:$gogopath:. *.proto

View File

@@ -0,0 +1,19 @@
package model
// ArgRefreshToken rpc refreshToken arg
type ArgRefreshToken struct {
AppID int32
RefreshToken string
}
// ArgToken rpc token arg.
type ArgToken struct {
AppID, SubID int32
Mid int64
}
// ArgCookie rpc cookie arg.
type ArgCookie struct {
Mid, Expires int64
PWD string
}

View File

@@ -0,0 +1,39 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["client_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = ["//vendor/github.com/smartystreets/goconvey/convey:go_default_library"],
)
go_library(
name = "go_default_library",
srcs = ["client.go"],
importpath = "go-common/app/service/main/passport-auth/rpc/client",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = ["//library/net/rpc:go_default_library"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,44 @@
package client
import (
"context"
"go-common/library/net/rpc"
)
var (
_noRes = &struct{}{}
)
const (
// token
_delTokenCache = "RPC.DelTokenCache"
// cookie
_delCookieCache = "RPC.DelCookieCache"
)
// Service is a question service.
type Service struct {
client *rpc.Client2
}
// New new a question service.
func New(c *rpc.ClientConfig) (s *Service) {
s = &Service{
client: rpc.NewDiscoveryCli("passport.service.auth", c),
}
return
}
// DelTokenCache query token.
func (s *Service) DelTokenCache(c context.Context, token string) (err error) {
err = s.client.Call(c, _delTokenCache, token, &_noRes)
return
}
// DelCookieCookie del cookie.
func (s *Service) DelCookieCookie(c context.Context, session string) (err error) {
err = s.client.Call(c, _delCookieCache, session, &_noRes)
return
}

View File

@@ -0,0 +1,40 @@
package client
import (
"context"
"testing"
"time"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
)
func startRPCServer() {
s = New(nil)
}
func TestClient_DelTokenCache(t *testing.T) {
startRPCServer()
time.Sleep(3 * time.Second)
Convey("Test RPC client del token by token", t, func() {
var (
c = context.TODO()
ak = "64294c76972aee8cf4af51566c76ed0d"
)
err := s.DelTokenCache(c, ak)
So(err, ShouldBeNil)
})
}
func TestClient_DelCookieCookie(t *testing.T) {
startRPCServer()
time.Sleep(3 * time.Second)
Convey("Test RPC Client del cookie by cookie", t, func() {
sd := "1d0fb9cf,1,7f9745b6"
err := s.DelCookieCookie(context.TODO(), sd)
So(err, ShouldBeNil)
})
}

View File

@@ -0,0 +1,37 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["server.go"],
importpath = "go-common/app/service/main/passport-auth/rpc/grpc",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/passport-auth/api/grpc/v1:go_default_library",
"//app/service/main/passport-auth/service:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/metadata:go_default_library",
"//library/net/rpc/warden:go_default_library",
"@org_golang_google_grpc//:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,85 @@
// Package grpc server generate by warden_gen
package grpc
import (
"context"
"go-common/app/service/main/passport-auth/api/grpc/v1"
"go-common/app/service/main/passport-auth/service"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/net/metadata"
"go-common/library/net/rpc/warden"
"google.golang.org/grpc"
)
// New Auth warden rpc server
func New(cfg *warden.ServerConfig, s *service.Service) *warden.Server {
w := warden.NewServer(cfg)
v1.RegisterAuthServer(w.Server(), &server{s})
w.Use(func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
if resp, err = handler(ctx, req); err == nil {
log.Infov(ctx,
log.KV("path", info.FullMethod),
log.KV("caller", metadata.String(ctx, metadata.Caller)),
log.KV("args", req), log.KV("retVal", resp))
}
return
})
ws, err := w.Start()
if err != nil {
panic(err)
}
return ws
}
type server struct {
svr *service.Service
}
var _ v1.AuthServer = &server{}
var (
emptyCookieReply = &v1.GetCookieInfoReply{
IsLogin: false,
}
emptyTokenReply = &v1.GetTokenInfoReply{
IsLogin: false,
}
)
// CookieInfo verify user info by cookie.
func (s *server) GetCookieInfo(c context.Context, req *v1.GetCookieInfoReq) (*v1.GetCookieInfoReply, error) {
res, err := s.svr.CookieInfo(c, req.GetCookie())
if err != nil {
if err == ecode.NoLogin {
return emptyCookieReply, nil
}
return nil, err
}
return &v1.GetCookieInfoReply{
IsLogin: true,
Mid: res.Mid,
Expires: res.Expires,
Csrf: res.CSRF,
}, nil
}
// TokenInfo verify user info by accesskey.
func (s *server) GetTokenInfo(c context.Context, req *v1.GetTokenInfoReq) (*v1.GetTokenInfoReply, error) {
res, err := s.svr.TokenInfo(c, req.GetToken())
if err != nil {
if err == ecode.NoLogin {
return emptyTokenReply, nil
}
return nil, err
}
return &v1.GetTokenInfoReply{
IsLogin: true,
Mid: res.Mid,
Expires: res.Expires,
Csrf: res.CSRF,
}, nil
}

View File

@@ -0,0 +1,50 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["rpc_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/service/main/passport-auth/conf:go_default_library",
"//app/service/main/passport-auth/model:go_default_library",
"//app/service/main/passport-auth/service:go_default_library",
"//library/log:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["rpc.go"],
importpath = "go-common/app/service/main/passport-auth/rpc/server",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/passport-auth/conf:go_default_library",
"//app/service/main/passport-auth/service:go_default_library",
"//library/net/rpc:go_default_library",
"//library/net/rpc/context:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,40 @@
package server
import (
"go-common/app/service/main/passport-auth/conf"
"go-common/app/service/main/passport-auth/service"
"go-common/library/net/rpc"
"go-common/library/net/rpc/context"
)
// RPC rpc struct
type RPC struct {
s *service.Service
}
// New new rpc server.
func New(c *conf.Config, s *service.Service) (svr *rpc.Server) {
r := &RPC{s: s}
svr = rpc.NewServer(c.RPCServer)
if err := svr.Register(r); err != nil {
panic(err)
}
return
}
// Ping check connection success.
func (r *RPC) Ping(c context.Context, arg *struct{}, res *struct{}) (err error) {
return
}
// DelTokenCache query token
func (r *RPC) DelTokenCache(c context.Context, token string, res *struct{}) (err error) {
err = r.s.DelTokenCache(c, token)
return
}
// DelCookieCache del cookie
func (r *RPC) DelCookieCache(c context.Context, session string, res *struct{}) (err error) {
err = r.s.DelCookieCache(c, session)
return
}

View File

@@ -0,0 +1,115 @@
package server
import (
"net/rpc"
"sync"
"testing"
"time"
"go-common/app/service/main/passport-auth/conf"
"go-common/app/service/main/passport-auth/model"
"go-common/app/service/main/passport-auth/service"
"go-common/library/log"
. "github.com/smartystreets/goconvey/convey"
)
const (
addr = "127.0.0.1:7579"
_testPing = "RPC.Ping"
// token
_tokenInfo = "RPC.TokenInfo"
_delToken = "RPC.DelToken"
// cookie
_cookieInfo = "RPC.CookieInfo"
_delCookie = "RPC.DelCookie"
)
var (
_noArg = &struct{}{}
client *rpc.Client
once sync.Once
)
func startServer() {
if err := conf.Init(); err != nil {
panic(err)
}
log.Init(conf.Conf.Xlog)
defer log.Close()
svr := service.New(conf.Conf)
New(conf.Conf, svr)
time.Sleep(time.Second * 3)
var err error
client, err = rpc.Dial("tcp", addr)
if err != nil {
panic(err)
}
}
func TestRPC_Ping(t *testing.T) {
once.Do(startServer)
if err := client.Call(_testPing, &_noArg, &_noArg); err != nil {
t.Errorf("client.Call(%s) error(%v)", _testPing, err)
t.FailNow()
}
}
func TestRPC_TokenInfo(t *testing.T) {
var (
err error
arg = "64294c76972aee8cf4af51566c76ed0d"
res *model.Token
)
once.Do(startServer)
Convey("Test RPC server get token by token", t, func() {
err = client.Call(_tokenInfo, arg, res)
So(err, ShouldNotBeNil)
So(res, ShouldNotBeEmpty)
})
}
func TestRPC_DelToken(t *testing.T) {
var (
err error
arg = "64294c76972aee8cf4af51566c76ed0d"
res int64
)
once.Do(startServer)
time.Sleep(3 * time.Second)
Convey("Test RPC server del token by token", t, func() {
err = client.Call(_delToken, arg, res)
So(err, ShouldNotBeNil)
So(res, ShouldNotBeEmpty)
})
}
func TestRPC_CookieInfo(t *testing.T) {
var (
err error
arg = "c1300f65,1519273116,f05bd5ef"
res *model.Cookie
)
once.Do(startServer)
Convey("Test RPC server get coookie by ssda", t, func() {
err = client.Call(_cookieInfo, arg, res)
So(err, ShouldNotBeNil)
So(res, ShouldNotBeEmpty)
})
}
func TestRPC_DelCookie(t *testing.T) {
var (
err error
arg = "c1300f65,1519273116,f05bd5ef"
res int64
)
once.Do(startServer)
time.Sleep(3 * time.Second)
Convey("Test RPC server del coookie by cookie", t, func() {
err = client.Call(_delCookie, arg, res)
So(err, ShouldNotBeNil)
So(res, ShouldNotBeEmpty)
})
}

View File

@@ -0,0 +1,58 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"cookie_test.go",
"service_test.go",
"token_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/service/main/passport-auth/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"cookie.go",
"generate.go",
"md5.go",
"service.go",
"token.go",
],
importpath = "go-common/app/service/main/passport-auth/service",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/passport-auth/conf:go_default_library",
"//app/service/main/passport-auth/dao:go_default_library",
"//app/service/main/passport-auth/model:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,118 @@
package service
import (
"context"
"time"
"go-common/app/service/main/passport-auth/model"
)
const (
_newTokenHexLen = 32
_newTokenBinByteLen = 16
)
// CookieInfo verify user info by cookie.
func (s *Service) CookieInfo(c context.Context, sd string) (res *model.AuthReply, err error) {
var r *model.Cookie
if r, err = s.cookieInfo(c, sd); err != nil {
return
}
if r == nil || time.Now().Unix() > r.Expires {
res = _noLogin
return
}
res = &model.AuthReply{
Login: true,
Mid: r.Mid,
CSRF: r.CSRF,
Expires: r.Expires,
}
return
}
func (s *Service) cookieInfo(c context.Context, sd string) (res *model.Cookie, err error) {
cache := true
if res, err = s.d.CookieCache(c, sd); err != nil {
cache = false
} else if res != nil {
return
}
if s.c.ServiceConf.SupportOld {
res, err = s.cookieInfoFromDBOld(c, sd)
} else {
res, err = s.cookieInfoFromDBNew(c, sd)
}
if err != nil || !cache {
return
}
if res != nil {
s.addCache(func() {
s.d.SetCookieCache(context.TODO(), sd, res)
})
return
}
return
}
func (s *Service) cookieInfoFromDBNew(c context.Context, sd string) (res *model.Cookie, err error) {
now := time.Now()
delta, err := calcMonDelta(sd, now)
if err != nil {
return
}
// check delta
if delta > _expiresMonth {
return
}
ct := monDiff(now, -delta)
sdBytes, err := decodeSD(sd)
if err != nil {
return
}
res, sdb, err := s.d.Cookie(c, sdBytes, ct)
if err != nil {
return
}
res.Session = encodeSD(sdb)
return
}
func (s *Service) cookieInfoFromDBOld(c context.Context, sd string) (res *model.Cookie, err error) {
// cur month
sdBytes, err := decodeSD(sd)
if err != nil {
return
}
var sdb []byte
now := time.Now()
if res, sdb, err = s.d.Cookie(c, sdBytes, now); err != nil || res != nil {
res.Session = encodeSD(sdb)
return
}
// last month
if res, sdb, err = s.d.Cookie(c, sdBytes, monDiff(now, -1)); err != nil || res != nil {
res.Session = encodeSD(sdb)
return
}
return
}
func decodeSD(sd string) (res []byte, err error) {
// if is new sd
if len(sd) == _newTokenHexLen {
return hexDecode(sd)
}
// else if is old sd
return []byte(sd), nil
}
func encodeSD(b []byte) (s string) {
// format new
if len(b) == _newTokenBinByteLen {
return hexEncode(b)
}
// or format old
return string(b)
}

View File

@@ -0,0 +1,50 @@
package service
import (
"context"
"encoding/json"
. "github.com/smartystreets/goconvey/convey"
"testing"
)
func TestService_SDConvert(t *testing.T) {
Convey("test convert sd", t, func() {
Convey("new sd encode and decode", func() {
// decode
sd := "25ded96af42eb61677730d0a74eb4c51"
sdb, err := decodeSD(sd)
So(err, ShouldBeNil)
So(len(sdb), ShouldEqual, _newTokenBinByteLen)
// encode
s := encodeSD(sdb)
So(s, ShouldEqual, sd)
})
Convey("old sd encode and decode", func() {
// decode
sd := "396c38bb,1519380539,d73804f2"
sdb, err := decodeSD(sd)
So(err, ShouldBeNil)
So(len(sdb), ShouldEqual, 16+2+10)
// encode
s := encodeSD(sdb)
So(s, ShouldEqual, sd)
})
})
}
func TestService_CookieInfo(t *testing.T) {
once.Do(startService)
Convey("Test Query Token", t, func() {
sd := "396c38bb,1519380539,d73804f2"
res, err := s.cookieInfo(context.TODO(), sd)
So(err, ShouldBeNil)
So(res, ShouldNotBeEmpty)
So(res.Session, ShouldEqual, sd)
str, _ := json.Marshal(res)
t.Logf("res: %s", str)
})
}

View File

@@ -0,0 +1,42 @@
package service
import (
"strconv"
"time"
)
func calcMonDelta(ak string, now time.Time) (res int, err error) {
var parsedMon int
if parsedMon, err = parseMonth(ak); err != nil {
return
}
curMon := int(now.Month())
// check if cur mon
if curMon == parsedMon {
return 0, nil
}
delta := curMon - parsedMon
if delta < 0 {
delta += 12
}
return delta, nil
}
func monDiff(t time.Time, delta int) time.Time {
if delta == 0 {
return t
}
year, month, _ := t.Date()
thisMonthFirstDay := time.Date(year, month, 1, 1, 1, 1, 1, t.Location())
return thisMonthFirstDay.AddDate(0, delta, 0)
}
func parseMonth(ak string) (int, error) {
n, err := strconv.ParseInt(ak[30:31], 16, 64)
if err != nil {
return 0, err
}
return int(n), nil
}

View File

@@ -0,0 +1,13 @@
package service
import (
"encoding/hex"
)
func hexEncode(b []byte) string {
return hex.EncodeToString(b)
}
func hexDecode(s string) (res []byte, err error) {
return hex.DecodeString(s)
}

View File

@@ -0,0 +1,60 @@
package service
import (
"context"
"go-common/app/service/main/passport-auth/conf"
"go-common/app/service/main/passport-auth/dao"
"go-common/app/service/main/passport-auth/model"
"go-common/library/log"
)
var (
_noLogin = &model.AuthReply{
Login: false,
}
)
// Service struct of service
type Service struct {
c *conf.Config
d *dao.Dao
missch chan func()
}
// New create new service
func New(c *conf.Config) (s *Service) {
s = &Service{
c: c,
d: dao.New(c),
missch: make(chan func(), 1024),
}
go s.cacheproc()
return
}
// Ping check server ok.
func (s *Service) Ping(c context.Context) (err error) {
return s.d.Ping(c)
}
// Close dao.
func (s *Service) Close() {
s.d.Close()
}
func (s *Service) addCache(f func()) {
select {
case s.missch <- f:
default:
log.Warn("cacheproc chan full")
}
}
// cacheproc is a routine for executing closure.
func (s *Service) cacheproc() {
for {
f := <-s.missch
f()
}
}

View File

@@ -0,0 +1,20 @@
package service
import (
"sync"
"go-common/app/service/main/passport-auth/conf"
)
var (
once sync.Once
s *Service
)
func startService() {
if err := conf.Init(); err != nil {
panic(err)
}
// service init
s = New(conf.Conf)
}

View File

@@ -0,0 +1,169 @@
package service
import (
"context"
"time"
"go-common/app/service/main/passport-auth/model"
"go-common/library/ecode"
)
const (
_expiresMonth = 1
_refreshExpiresMonth = 2
)
// RefreshInfo refreshToken by refreshToken
func (s *Service) RefreshInfo(c context.Context, rk string) (res *model.Refresh, err error) {
return s.refreshInfo(c, rk)
}
// TokenInfo verify user info by accesskey.
func (s *Service) TokenInfo(c context.Context, ak string) (res *model.AuthReply, err error) {
var r *model.Token
if r, err = s.tokenInfo(c, ak); err != nil {
return
}
if r == nil || time.Now().Unix() > r.Expires {
res = _noLogin
return
}
res = &model.AuthReply{
Login: true,
Mid: r.Mid,
Expires: r.Expires,
}
return
}
// OldTokenInfo get old token info by accesskey.
func (s *Service) OldTokenInfo(c context.Context, ak string) (res *model.Token, err error) {
return s.tokenInfo(c, ak)
}
// DelTokenCache del mc cache
func (s *Service) DelTokenCache(c context.Context, ak string) (err error) {
return s.d.DelTokenCache(c, ak)
}
// DelCookieCache del mc cache
func (s *Service) DelCookieCache(c context.Context, session string) (err error) {
return s.d.DelCookieCache(c, session)
}
func (s *Service) refreshInfo(c context.Context, rk string) (res *model.Refresh, err error) {
// load from db
if s.c.ServiceConf.SupportOld {
res, err = s.refreshInfoFromDBOld(c, rk)
} else {
res, err = s.refreshInfoFromDBNew(c, rk)
}
return
}
func (s *Service) refreshInfoFromDBNew(c context.Context, rk string) (res *model.Refresh, err error) {
now := time.Now()
delta, err := calcMonDelta(rk, now)
if err != nil {
return
}
// check delta
if delta > _refreshExpiresMonth {
return
}
ct := monDiff(now, -delta)
rkBytes, err := hexDecode(rk)
if err != nil {
return
}
res, err = s.d.Refresh(c, rkBytes, ct)
return
}
func (s *Service) refreshInfoFromDBOld(c context.Context, rk string) (res *model.Refresh, err error) {
// cur month
now := time.Now()
rkBytes, err := hexDecode(rk)
if err != nil {
return
}
if res, err = s.d.Refresh(c, rkBytes, now); err != nil || res != nil {
return
}
// last one
if res, err = s.d.Refresh(c, rkBytes, monDiff(now, -1)); err != nil || res != nil {
return
}
// last two
res, err = s.d.Refresh(c, rkBytes, monDiff(now, -2))
return
}
func (s *Service) tokenInfo(c context.Context, ak string) (res *model.Token, err error) {
cache := true
if res, err = s.d.TokenCache(c, ak); err != nil {
cache = false
} else if res != nil {
return
}
if s.c.ServiceConf.SupportOld {
res, err = s.tokenInfoFromDBOld(c, ak)
} else {
res, err = s.tokenInfoFromDBNew(c, ak)
}
if err != nil || !cache {
return
}
if res != nil {
s.addCache(func() {
s.d.SetTokenCache(context.TODO(), ak, res)
})
return
}
return
}
func (s *Service) tokenInfoFromDBNew(c context.Context, ak string) (res *model.Token, err error) {
now := time.Now()
delta, err := calcMonDelta(ak, now)
if err != nil {
return
}
// check delta
if delta > _expiresMonth {
return
}
ct := monDiff(now, -delta)
tokenBytes, err := hexDecode(ak)
if err != nil {
err = ecode.RequestErr
return
}
res, err = s.d.Token(c, tokenBytes, ct)
return
}
func (s *Service) tokenInfoFromDBOld(c context.Context, ak string) (res *model.Token, err error) {
// cur month
now := time.Now()
tokenBytes, err := hexDecode(ak)
if err != nil {
return
}
if res, err = s.d.Token(c, tokenBytes, now); err != nil || res != nil {
return
}
// last one
if res, err = s.d.Token(c, tokenBytes, monDiff(now, -1)); err != nil || res != nil {
return
}
// last two
res, err = s.d.Token(c, tokenBytes, monDiff(now, -2))
return
}

View File

@@ -0,0 +1,32 @@
package service
import (
"context"
"encoding/json"
"testing"
"time"
. "github.com/smartystreets/goconvey/convey"
)
func TestNew(t *testing.T) {
Convey("test tmp", t, func() {
Convey("get month int", func() {
So(int(time.Unix(1526980273, 0).Month()), ShouldEqual, 5)
})
})
}
func TestService_TokenInfo(t *testing.T) {
once.Do(startService)
Convey("Test Query Token", t, func() {
token := "2ee11df3a6ba1b7f04a5a15336c2a051"
res, err := s.tokenInfo(context.TODO(), token)
So(err, ShouldBeNil)
So(res.Token, ShouldEqual, token)
str, _ := json.Marshal(res)
t.Logf("res: %s", str)
})
}