342 lines
8.0 KiB
Go
342 lines
8.0 KiB
Go
|
package auth
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"context"
|
||
|
"fmt"
|
||
|
"mime/multipart"
|
||
|
"net/http"
|
||
|
"net/url"
|
||
|
"testing"
|
||
|
"time"
|
||
|
|
||
|
"go-common/library/ecode"
|
||
|
"go-common/library/log"
|
||
|
bm "go-common/library/net/http/blademaster"
|
||
|
"go-common/library/net/metadata"
|
||
|
"go-common/library/net/netutil/breaker"
|
||
|
"go-common/library/net/rpc/warden"
|
||
|
xtime "go-common/library/time"
|
||
|
|
||
|
"github.com/stretchr/testify/assert"
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
_testUID = "2231365"
|
||
|
)
|
||
|
|
||
|
type Response struct {
|
||
|
Code int `json:"code"`
|
||
|
Data string `json:"data"`
|
||
|
}
|
||
|
|
||
|
func init() {
|
||
|
log.Init(&log.Config{
|
||
|
Stdout: true,
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func client() *bm.Client {
|
||
|
return bm.NewClient(&bm.ClientConfig{
|
||
|
App: &bm.App{
|
||
|
Key: "53e2fa226f5ad348",
|
||
|
Secret: "3cf6bd1b0ff671021da5f424fea4b04a",
|
||
|
},
|
||
|
Dial: xtime.Duration(time.Second),
|
||
|
Timeout: xtime.Duration(time.Second),
|
||
|
KeepAlive: xtime.Duration(time.Second * 10),
|
||
|
Breaker: &breaker.Config{
|
||
|
Window: xtime.Duration(time.Second),
|
||
|
Sleep: xtime.Duration(time.Millisecond * 100),
|
||
|
Bucket: 10,
|
||
|
Ratio: 0.5,
|
||
|
Request: 100,
|
||
|
},
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func create() *Auth {
|
||
|
return New(&Config{
|
||
|
Identify: &warden.ClientConfig{},
|
||
|
DisableCSRF: false,
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func engine() *bm.Engine {
|
||
|
e := bm.NewServer(nil)
|
||
|
authn := create()
|
||
|
e.GET("/user", authn.User, func(ctx *bm.Context) {
|
||
|
mid, _ := ctx.Get("mid")
|
||
|
ctx.JSON(fmt.Sprintf("%d", mid), nil)
|
||
|
})
|
||
|
e.GET("/metadata/user", authn.User, func(ctx *bm.Context) {
|
||
|
mid := metadata.Value(ctx, metadata.Mid)
|
||
|
ctx.JSON(fmt.Sprintf("%d", mid.(int64)), nil)
|
||
|
})
|
||
|
e.GET("/mobile", authn.UserMobile, func(ctx *bm.Context) {
|
||
|
mid, _ := ctx.Get("mid")
|
||
|
ctx.JSON(fmt.Sprintf("%d", mid), nil)
|
||
|
})
|
||
|
e.GET("/metadata/mobile", authn.UserMobile, func(ctx *bm.Context) {
|
||
|
mid := metadata.Value(ctx, metadata.Mid)
|
||
|
ctx.JSON(fmt.Sprintf("%d", mid.(int64)), nil)
|
||
|
})
|
||
|
e.GET("/web", authn.UserWeb, func(ctx *bm.Context) {
|
||
|
mid, _ := ctx.Get("mid")
|
||
|
ctx.JSON(fmt.Sprintf("%d", mid), nil)
|
||
|
})
|
||
|
e.GET("/guest", authn.Guest, func(ctx *bm.Context) {
|
||
|
var (
|
||
|
mid int64
|
||
|
)
|
||
|
if _mid, ok := ctx.Get("mid"); ok {
|
||
|
mid, _ = _mid.(int64)
|
||
|
}
|
||
|
ctx.JSON(fmt.Sprintf("%d", mid), nil)
|
||
|
})
|
||
|
e.GET("/guest/web", authn.GuestWeb, func(ctx *bm.Context) {
|
||
|
var (
|
||
|
mid int64
|
||
|
)
|
||
|
if _mid, ok := ctx.Get("mid"); ok {
|
||
|
mid, _ = _mid.(int64)
|
||
|
}
|
||
|
ctx.JSON(fmt.Sprintf("%d", mid), nil)
|
||
|
})
|
||
|
e.GET("/guest/mobile", authn.GuestMobile, func(ctx *bm.Context) {
|
||
|
var (
|
||
|
mid int64
|
||
|
)
|
||
|
if _mid, ok := ctx.Get("mid"); ok {
|
||
|
mid, _ = _mid.(int64)
|
||
|
}
|
||
|
ctx.JSON(fmt.Sprintf("%d", mid), nil)
|
||
|
})
|
||
|
e.POST("/guest/csrf", authn.Guest, func(ctx *bm.Context) {
|
||
|
var (
|
||
|
mid int64
|
||
|
)
|
||
|
if _mid, ok := ctx.Get("mid"); ok {
|
||
|
mid, _ = _mid.(int64)
|
||
|
}
|
||
|
ctx.JSON(fmt.Sprintf("%d", mid), nil)
|
||
|
})
|
||
|
return e
|
||
|
}
|
||
|
|
||
|
func TestFromNilConfig(t *testing.T) {
|
||
|
New(nil)
|
||
|
}
|
||
|
|
||
|
func TestIdentifyHandler(t *testing.T) {
|
||
|
e := engine()
|
||
|
go e.Run(":18080")
|
||
|
|
||
|
time.Sleep(time.Second)
|
||
|
|
||
|
// test cases
|
||
|
testWebUser(t, "/user")
|
||
|
testWebUser(t, "/metadata/user")
|
||
|
testWebUser(t, "/web")
|
||
|
testWebUser(t, "/guest")
|
||
|
testWebUser(t, "/guest/web")
|
||
|
testWebUserFailed(t, "/user")
|
||
|
testWebUserFailed(t, "/web")
|
||
|
|
||
|
testMobileUser(t, "/user")
|
||
|
testMobileUser(t, "/mobile")
|
||
|
testMobileUser(t, "/metadata/mobile")
|
||
|
testMobileUser(t, "/guest")
|
||
|
testMobileUser(t, "/guest/mobile")
|
||
|
testMobileUserFailed(t, "/user")
|
||
|
testMobileUserFailed(t, "/mobile")
|
||
|
|
||
|
testGuest(t, "/guest")
|
||
|
testGuestCSRF(t, "/guest/csrf")
|
||
|
testGuestCSRFFailed(t, "/guest/csrf")
|
||
|
testMultipartCSRF(t, "/guest/csrf")
|
||
|
|
||
|
if err := e.Server().Shutdown(context.TODO()); err != nil {
|
||
|
t.Logf("Failed to shutdown bm engine: %v", err)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func testWebUser(t *testing.T, path string) {
|
||
|
res := Response{}
|
||
|
query := url.Values{}
|
||
|
cli := client()
|
||
|
req, err := cli.NewRequest(http.MethodGet, "http://127.0.0.1:18080/"+path, "", query)
|
||
|
assert.NoError(t, err)
|
||
|
|
||
|
req.AddCookie(&http.Cookie{
|
||
|
Name: "DedeUserID",
|
||
|
Value: _testUID,
|
||
|
})
|
||
|
req.AddCookie(&http.Cookie{
|
||
|
Name: "DedeUserID__ckMd5",
|
||
|
Value: "36976f7a5cb6e4a6",
|
||
|
})
|
||
|
req.AddCookie(&http.Cookie{
|
||
|
Name: "SESSDATA",
|
||
|
Value: "7bf20cf0%2C1540627371%2C8ec39f0c",
|
||
|
})
|
||
|
|
||
|
err = cli.Do(context.TODO(), req, &res)
|
||
|
assert.NoError(t, err)
|
||
|
|
||
|
assert.Equal(t, 0, res.Code)
|
||
|
assert.Equal(t, _testUID, res.Data)
|
||
|
}
|
||
|
|
||
|
func testMobileUser(t *testing.T, path string) {
|
||
|
res := Response{}
|
||
|
query := url.Values{}
|
||
|
query.Set("access_key", "cdbd166be6673a5a4f6fbcdd88569edf")
|
||
|
cli := client()
|
||
|
req, err := cli.NewRequest(http.MethodGet, "http://127.0.0.1:18080"+path, "", query)
|
||
|
assert.NoError(t, err)
|
||
|
|
||
|
err = cli.Do(context.TODO(), req, &res)
|
||
|
assert.NoError(t, err)
|
||
|
|
||
|
assert.Equal(t, 0, res.Code)
|
||
|
assert.Equal(t, _testUID, res.Data)
|
||
|
}
|
||
|
|
||
|
func testWebUserFailed(t *testing.T, path string) {
|
||
|
res := Response{}
|
||
|
query := url.Values{}
|
||
|
cli := client()
|
||
|
req, err := cli.NewRequest(http.MethodGet, "http://127.0.0.1:18080/"+path, "", query)
|
||
|
assert.NoError(t, err)
|
||
|
|
||
|
req.AddCookie(&http.Cookie{
|
||
|
Name: "DedeUserID",
|
||
|
Value: _testUID,
|
||
|
})
|
||
|
req.AddCookie(&http.Cookie{
|
||
|
Name: "DedeUserID__ckMd5",
|
||
|
Value: "53c4b106fb4462f1",
|
||
|
})
|
||
|
req.AddCookie(&http.Cookie{
|
||
|
Name: "SESSDATA",
|
||
|
Value: "6eeda532%2C1515837495%2C5a6baa4e",
|
||
|
})
|
||
|
|
||
|
err = cli.Do(context.TODO(), req, &res)
|
||
|
assert.NoError(t, err)
|
||
|
|
||
|
assert.Equal(t, ecode.NoLogin.Code(), res.Code)
|
||
|
assert.Empty(t, res.Data)
|
||
|
}
|
||
|
|
||
|
func testMobileUserFailed(t *testing.T, path string) {
|
||
|
res := Response{}
|
||
|
query := url.Values{}
|
||
|
query.Set("access_key", "5dce488c2ff8d62d7b131da40ae18729")
|
||
|
cli := client()
|
||
|
req, err := cli.NewRequest(http.MethodGet, "http://127.0.0.1:18080"+path, "", query)
|
||
|
assert.NoError(t, err)
|
||
|
|
||
|
err = cli.Do(context.TODO(), req, &res)
|
||
|
assert.NoError(t, err)
|
||
|
|
||
|
assert.Equal(t, ecode.NoLogin.Code(), res.Code)
|
||
|
assert.Empty(t, res.Data)
|
||
|
}
|
||
|
|
||
|
func testGuest(t *testing.T, path string) {
|
||
|
res := Response{}
|
||
|
cli := client()
|
||
|
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:18080"+path, nil)
|
||
|
assert.NoError(t, err)
|
||
|
|
||
|
err = cli.Do(context.TODO(), req, &res)
|
||
|
assert.NoError(t, err)
|
||
|
|
||
|
assert.Equal(t, 0, res.Code)
|
||
|
assert.Equal(t, "0", res.Data)
|
||
|
}
|
||
|
|
||
|
func testGuestCSRF(t *testing.T, path string) {
|
||
|
res := Response{}
|
||
|
param := url.Values{}
|
||
|
param.Set("csrf", "c1524bbf3aa5a1996ff7b1f29a09e796")
|
||
|
cli := client()
|
||
|
req, err := cli.NewRequest(http.MethodPost, "http://127.0.0.1:18080"+path, "", param)
|
||
|
assert.NoError(t, err)
|
||
|
|
||
|
req.AddCookie(&http.Cookie{
|
||
|
Name: "DedeUserID",
|
||
|
Value: _testUID,
|
||
|
})
|
||
|
req.AddCookie(&http.Cookie{
|
||
|
Name: "DedeUserID__ckMd5",
|
||
|
Value: "36976f7a5cb6e4a6",
|
||
|
})
|
||
|
req.AddCookie(&http.Cookie{
|
||
|
Name: "SESSDATA",
|
||
|
Value: "7bf20cf0%2C1540627371%2C8ec39f0c",
|
||
|
})
|
||
|
err = cli.Do(context.TODO(), req, &res)
|
||
|
assert.NoError(t, err)
|
||
|
|
||
|
assert.Equal(t, 0, res.Code)
|
||
|
assert.Equal(t, _testUID, res.Data)
|
||
|
}
|
||
|
|
||
|
func testGuestCSRFFailed(t *testing.T, path string) {
|
||
|
res := Response{}
|
||
|
param := url.Values{}
|
||
|
param.Set("csrf", "invalid-csrf-token")
|
||
|
cli := client()
|
||
|
req, err := cli.NewRequest(http.MethodPost, "http://127.0.0.1:18080"+path, "", param)
|
||
|
assert.NoError(t, err)
|
||
|
|
||
|
req.AddCookie(&http.Cookie{
|
||
|
Name: "DedeUserID",
|
||
|
Value: _testUID,
|
||
|
})
|
||
|
req.AddCookie(&http.Cookie{
|
||
|
Name: "DedeUserID__ckMd5",
|
||
|
Value: "36976f7a5cb6e4a6",
|
||
|
})
|
||
|
req.AddCookie(&http.Cookie{
|
||
|
Name: "SESSDATA",
|
||
|
Value: "7bf20cf0%2C1540627371%2C8ec39f0c",
|
||
|
})
|
||
|
err = cli.Do(context.TODO(), req, &res)
|
||
|
assert.NoError(t, err)
|
||
|
|
||
|
assert.Equal(t, ecode.CsrfNotMatchErr.Code(), res.Code)
|
||
|
assert.Empty(t, res.Data)
|
||
|
}
|
||
|
|
||
|
func testMultipartCSRF(t *testing.T, path string) {
|
||
|
res := Response{}
|
||
|
body := &bytes.Buffer{}
|
||
|
writer := multipart.NewWriter(body)
|
||
|
writer.WriteField("csrf", "c1524bbf3aa5a1996ff7b1f29a09e796")
|
||
|
writer.Close()
|
||
|
req, err := http.NewRequest("POST", "http://127.0.0.1:18080"+path, body)
|
||
|
assert.NoError(t, err)
|
||
|
req.Header.Set("Content-Type", writer.FormDataContentType())
|
||
|
cli := client()
|
||
|
req.AddCookie(&http.Cookie{
|
||
|
Name: "DedeUserID",
|
||
|
Value: _testUID,
|
||
|
})
|
||
|
req.AddCookie(&http.Cookie{
|
||
|
Name: "DedeUserID__ckMd5",
|
||
|
Value: "36976f7a5cb6e4a6",
|
||
|
})
|
||
|
req.AddCookie(&http.Cookie{
|
||
|
Name: "SESSDATA",
|
||
|
Value: "7bf20cf0%2C1540627371%2C8ec39f0c",
|
||
|
})
|
||
|
err = cli.Do(context.TODO(), req, &res)
|
||
|
assert.NoError(t, err)
|
||
|
assert.Equal(t, 0, res.Code)
|
||
|
assert.Equal(t, _testUID, res.Data)
|
||
|
}
|