Просмотр исходного кода

更新文件 url 加密相关数据和方法

reghao 3 лет назад
Родитель
Сommit
8f8dceb4af

+ 1 - 0
src/main/java/cn/reghao/dfs/store/config/DfsProperties.java

@@ -21,4 +21,5 @@ public class DfsProperties {
     private int node;
     // TODO 修改为 mountedDirs, 表示磁盘挂载的目录
     private List<String> baseDirs;
+    private String encryptKey;
 }

+ 14 - 0
src/main/java/cn/reghao/dfs/store/controller/FileController.java

@@ -1,5 +1,8 @@
 package cn.reghao.dfs.store.controller;
 
+import cn.reghao.dfs.api.dto.EncryptParam;
+import cn.reghao.dfs.api.dto.VideoUrlDto;
+import cn.reghao.dfs.store.rpc.MediaUrlServiceImpl;
 import cn.reghao.dfs.store.util.store.LocalStore;
 import cn.reghao.dfs.store.util.store.LocalStores;
 import cn.reghao.dfs.store.util.store.StoreDir;
@@ -8,6 +11,7 @@ import cn.reghao.dfs.store.db.repository.FileRepository;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import org.apache.ibatis.annotations.Param;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.MediaType;
 import org.springframework.web.bind.annotation.*;
 
@@ -49,4 +53,14 @@ public class FileController {
         List<StoreDir> list1 = LocalStores.getStoreDirs();
         return WebBody.success(list);
     }
+
+    @Autowired
+    MediaUrlServiceImpl mediaUrlService;
+    @GetMapping(value = "/geturl", produces = MediaType.APPLICATION_JSON_VALUE)
+    @Deprecated
+    public String getUrl() {
+        EncryptParam encryptParam = new EncryptParam("yPb1l5V6JN", "wKLx1Zpod6", -1L);
+        List<VideoUrlDto> list = mediaUrlService.getEncryptMp4Urls(encryptParam);
+        return WebBody.success(list);
+    }
 }

+ 56 - 2
src/main/java/cn/reghao/dfs/store/controller/VideoFileController.java

@@ -1,7 +1,12 @@
 package cn.reghao.dfs.store.controller;
 
+import cn.reghao.dfs.store.config.DfsProperties;
+import cn.reghao.dfs.store.db.mapper.FileUserMapper;
 import cn.reghao.dfs.store.model.dto.PathUrl;
+import cn.reghao.dfs.api.dto.FileAccess;
 import cn.reghao.dfs.store.service.FileUrlService;
+import cn.reghao.jutil.jdk.security.crypto.AesEncrypt;
+import cn.reghao.jutil.web.ServletUtil;
 import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletResponse;
