Skip to content

Commit

Permalink
feat: sign of file
Browse files Browse the repository at this point in the history
  • Loading branch information
xhofe committed Jun 28, 2022
1 parent 5dbf5db commit d89ec89
Show file tree
Hide file tree
Showing 8 changed files with 122 additions and 10 deletions.
1 change: 1 addition & 0 deletions internal/bootstrap/data/setting.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ func initialSettings() {
{Key: "global_readme", Value: "This is global readme", Type: conf.TypeText, Group: model.GLOBAL},
{Key: "customize_head", Type: conf.TypeText, Group: model.GLOBAL, Flag: model.PRIVATE},
{Key: "customize_body", Type: conf.TypeText, Group: model.GLOBAL, Flag: model.PRIVATE},
{Key: "link_expiration", Value: "4", Type: conf.TypeNumber, Group: model.GLOBAL, Flag: model.PRIVATE},
// single settings
{Key: "token", Value: token, Type: conf.TypeString, Group: model.SINGLE, Flag: model.PRIVATE},
}
Expand Down
30 changes: 30 additions & 0 deletions internal/sign/sign.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package sign

import (
"github.com/alist-org/alist/v3/internal/setting"
"github.com/alist-org/alist/v3/pkg/sign"
"sync"
"time"
)

var once sync.Once
var instance sign.Sign

func WithDuration(data string, d time.Duration) string {
once.Do(Instance)
return instance.Sign(data, time.Now().Add(d).Unix())
}

func NotExpired(data string) string {
once.Do(Instance)
return instance.Sign(data, 0)
}

func Verify(data string, sign string) error {
once.Do(Instance)
return instance.Verify(data, sign)
}

func Instance() {
instance = sign.NewHMACSign([]byte(setting.GetByKey("token")))
}
52 changes: 52 additions & 0 deletions pkg/sign/hmac.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package sign

import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"io"
"strconv"
"strings"
"time"
)

type HMACSign struct {
SecretKey []byte
}

func (s HMACSign) Sign(data string, expire int64) string {
h := hmac.New(sha256.New, s.SecretKey)
expireTimeStamp := strconv.FormatInt(expire, 10)
_, err := io.WriteString(h, data+":"+expireTimeStamp)
if err != nil {
return ""
}

return base64.URLEncoding.EncodeToString(h.Sum(nil)) + ":" + expireTimeStamp
}

func (s HMACSign) Verify(data, sign string) error {
signSlice := strings.Split(sign, ":")
// check whether contains expire time
if signSlice[len(signSlice)-1] == "" {
return ErrExpireMissing
}
// check whether expire time is expired
expires, err := strconv.ParseInt(signSlice[len(signSlice)-1], 10, 64)
if err != nil {
return ErrExpireInvalid
}
// if expire time is expired, return error
if expires < time.Now().Unix() && expires != 0 {
return ErrSignExpired
}
// verify sign
if s.Sign(data, expires) != sign {
return ErrSignInvalid
}
return nil
}

func NewHMACSign(secret []byte) Sign {
return HMACSign{SecretKey: secret}
}
15 changes: 15 additions & 0 deletions pkg/sign/sign.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package sign

import "errors"

type Sign interface {
Sign(data string, expire int64) string
Verify(data, sign string) error
}

var (
ErrSignExpired = errors.New("sign expired")
ErrSignInvalid = errors.New("sign invalid")
ErrExpireInvalid = errors.New("expire invalid")
ErrExpireMissing = errors.New("expire missing")
)
11 changes: 6 additions & 5 deletions server/controllers/fsget.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,18 @@ func FsGet(c *gin.Context) {
common.ErrorStrResp(c, "password is incorrect", 401)
return
}
data, err := fs.Get(c, req.Path)
obj, err := fs.Get(c, req.Path)
if err != nil {
common.ErrorResp(c, err, 500, true)
return
}
common.SuccessResp(c, FsGetResp{
ObjResp: ObjResp{
Name: data.GetName(),
Size: data.GetSize(),
IsDir: data.IsDir(),
Modified: data.ModTime(),
Name: obj.GetName(),
Size: obj.GetSize(),
IsDir: obj.IsDir(),
Modified: obj.ModTime(),
Sign: Sign(obj),
},
// TODO: set raw url
})
Expand Down
19 changes: 15 additions & 4 deletions server/controllers/fslist.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package controllers

import (
"fmt"
"github.com/alist-org/alist/v3/internal/db"
"github.com/alist-org/alist/v3/internal/fs"
"github.com/alist-org/alist/v3/internal/model"
"github.com/alist-org/alist/v3/internal/setting"
"github.com/alist-org/alist/v3/internal/sign"
"github.com/alist-org/alist/v3/pkg/utils"
"github.com/alist-org/alist/v3/server/common"
"github.com/gin-gonic/gin"
Expand All @@ -24,7 +24,7 @@ type ObjResp struct {
Size int64 `json:"size"`
IsDir bool `json:"is_dir"`
Modified time.Time `json:"modified"`
URL string `json:"url"`
Sign string `json:"sign"`
}

type FsListResp struct {
Expand Down Expand Up @@ -99,9 +99,20 @@ func toObjResp(objs []model.Obj, path string, baseURL string) []ObjResp {
Size: obj.GetSize(),
IsDir: obj.IsDir(),
Modified: obj.ModTime(),
// TODO: sign url
URL: fmt.Sprintf("%s/d%s", baseURL, stdpath.Join(path, obj.GetName())),
Sign: Sign(obj),
})
}
return resp
}

func Sign(obj model.Obj) string {
if obj.IsDir() {
return ""
}
expire := setting.GetIntSetting("link_expiration", 0)
if expire == 0 {
return sign.NotExpired(obj.GetName())
} else {
return sign.WithDuration(obj.GetName(), time.Duration(expire)*time.Hour)
}
}
2 changes: 2 additions & 0 deletions server/controllers/setting.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"github.com/alist-org/alist/v3/internal/conf"
"github.com/alist-org/alist/v3/internal/db"
"github.com/alist-org/alist/v3/internal/model"
"github.com/alist-org/alist/v3/internal/sign"
"github.com/alist-org/alist/v3/pkg/utils/random"
"github.com/alist-org/alist/v3/server/common"
"github.com/gin-gonic/gin"
Expand All @@ -17,6 +18,7 @@ func ResetToken(c *gin.Context) {
common.ErrorResp(c, err, 500)
return
}
sign.Instance()
common.SuccessResp(c, token)
}

Expand Down
2 changes: 1 addition & 1 deletion server/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func Init(r *gin.Engine) {
public := api.Group("/public")
public.GET("/settings", controllers.PublicSettings)
public.Any("/list", controllers.FsList)
public.GET("/get", controllers.FsGet)
public.Any("/get", controllers.FsGet)
}

func Cors(r *gin.Engine) {
Expand Down

0 comments on commit d89ec89

Please sign in to comment.