Skip to content

Commit

Permalink
refactor proxy
Browse files Browse the repository at this point in the history
  • Loading branch information
Terry-Mao committed May 12, 2016
1 parent 77ba840 commit 9790024
Show file tree
Hide file tree
Showing 9 changed files with 355 additions and 267 deletions.
121 changes: 24 additions & 97 deletions proxy/auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,150 +2,77 @@ package auth

import (
"bfs/libs/errors"
ibucket "bfs/proxy/bucket"
"bfs/proxy/conf"
"crypto/hmac"
"crypto/sha1"
"encoding/base64"
"fmt"
log "github.com/golang/glog"
"hash"
"net/http"
"strconv"
"strings"
"time"
)

const (
// bucket acl
_statusReadBit = 0
_statusWriteBit = 1
//
_statusRead = 1 << _statusReadBit
_statusWrite = 1 << _statusWriteBit
//
_authExpire = 900 // s
_authExpire = 900 // 15min
_template = "%s\n%s\n%s\n%d\n" // method bucket filename expire
)

type Auth struct {
b map[string]Bucket
c *conf.Config
}

// NewAuth
func NewAuth(c *conf.Config) (a *Auth, err error) {
a = &Auth{}
a.c = c
a.b, err = InitBucket()
return
}

// CheckAuth
func (a *Auth) CheckAuth(r *http.Request) (err error) {
func (a *Auth) Authorize(item *ibucket.Item, method, bucket, file, token string) (err error) {
// token keyid:sign:time
var (
params = r.URL.Query()
ss []string
bucket string
filename string
token string
exist bool
expire int64
delta int64
now int64
keyId string
ss = strings.Split(token, ":")
)
if r.Method == "PUT" || r.Method == "DELETE" {
ss = strings.Split(r.URL.Path[1:], "/")
} else {
ss = strings.Split(strings.TrimPrefix(r.URL.Path, "/bfs")[1:], "/")
}
bucket = ss[0]
if _, exist = a.b[bucket]; !exist {
err = errors.ErrBucketNotExist
return
}
if !a.bucketNeedAuth(r.Method, bucket) {
return
}
filename = ss[len(ss)-1]
token = params.Get("token")
if token == "" {
token = r.Header.Get("Authorization")
}
if !a.reqAuth(r.Method, bucket, filename, token) {
log.Errorf("CheckAuth failed method: %s, bucket: %s, token: %s", r.Method, bucket, token)
err = errors.ErrAuthFailed
}
return
}

// Bucket need check authorization
func (a *Auth) bucketNeedAuth(method, bucket string) bool {
var (
property int
)
property = a.b[bucket].Property
if method == "GET" || method == "HEAD" {
if property&_statusRead == 0 {
return false
}
} else { // POST DELETE
if property&_statusWrite == 0 {
return false
}
}
return true
}

// auth
func (a *Auth) reqAuth(method, bucket, filename, token string) bool {
var (
err error
now int64
keyId string
keySecret string
expire int64
auth string
realAuth string
ss []string
)
ss = strings.Split(token, ":")
if len(ss) != 3 {
return false
return errors.ErrAuthFailed
}
keyId = ss[0]
if keyId != a.b[bucket].KeyId {
return false
if keyId != item.KeyId {
return errors.ErrAuthFailed
}
keySecret = a.b[bucket].KeySecret
auth = ss[1]
if expire, err = strconv.ParseInt(ss[2], 10, 64); err != nil {
return false
return errors.ErrAuthFailed
}
now = time.Now().Unix()
// > ±15 min is forbidden
if expire > now {
if expire-now > _authExpire {
return false
}
delta = expire - now
} else {
if now-expire > _authExpire {
return false
}
delta = now - expire
}
realAuth = a.createAuthorization(method, bucket, filename, expire, keySecret)
if auth != realAuth {
log.Errorf("auth failed: auth: %s realAuth: %s ", auth, realAuth)
return false
if delta > _authExpire {
return errors.ErrAuthFailed
}
return true
err = a.sign(ss[1], method, bucket, file, item.KeySecret, expire)
return
}

// createAuthorization
func (a *Auth) createAuthorization(method, bucket, filename string, expire int64, keySecret string) (auth string) {
func (a *Auth) sign(src, method, bucket, file, keySecret string, expire int64) (err error) {
var (
content string
mac hash.Hash
)
content = fmt.Sprintf(_template, method, bucket, filename, expire)
content = fmt.Sprintf(_template, method, bucket, file, expire)
mac = hmac.New(sha1.New, []byte(keySecret))
mac.Write([]byte(content))
auth = base64.StdEncoding.EncodeToString(mac.Sum(nil))
if base64.StdEncoding.EncodeToString(mac.Sum(nil)) != src {
return errors.ErrAuthFailed
}
return
}
30 changes: 0 additions & 30 deletions proxy/auth/bucket.go

This file was deleted.

8 changes: 6 additions & 2 deletions proxy/bfs/bfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ var (
}
return c, nil
},
DisableCompression: true,
}
_client = &http.Client{
Transport: _transport,
Expand Down Expand Up @@ -153,6 +154,7 @@ func (b *Bfs) Upload(bucket, filename, mine, sha1 string, buf []byte) (err error
if res.Ret == errors.RetNeedleExist {
err = errors.ErrNeedleExist
}
log.Infof("bfs.upload bucket:%s filename:%s key:%d cookie:%d vid:%d", bucket, filename, res.Key, res.Cookie, res.Vid)
return
}

Expand Down Expand Up @@ -216,6 +218,7 @@ func Http(method, uri string, params url.Values, buf []byte, res interface{}) (e
resp *http.Response
ru string
enc string
ctype string
)
enc = params.Encode()
if enc != "" {
Expand All @@ -236,19 +239,20 @@ func Http(method, uri string, params url.Values, buf []byte, res interface{}) (e
if bw, err = w.CreateFormFile("file", "1.jpg"); err != nil {
return
}
if _, err = io.WriteString(bw, string(buf)); err != nil {
if _, err = bw.Write(buf); err != nil {
return
}
for key, _ := range params {
w.WriteField(key, params.Get(key))
}
ctype = w.FormDataContentType()
if err = w.Close(); err != nil {
return
}
if req, err = http.NewRequest("POST", uri, bufdata); err != nil {
return
}
req.Header.Set("Content-Type", w.FormDataContentType())
req.Header.Set("Content-Type", ctype)
}
}
td := _timer.Start(5*time.Second, func() {
Expand Down
77 changes: 77 additions & 0 deletions proxy/bucket/bucket.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package bucket

import (
"bfs/libs/errors"
"fmt"
)

const (
// status bit
_privateReadBit = 0
_privateWriteBit = 1
// status
_public = int(0)
_privateRead = int(1 << _privateReadBit)
_privateWrite = int(1 << _privateWriteBit)
_privateReadWrite = int(_privateRead | _privateWrite)
)

// bucket_name property key_id key_secret
type Bucket struct {
data map[string]*Item
}

type Item struct {
Name string
KeyId string
KeySecret string
PurgeCDN bool

// property 第0位:读 (0表示共有,1表示私有) 第1位:写 (0表示共有,1表示私有)
property int
}

func (i *Item) String() string {
return fmt.Sprintf("{name: %s, purge: %s, property: %d}", i.Name, i.PurgeCDN, i.property)
}

func (i *Item) writePublic() bool {
return i.property&_privateWrite == 0
}

func (i *Item) readPublic() bool {
return i.property&_privateRead == 0
}

// Public check the item is public or not.
func (i *Item) Public(read bool) bool {
if read {
return i.readPublic()
}
return i.writePublic()
}

// NewBucket
func NewBucket() (b *Bucket, err error) {
var item *Item
b = new(Bucket)
b.data = make(map[string]*Item)
// bucket test
item = new(Item)
item.Name = "test"
item.property = _privateWrite
item.KeyId = "221bce6492eba70f"
item.KeySecret = "6eb80603e85842542f9736eb13b7e3"
item.PurgeCDN = false
b.data[item.Name] = item
return
}

// Get get a bucket, if not exist then error.
func (b *Bucket) Get(name string) (item *Item, err error) {
var ok bool
if item, ok = b.data[name]; !ok {
err = errors.ErrBucketNotExist
}
return
}
23 changes: 15 additions & 8 deletions proxy/conf/config.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package conf

import (
"github.com/BurntSushi/toml"
"io/ioutil"
"os"
"path"
"strings"
"time"

"github.com/BurntSushi/toml"
)

type Config struct {
Expand All @@ -17,14 +20,10 @@ type Config struct {
BfsAddr string
// download domain
Domain string
// location prefix
Prefix string
// file
MaxFileSize int
// aliyun
AliyunKeyId string
AliyunKeySecret string
// netcenter
NetUserName string
NetPasswd string
// purge channel
PurgeMaxSize int
}
Expand Down Expand Up @@ -53,6 +52,14 @@ func NewConfig(conf string) (c *Config, err error) {
if blob, err = ioutil.ReadAll(file); err != nil {
return
}
err = toml.Unmarshal(blob, c)
if err = toml.Unmarshal(blob, c); err != nil {
return
}
// http://domain/ covert to http://domain
c.Domain = strings.TrimRight(c.Domain, "/")
// bfs,/bfs,/bfs/ convert to /bfs/
if c.Prefix != "" {
c.Prefix = path.Join("/", c.Prefix) + "/"
}
return
}
Loading

0 comments on commit 9790024

Please sign in to comment.