@@ -20,15 +25,64 @@ import java.util.Arrays;
 @RequestMapping("/video")
 public class VideoFileController {
     private final FileUrlService fileUrlService;
+    private final FileUserMapper fileUserMapper;
+    private final String encryptKey;
 
-    public VideoFileController(FileUrlService fileUrlService) {
+    public VideoFileController(FileUrlService fileUrlService, FileUserMapper fileUserMapper,
+                               DfsProperties dfsProperties) {
         this.fileUrlService = fileUrlService;
+        this.fileUserMapper = fileUserMapper;
+        this.encryptKey = dfsProperties.getEncryptKey();
     }
 
     @GetMapping("/playback/{filename}")
-    public void videoPlayer(@PathVariable("filename") String filename, @RequestHeader(required = false) String range,
+    public void videoPlayer(@PathVariable("filename") String filename,
+                            @RequestHeader(required = false) String range,
+                            @RequestParam(value = "sign", required = false) String sign,
                             HttpServletResponse response) throws Exception {
         String uploadId = filename.split("\\.")[0];
+        FileAccess fileAccess = fileUserMapper.findFileAccessByUploadId(uploadId);
+        if (fileAccess == null) {
+            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
+            response.getOutputStream().write("".getBytes(StandardCharsets.UTF_8));
+            return;
+        }
+
+        if (!fileAccess.isActivate()) {
+            response.setStatus(HttpServletResponse.SC_FORBIDDEN);
+            response.getOutputStream().write("".getBytes(StandardCharsets.UTF_8));
+            return;
+        }
+
+        if (fileAccess.isAuth()) {
+            if (sign == null) {
+                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+                response.getOutputStream().write("".getBytes(StandardCharsets.UTF_8));
+                return;
+            }
+
+            String decryptSign = AesEncrypt.decrypt(sign, encryptKey);
+            String[] arr = decryptSign.split("_");
+            String key = arr[0];
+            long userId = Long.parseLong(arr[1]);
+            long timestamp = Long.parseLong(arr[2]);
+
+            Long accessUserId = ServletUtil.getUserId();
+            if (userId != accessUserId) {
+                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+                String errMsg = "url 不是为当前用户生成";
+                response.getOutputStream().write(errMsg.getBytes(StandardCharsets.UTF_8));
+                return;
+            }
+
+            if (timestamp < System.currentTimeMillis()) {
+                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+                String errMsg = "url 过期";
+                response.getOutputStream().write(errMsg.getBytes(StandardCharsets.UTF_8));
+                return;
+            }
+        }
+
         PathUrl pathUrl = fileUrlService.getPathUrl(uploadId);
         if (pathUrl == null) {
             response.setStatus(HttpServletResponse.SC_NOT_FOUND);

+ 5 - 2
src/main/java/cn/reghao/dfs/store/db/mapper/FileUserMapper.java

@@ -1,5 +1,6 @@
 package cn.reghao.dfs.store.db.mapper;
 
+import cn.reghao.dfs.api.dto.FileAccess;
 import cn.reghao.jutil.jdk.db.BaseMapper;
 import cn.reghao.dfs.store.model.po.FileInfo;
 import cn.reghao.dfs.store.model.po.FileUser;
@@ -12,9 +13,11 @@ import org.apache.ibatis.annotations.Param;
  */
 @Mapper
 public interface FileUserMapper extends BaseMapper<FileUser> {
-    void updateSetActivate(String uploadId);
+    void updateSetFileAccess(FileAccess fileAccess);
+    void updateSetNeedAuth(String uploadId);
+    void updateSetNotNeedAuth(String uploadId);
 
-    boolean isActivate(String uploadId);
+    FileAccess findFileAccessByUploadId(String uploadId);
     FileUser findByFileAndUserId(@Param("fileId") String fileId, @Param("userId") String userId);
     FileUser findByUploadAndUserId(@Param("uploadId") String uploadId, @Param("userId") String userId);
     FileInfo findFileInfoByUploadId(String uploadId);

+ 2 - 0
src/main/java/cn/reghao/dfs/store/model/po/FileUser.java

@@ -15,11 +15,13 @@ public class FileUser extends BaseObject<Integer> {
     private String fileId;
     private String uploadBy;
     private Boolean activate;
+    private Boolean auth;
 
     public FileUser(String uploadId, String fileId, String uploadBy) {
         this.uploadId = uploadId;
         this.fileId = fileId;
         this.uploadBy = uploadBy;
         this.activate = false;
+        this.auth = false;
     }
 }

+ 18 - 14
src/main/java/cn/reghao/dfs/store/rpc/MediaUrlServiceImpl.java

@@ -1,15 +1,16 @@
 package cn.reghao.dfs.store.rpc;
 
+import cn.reghao.dfs.api.dto.EncryptParam;
+import cn.reghao.dfs.api.dto.FileAccess;
 import cn.reghao.dfs.api.iface.MediaUrlService;
+import cn.reghao.dfs.store.config.DfsProperties;
 import cn.reghao.dfs.store.db.mapper.FileUserMapper;
 import cn.reghao.dfs.store.db.mapper.VideoUrlMapper;
 import cn.reghao.dfs.api.dto.VideoUrlDto;
-import cn.reghao.jutil.jdk.security.DigestUtil;
+import cn.reghao.jutil.jdk.security.crypto.AesEncrypt;
 import org.apache.dubbo.config.annotation.DubboService;
 import org.springframework.stereotype.Service;
 
-import java.nio.charset.StandardCharsets;
-import java.security.NoSuchAlgorithmException;
 import java.util.List;
 import java.util.Objects;
 import java.util.stream.Collectors;
@@ -21,10 +22,13 @@ import java.util.stream.Collectors;
 @DubboService
 @Service
 public class MediaUrlServiceImpl implements MediaUrlService {
+    private final String encryptKey;
     private final VideoUrlMapper videoUrlMapper;
     private final FileUserMapper fileUserMapper;
 
-    public MediaUrlServiceImpl(VideoUrlMapper videoUrlMapper, FileUserMapper fileUserMapper) {
+    public MediaUrlServiceImpl(DfsProperties dfsProperties, VideoUrlMapper videoUrlMapper,
+                               FileUserMapper fileUserMapper) {
+        this.encryptKey = dfsProperties.getEncryptKey();
         this.videoUrlMapper = videoUrlMapper;
         this.fileUserMapper = fileUserMapper;
     }
@@ -36,16 +40,17 @@ public class MediaUrlServiceImpl implements MediaUrlService {
     }
 
     @Override
-    public List<VideoUrlDto> getEncryptMp4Urls(String videoFileId, String key) throws NoSuchAlgorithmException {
+    public List<VideoUrlDto> getEncryptMp4Urls(EncryptParam encryptParam) {
+        String videoFileId = encryptParam.getVideoFileId();
         List<VideoUrlDto> urls = videoUrlMapper.findByVideoFileId(videoFileId);
         return urls.stream()
                 .map(videoUrlDto -> {
                     String url = videoUrlDto.getUrl();
                     try {
-                        String encryptUrl = encryptUrl(videoFileId, url);
+                        String encryptUrl = encryptUrl(encryptParam.getAccessUserId(), url);
                         videoUrlDto.setUrl(encryptUrl);
                         return videoUrlDto;
-                    } catch (NoSuchAlgorithmException e) {
+                    } catch (Exception e) {
                         e.printStackTrace();
                     }
                     return null;
@@ -54,18 +59,17 @@ public class MediaUrlServiceImpl implements MediaUrlService {
                 .collect(Collectors.toList());
     }
 
-    private String encryptUrl(String videoFileId, String url) throws NoSuchAlgorithmException {
+    private String encryptUrl(long accessUserId, String url) throws Exception {
         String key = "abcdABCD1234";
         // 链接过期时间戳,8 小时后过期
         long t = System.currentTimeMillis() + 8*3600*1000;
-        byte[] bytes = (key + t).getBytes(StandardCharsets.UTF_8);
-        String sign = DigestUtil.md5sum(bytes);
-        String encryptUrl = String.format("%s?t=%s&sign=%s", url, t, sign);
-        return encryptUrl;
+        String sign = String.format("%s_%s_%s", key, accessUserId, t);
+        String encryptSign = AesEncrypt.encrypt(sign, encryptKey);
+        return String.format("%s?sign=%s", url, encryptSign);
     }
 
     @Override
-    public void activateFile(String uploadId) {
-        fileUserMapper.updateSetActivate(uploadId);
+    public void activateFileAccess(FileAccess fileAccess) {
+        fileUserMapper.updateSetFileAccess(fileAccess);
     }
 }

+ 2 - 1
src/main/resources/application-dev.yml

@@ -12,4 +12,5 @@ dfs:
   node: 0
   baseDirs:
     - /opt/file/disk0/
-    - /home/reghao/opt/file/disk0/
+    - /home/reghao/opt/file/disk0/
+  encryptKey: 5JCdi68CulSDu0TqD4jR

+ 2 - 1
src/main/resources/application-dev1.yml

@@ -12,4 +12,5 @@ dfs:
   node: 0
   baseDirs:
     - /opt/file/disk0/
-    - /home/reghao/opt/file/disk0/
+    - /home/reghao/opt/file/disk0/
+  encryptKey: 5JCdi68CulSDu0TqD4jR

+ 2 - 1
src/main/resources/application-dev2.yml

@@ -12,4 +12,5 @@ dfs:
   node: 0
   baseDirs:
     - /opt/file/disk0/
-    - /home/reghao/opt/file/disk0/
+    - /home/reghao/opt/file/disk0/
+  encryptKey: 5JCdi68CulSDu0TqD4jR

+ 2 - 1
src/main/resources/application-test.yml

@@ -13,4 +13,5 @@ dfs:
   baseDirs:
     - /opt/file/disk0/
     - /opt/file/disk1/
-    - /opt/file/disk2/
+    - /opt/file/disk2/
+  encryptKey: 5JCdi68CulSDu0TqD4jR

+ 16 - 6
src/main/resources/mapper/FileUserMapper.xml

@@ -4,19 +4,29 @@
 <mapper namespace="cn.reghao.dfs.store.db.mapper.FileUserMapper">
     <insert id="save" useGeneratedKeys="true" keyProperty="id">
         insert into file_user
-        (`id`,`deleted`,`create_time`,`update_time`,`upload_id`,`upload_by`,`file_id`,`activate`)
+        (`id`,`deleted`,`create_time`,`update_time`,`upload_id`,`upload_by`,`file_id`,`activate`,`auth`)
         values 
-        (#{id},#{deleted},#{createTime},#{updateTime},#{uploadId},#{uploadBy},#{fileId},#{activate})
+        (#{id},#{deleted},#{createTime},#{updateTime},#{uploadId},#{uploadBy},#{fileId},#{activate},#{auth})
     </insert>
 
-    <update id="updateSetActivate">
+    <update id="updateSetFileAccess">
         update file_user
-        set update_time=now(),activate=1
+        set update_time=now(),activate=#{activate},auth=#{auth}
+        where upload_id=#{uploadId}
+    </update>
+    <update id="updateSetNeedAuth">
+        update file_user
+        set update_time=now(),auth=1
+        where upload_id=#{uploadId}
+    </update>
+    <update id="updateSetNotNeedAuth">
+        update file_user
+        set update_time=now(),auth=0
         where upload_id=#{uploadId}
     </update>
 
-    <select id="isActivate" resultType="java.lang.Boolean">
-        select activate from file_user where upload_id=#{uploadId}
+    <select id="findFileAccessByUploadId" resultType="cn.reghao.dfs.api.dto.FileAccess">
+        select upload_id,activate,auth from file_user where upload_id=#{uploadId}
     </select>
     <select id="findByFileAndUserId" resultType="cn.reghao.dfs.store.model.po.FileUser">
         select * from file_user