engineercms分享文件提取码-参考蓝眼云盘
- 2020 年 3 月 6 日
- 笔记
因为蓝眼云盘也是采用go语言+gorm编写的,所以参考起来稍微轻松一点。主要还是了解如何通过一段提取码就能取到文件的访问权。
生成一个分享文件uuid和提取码code。服务端接受选择的文件或文件夹id,随机生成一个share uuid和提取码code,返回给页面:服务端写入数据表share和bridge,前者存share uuid和分享者id,及过期时间expiretime,还有是否永久有效。后者存储share uuid和对应的文件id,一对多。
用户通过这个链接地址,浏览器请求服务端,服务端判断用户有无登录——如果登录,再判断这个分享是不是这个登录用户创建。如果没登录,则需要提取码code。
当输入code后,服务根据share uuid,和code,通过读取share数据表,如果符合,则根据share uuid取出bridge里的文件列表
当用户全部打包下载,或下载其中一个,怎么处理逻辑呢?再通过share uuid和code做一次判断么?
// check whether shareUuid and shareCode matches. check whether user can access. func (this *ShareService) CheckShare(request *http.Request, shareUuid string, code string, user *User) *Share { share := this.shareDao.CheckByUuid(shareUuid) //if self, not need shareCode if user == nil || user.Uuid != share.UserUuid { //if not login or not self's share, shareCode is required. if code == "" { panic(result.CustomWebResultI18n(request, result.NEED_SHARE_CODE, i18n.ShareCodeRequired)) } else if share.Code != code { panic(result.CustomWebResultI18n(request, result.SHARE_CODE_ERROR, i18n.ShareCodeError)) } else { if !share.ExpireInfinity { if share.ExpireTime.Before(time.Now()) { panic(result.BadRequest("share expired")) } } } } return share }
如果是自己,就不需要提取码,不是自己的,或者没有登录,就判断提取码,如果有提取码,就和数据库中存的对比,如果正确,再判断有效期,如果是永远的,则不需要判断过期时间。如果不是永远有效的,则看看数据库里的过期时间跟当前时间对比。
上面的逻辑相当于通过认证后,提供给页面的文件或文件列表。
那么下载也差不多是这个逻辑,也是要判断code。
func (this *ShareController) Zip(writer http.ResponseWriter, request *http.Request) *result.WebResult { shareUuid := request.FormValue("shareUuid") code := request.FormValue("code") puuid := request.FormValue("puuid") rootUuid := request.FormValue("rootUuid") user := this.findUser(request) if puuid == MATTER_ROOT { //download all things. share := this.shareService.CheckShare(request, shareUuid, code, user) bridges := this.bridgeDao.FindByShareUuid(share.Uuid) var matterUuids []string for _, bridge := range bridges { matterUuids = append(matterUuids, bridge.MatterUuid) } matters := this.matterDao.FindByUuids(matterUuids, nil) this.matterService.DownloadZip(writer, request, matters) } else { //download a folder. matter := this.matterDao.CheckByUuid(puuid) this.shareService.ValidateMatter(request, shareUuid, code, user, rootUuid, matter) this.matterService.DownloadZip(writer, request, []*Matter{matter}) } return nil }
也是先要checkshare,然后再去bridge数据表里取出文件或文件的id……如果是文件夹,则用validatematter判断,也是一样的:
//check whether a user can access a matter. shareRootUuid is matter's parent(or parent's parent and so on) func (this *ShareService) ValidateMatter(request *http.Request, shareUuid string, code string, user *User, shareRootUuid string, matter *Matter) { if matter == nil { panic(result.Unauthorized("matter cannot be nil")) } //if self's matter, ok. if user != nil && matter.UserUuid == user.Uuid { return } if shareUuid == "" || code == "" || shareRootUuid == "" { panic(result.Unauthorized("shareUuid,code,shareRootUuid cannot be null")) } share := this.CheckShare(request, shareUuid, code, user) //if shareRootUuid is root. Bridge must has record. if shareRootUuid == MATTER_ROOT { this.bridgeDao.CheckByShareUuidAndMatterUuid(share.Uuid, matter.Uuid) } else { //check whether shareRootMatter is being sharing shareRootMatter := this.matterDao.CheckByUuid(shareRootUuid) this.bridgeDao.CheckByShareUuidAndMatterUuid(share.Uuid, shareRootMatter.Uuid) // shareRootMatter is ancestor of matter. child := strings.HasPrefix(matter.Path, shareRootMatter.Path) if !child { panic(result.BadRequest("%s is not %s's children", matter.Uuid, shareRootUuid)) } } }
也是要checkshare一下的。