Feat: qiniu upload & callback

This commit is contained in:
HFO4
2020-01-15 10:14:15 +08:00
parent 5be7ec98c1
commit e8d21b1e9b
15 changed files with 356 additions and 71 deletions

View File

@@ -5,8 +5,10 @@ import (
"github.com/HFO4/cloudreve/pkg/auth"
"github.com/HFO4/cloudreve/pkg/cache"
"github.com/HFO4/cloudreve/pkg/serializer"
"github.com/HFO4/cloudreve/pkg/util"
"github.com/gin-contrib/sessions"
"github.com/gin-gonic/gin"
"github.com/qiniu/api.v7/v7/auth/qbox"
"net/http"
)
@@ -106,41 +108,45 @@ func WebDAVAuth() gin.HandlerFunc {
}
}
// uploadCallbackCheck 对上传回调请求的 callback key 进行验证,如果成功则返回上传用户
func uploadCallbackCheck(c *gin.Context) (serializer.Response, *model.User) {
// 验证 Callback Key
callbackKey := c.Param("key")
if callbackKey == "" {
return serializer.ParamErr("Callback Key 不能为空", nil), nil
}
callbackSessionRaw, exist := cache.Get("callback_" + callbackKey)
if !exist {
return serializer.ParamErr("回调会话不存在或已过期", nil), nil
}
callbackSession := callbackSessionRaw.(serializer.UploadSession)
c.Set("callbackSession", &callbackSession)
// 清理回调会话
_ = cache.Deletes([]string{callbackKey}, "callback_")
// 查找用户
user, err := model.GetUserByID(callbackSession.UID)
if err != nil {
return serializer.Err(serializer.CodeCheckLogin, "找不到用户", err), nil
}
c.Set("user", &user)
// 检查存储策略是否一致
if user.GetPolicyID() != callbackSession.PolicyID {
return serializer.Err(serializer.CodePolicyNotAllowed, "存储策略已变更,请重新上传", nil), nil
}
return serializer.Response{}, &user
}
// RemoteCallbackAuth 远程回调签名验证
// TODO 测试
func RemoteCallbackAuth() gin.HandlerFunc {
return func(c *gin.Context) {
// 验证 Callback Key
callbackKey := c.Param("key")
if callbackKey == "" {
c.JSON(200, serializer.ParamErr("Callback Key 不能为空", nil))
c.Abort()
return
}
callbackSessionRaw, exist := cache.Get("callback_" + callbackKey)
if !exist {
c.JSON(200, serializer.ParamErr("回调会话不存在或已过期", nil))
c.Abort()
return
}
callbackSession := callbackSessionRaw.(serializer.UploadSession)
c.Set("callbackSession", &callbackSession)
// 清理回调会话
_ = cache.Deletes([]string{callbackKey}, "callback_")
// 查找用户
user, err := model.GetUserByID(callbackSession.UID)
if err != nil {
c.JSON(200, serializer.Err(serializer.CodeCheckLogin, "找不到用户", err))
c.Abort()
return
}
c.Set("user", &user)
// 检查存储策略是否一致
if user.GetPolicyID() != callbackSession.PolicyID {
c.JSON(200, serializer.Err(serializer.CodePolicyNotAllowed, "存储策略已变更,请重新上传", nil))
// 验证key并查找用户
resp, user := uploadCallbackCheck(c)
if resp.Code != 0 {
c.JSON(200, resp)
c.Abort()
return
}
@@ -157,3 +163,34 @@ func RemoteCallbackAuth() gin.HandlerFunc {
}
}
// QiniuCallbackAuth 七牛回调签名验证
// TODO 测试
func QiniuCallbackAuth() gin.HandlerFunc {
return func(c *gin.Context) {
// 验证key并查找用户
resp, user := uploadCallbackCheck(c)
if resp.Code != 0 {
c.JSON(401, serializer.QiniuCallbackFailed{Error: resp.Msg})
c.Abort()
return
}
// 验证回调是否来自qiniu
mac := qbox.NewMac(user.Policy.AccessKey, user.Policy.SecretKey)
ok, err := mac.VerifyCallback(c.Request)
if err != nil {
util.Log().Debug("无法验证回调请求,%s", err)
c.JSON(401, serializer.QiniuCallbackFailed{Error: "无法验证回调请求"})
c.Abort()
return
}
if !ok {
c.JSON(401, serializer.QiniuCallbackFailed{Error: "回调签名无效"})
c.Abort()
return
}
c.Next()
}
}