├── .gitignore ├── LICENSE ├── README.md ├── pom.xml └── src └── main ├── java └── top │ └── retain │ └── nd │ ├── StarterApplication.java │ ├── aspect │ └── UrlLoggerAspect.java │ ├── common │ ├── CommonResult.java │ ├── CommonResultTool.java │ ├── ShareStatus.java │ └── StatusCode.java │ ├── config │ ├── FilterConfig.java │ ├── MybatisPlusConfig.java │ ├── RedisConfig.java │ ├── RedisKeyExpirationListerner.java │ ├── RedisListenerConfig.java │ ├── Swagger2.java │ ├── WebMvcConfig.java │ └── security │ │ ├── SecurityConfig.java │ │ ├── SmsCodeAuthenticationProvider.java │ │ ├── SmsCodeAuthenticationSecurityConfig.java │ │ ├── SmsCodeAuthenticationToken.java │ │ └── TokenAuthenticationHelper.java │ ├── controller │ ├── ControllerAdvice.java │ ├── ExtendCodeController.java │ ├── FileController.java │ ├── SafeController.java │ ├── ShareController.java │ ├── TagController.java │ ├── TaskController.java │ └── UserController.java │ ├── dto │ ├── DownloadDirResp.java │ ├── ForgetPasswordReq.java │ ├── ForgetSafeCodeReq.java │ ├── GetFileDetailResp.java │ ├── GetFinishedTasksResp.java │ ├── GetUserFIleSpaceResp.java │ ├── ListFilesPagedResp.java │ ├── STSResp.java │ └── UpdateUserBasicInfoReq.java │ ├── entity │ ├── ExtendCode.java │ ├── SafeFile.java │ ├── Share.java │ ├── Tag.java │ ├── TagFile.java │ ├── Task.java │ ├── User.java │ ├── UserCode.java │ └── UserFile.java │ ├── exception │ ├── CodeWrongException.java │ ├── DownloadException.java │ ├── FileHasExpiredOrNonExist.java │ ├── SmsCodeException.java │ ├── TagFileAlreadyExistException.java │ ├── TagNotExistException.java │ ├── UploadException.java │ ├── UserExistException.java │ └── UserNotLoginException.java │ ├── filter │ ├── CorsFilter.java │ ├── JwtAuthenticationFilter.java │ ├── JwtLoginFilter.java │ ├── LogFilter.java │ ├── SmsCodeAuthenticationFilter.java │ └── WrapperRequestFilter.java │ ├── handler │ ├── CustomAuthenticationFailureHandler.java │ ├── CustomAuthenticationSuccessHandler.java │ ├── CustomMetaObjectHandler.java │ ├── CustomerAccessDeniedHandler.java │ └── CustomizeLogoutSuccessHandler.java │ ├── mapper │ ├── IExtendCodeMapper.java │ ├── IFileMapper.java │ ├── ISafeFileMapper.java │ ├── IShareMapper.java │ ├── ITagFileMapper.java │ ├── ITagMapper.java │ ├── ITaskMapper.java │ ├── IUserCodeMapper.java │ └── IUserMapper.java │ ├── mappers │ ├── ExtendCodemapper.xml │ ├── FileMapper.xml │ ├── ISafeFileMapper.xml │ ├── IShareMapper.xml │ ├── ITagFileMapper.xml │ ├── ITaskMapper.xml │ ├── TagMapper.xml │ ├── UserCode.xml │ └── UserMapper.xml │ ├── service │ ├── IExtendCodeService.java │ ├── IFileService.java │ ├── ISafeFileService.java │ ├── IShareService.java │ ├── ITagFileService.java │ ├── ITagService.java │ ├── ITaskService.java │ ├── IUserCodeService.java │ ├── IUserService.java │ └── impl │ │ ├── ExtendCodeServiceImpl.java │ │ ├── FileService.java │ │ ├── SafeFileServiceImpl.java │ │ ├── ShareServiceImpl.java │ │ ├── TagFileServiceImpl.java │ │ ├── TagServiceImpl.java │ │ ├── TaskServiceImpl.java │ │ ├── UserCodeServiceImpl.java │ │ ├── UserServiceImpl.java │ │ └── UserSmsServiceImpl.java │ ├── util │ ├── FileUtils.java │ ├── OSSUtils.java │ ├── QRCodeUtils.java │ ├── RedisUtils.java │ ├── RequestWrapper.java │ ├── SmsUtil.java │ ├── SpringSecurityUtil.java │ └── VerifyCodeUtils.java │ └── vo │ └── UserVo.java └── resources ├── application.yaml ├── logback-spring.xml └── sql ├── data.sql └── schema.sql /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.nar 17 | *.ear 18 | *.zip 19 | *.tar.gz 20 | *.rar 21 | 22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 23 | hs_err_pid* 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cloud-disk-based-on-oss 2 | 3 | ![logo](http://cdn.retainblog.top/blog/logo-165742112282212.png) 4 | 5 | #### 介绍 6 | 结合阿里云OSS对象存储,实现的公有云网盘(仅供个人学习使用),目前个人自用体验良好。 7 | 8 | #### 软件架构 9 | 此为后端项目,后端技术栈:SpringBoot+MybatisPlus+Redis+SpringSecurity+腾讯云短信服务+阿里云OSS 10 | 在线预览使用开源kkfileview。前端项目[点此跳转](https://github.com/Retainv/cloud-disk-frontend) 11 | 12 | #### 特点 13 | 14 | 1. 上传位置与服务器解耦,通过前端直传OSS,不受服务器带宽限制,适合个人或小圈子朋友使用,易于扩展,成本低,体验好。 15 | 2. 集成腾讯云短信服务,支持手机验证码一键登录,随时随地打开网页即可查看个人文件。 16 | 3. 上传下载带宽不受低配置服务器带宽限制,上传下载速度最高支持10 Gbit/s,分片上传文件最大支持48.8 TB。 17 | 4. STS临时令牌认证,保证上传接口安全。 18 | 5. 集成第三方在线预览服务,支持常规文件单击预览。 19 | 6. 外链分享、提取码生成、分享统一管理等。 20 | 21 | #### 详细功能 22 | 23 | - 已实现功能: 24 | - 文件 25 | - 新建文件夹 26 | - 多级文件夹点击路径跳转 27 | - 上传文件 28 | - 上传文件夹 29 | - 右键菜单 30 | - 在线预览 31 | - 支持主流文件类型,包括office、图片、压缩包、MP4、MP3等等 32 | - 下载 33 | - 获取输出流通过浏览器下载,不限速 34 | - 分享 35 | - 可设置过期时间、生成专属二维码,生成提取码、专属分享页面,专属分享链接 36 | - 他人打开分享界面可在线预览文件或下载 37 | - 收藏 38 | - 可创建新标签、将文件归类到特定标签 39 | - 重命名 40 | - 保险箱 41 | - 首次进入需设置专属密钥激活 42 | - 10分钟内如进入过保险箱,后续进入无需密码 43 | - 文件移入保险箱后只能在保险箱中查看 44 | - 锁定保险箱后再次进入需输入密码 45 | - 查看文件详细信息 46 | - 可查看文件大小、上传时间、路径等具体信息 47 | - 回收站 48 | - 文件移入回收站后不会显示在文件页面 49 | - 可在回收站选择清空或恢复文件,清空后不可恢复 50 | - 上传 51 | - 上传显示网速与上传进度,通过vue总线实时显示 52 | - 剩余上传任务小圆点实时提示 53 | - 切换标签查看已上传文件,可清空记录 54 | - 收藏夹 55 | - 新建标签 56 | - 右键菜单 57 | - 点击切换标签,实时显示不同标签下文件 58 | - 我的分享 59 | - 统一管理我的分享,显示文件名、文件路径、创建时间、过期时间、分享状态、分享链接、提取码、浏览量、下载量、转存量等信息,分享状态自动判断更新,可快捷再次分享、取消分享、删除分享 60 | - 分享界面 61 | - 提取码提取文件 62 | - 在线预览分享文件 63 | - 不限速直接下载文件 64 | - 转存文件、文件夹 65 | - 保险箱 66 | - 首次进入需设置专属密钥激活 67 | - 10分钟内如进入过保险箱,后续进入无需密码 68 | - 文件移入保险箱后只能在保险箱中查看 69 | - 锁定保险箱后再次进入需输入密码 70 | - 回收站 71 | - 文件移入回收站后不会显示在文件页面 72 | - 可在回收站选择清空或恢复文件,清空后不可恢复 73 | - 用户操作 74 | - 点击头像可进入个人主页 75 | - 点击个人主页头像可修改头像 76 | - 点击昵称可修改昵称 77 | - 可修改手机号(登录账号默认手机号) 78 | - 修改密码 79 | 80 | #### 部分截图 81 | 82 | ![image-20220709214033659](http://cdn.retainblog.top/blog/image-20220709214033659.png) 83 | 84 | ![image-20220709214124387](http://cdn.retainblog.top/blog/image-20220709214124387.png) 85 | 86 | ![image-20220710101614656](http://cdn.retainblog.top/blog/image-20220710101614656.png) 87 | 88 | ![image-20220709214210028](http://cdn.retainblog.top/blog/image-20220709214210028.png) 89 | 90 | ![image-20220709214304368](http://cdn.retainblog.top/blog/image-20220709214304368.png) 91 | 92 | ![image-20220709214338000](http://cdn.retainblog.top/blog/image-20220709214338000.png) 93 | 94 | ![image-20220709214406804](http://cdn.retainblog.top/blog/image-20220709214406804.png) 95 | 96 | ![image-20220709214537109](http://cdn.retainblog.top/blog/image-20220709214537109.png) 97 | 98 | ![image-20220709214552394](http://cdn.retainblog.top/blog/image-20220709214552394.png) 99 | 100 | ![image-20220709214610850](http://cdn.retainblog.top/blog/image-20220709214610850.png) 101 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | jar 7 | 8 | 9 | org.springframework.boot 10 | spring-boot-starter-parent 11 | 2.3.4.RELEASE 12 | 13 | 14 | top.retain 15 | network-disk 16 | 1.0-SNAPSHOT 17 | 18 | 19 | UTF-8 20 | 8 21 | 8 22 | 23 | 24 | 25 | 26 | 27 | org.springframework.boot 28 | spring-boot-starter-aop 29 | 30 | 31 | com.google.zxing 32 | core 33 | 3.4.1 34 | 35 | 36 | com.baomidou 37 | mybatis-plus-boot-starter 38 | 3.4.1 39 | 40 | 41 | io.jsonwebtoken 42 | jjwt 43 | 0.9.1 44 | 45 | 46 | com.github.xiaoymin 47 | knife4j-spring-boot-starter 48 | 2.0.2 49 | 50 | 51 | org.springframework.boot 52 | spring-boot-starter-web 53 | 54 | 55 | mysql 56 | mysql-connector-java 57 | 8.0.21 58 | runtime 59 | 60 | 61 | org.projectlombok 62 | lombok 63 | 1.18.18 64 | true 65 | 66 | 67 | org.springframework.boot 68 | spring-boot-starter-test 69 | test 70 | 71 | 72 | org.junit.vintage 73 | junit-vintage-engine 74 | 75 | 76 | com.vaadin.external.google 77 | android-json 78 | 79 | 80 | 81 | 82 | cn.hutool 83 | hutool-all 84 | 5.5.7 85 | 86 | 87 | 88 | org.springframework.boot 89 | spring-boot-starter-security 90 | 91 | 92 | 93 | com.aliyun.oss 94 | aliyun-sdk-oss 95 | 3.13.2 96 | 97 | 98 | 99 | com.aliyun 100 | aliyun-java-sdk-sts 101 | 3.0.0 102 | 103 | 104 | com.aliyun 105 | aliyun-java-sdk-core 106 | 4.4.6 107 | 108 | 109 | org.springframework.boot 110 | spring-boot-starter-data-redis 111 | 112 | 113 | com.github.qcloudsms 114 | qcloudsms 115 | 1.0.6 116 | 117 | 118 | 119 | io.springfox 120 | springfox-swagger2 121 | 2.9.2 122 | 123 | 124 | io.springfox 125 | springfox-swagger-ui 126 | 2.9.2 127 | 128 | 129 | org.springframework.boot 130 | spring-boot-starter-log4j2 131 | 2.6.7 132 | 133 | 134 | 135 | 136 | 137 | 138 | org.springframework.boot 139 | spring-boot-maven-plugin 140 | 141 | 142 | 143 | repackage 144 | build-info 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | src/main/java 153 | 154 | **/*.properties 155 | **/*.xml 156 | 157 | false 158 | 159 | 160 | src/main/resources 161 | 162 | **/*.properties 163 | **/*.xml 164 | **/*.yaml 165 | **/*.sql 166 | **/*.txt 167 | **/*.pfx 168 | static/** 169 | 170 | false 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | dev 179 | 180 | dev 181 | 182 | 183 | true 184 | 185 | 186 | 187 | prod 188 | 189 | prod 190 | 191 | 192 | 193 | 194 | 195 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/StarterApplication.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd; 2 | 3 | import org.mybatis.spring.annotation.MapperScan; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import springfox.documentation.swagger2.annotations.EnableSwagger2; 7 | 8 | /** 9 | * @author Retain 10 | * @date 2021/9/29 12:28 11 | */ 12 | @SpringBootApplication 13 | @EnableSwagger2 14 | @MapperScan(value = "top.retain.nd.mapper") 15 | public class StarterApplication { 16 | public static void main(String[] args) { 17 | SpringApplication.run(StarterApplication.class, args); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/aspect/UrlLoggerAspect.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.aspect; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.aspectj.lang.JoinPoint; 5 | import org.aspectj.lang.annotation.Aspect; 6 | import org.springframework.stereotype.Component; 7 | import org.springframework.web.context.request.RequestAttributes; 8 | import org.springframework.web.context.request.RequestContextHolder; 9 | import org.springframework.web.context.request.ServletRequestAttributes; 10 | 11 | import javax.servlet.http.HttpServletRequest; 12 | import java.util.Arrays; 13 | 14 | /** 15 | * @author Retain 16 | * @date 2021/12/10 10:36 17 | * 已弃用,使用LogFilter 18 | */ 19 | @Component 20 | @Aspect 21 | @Slf4j 22 | @Deprecated 23 | public class UrlLoggerAspect { 24 | // @Pointcut("execution(* top.retain.nd.controller.*.*(..))") 25 | public void pt(){}; 26 | 27 | // @Before("pt()") //在切入点的方法run之前要干的 28 | public void logBeforeController(JoinPoint joinPoint){ 29 | // 这个RequestContextHolder是Springmvc提供来获得请求的东西 30 | RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); 31 | HttpServletRequest request = ((ServletRequestAttributes)requestAttributes).getRequest(); 32 | // 记录下请求内容 33 | log.info("**USER:" + request.getRemoteUser()); 34 | log.info("**URL : " + request.getRequestURL().toString()); 35 | log.info("**HTTP_METHOD : " + request.getMethod()); 36 | log.info("**IP : " + request.getRemoteAddr()); 37 | log.info("**THE ARGS OF THE CONTROLLER : " + Arrays.toString(joinPoint.getArgs())); 38 | //下面这个getSignature().getDeclaringTypeName()是获取包+类名的 然后后面的joinPoint.getSignature.getName()获取了方法名 39 | log.info("**CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName()); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/common/CommonResult.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.common; 2 | 3 | 4 | @SuppressWarnings(value = "unused") 5 | public class CommonResult { 6 | private int code; 7 | private String message; 8 | private int currentPage; 9 | private int total; 10 | private Object data; 11 | 12 | public CommonResult() { 13 | } 14 | 15 | public CommonResult(int code, String message) { 16 | this.code = code; 17 | this.message = message; 18 | } 19 | 20 | public CommonResult(int code, String message, Object data) { 21 | this.code = code; 22 | this.message = message; 23 | this.data = data; 24 | } 25 | 26 | public int getCode() { 27 | return code; 28 | } 29 | 30 | public CommonResult setCode(int code) { 31 | this.code = code; 32 | return this; 33 | } 34 | 35 | public String getMessage() { 36 | return message; 37 | } 38 | 39 | public CommonResult setMessage(String message) { 40 | this.message = message; 41 | return this; 42 | } 43 | 44 | public int getCurrentPage() { 45 | return currentPage; 46 | } 47 | 48 | public CommonResult setCurrentPage(int currentPage) { 49 | this.currentPage = currentPage; 50 | return this; 51 | } 52 | 53 | public int getTotal() { 54 | return total; 55 | } 56 | 57 | public CommonResult setTotal(int total) { 58 | this.total = total; 59 | return this; 60 | } 61 | 62 | public Object getData() { 63 | return data; 64 | } 65 | 66 | public CommonResult setData(Object data) { 67 | this.data = data; 68 | return this; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/common/CommonResultTool.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.common; 2 | 3 | import com.fasterxml.jackson.core.JsonProcessingException; 4 | import com.fasterxml.jackson.databind.ObjectMapper; 5 | import org.springframework.security.core.AuthenticationException; 6 | 7 | import javax.servlet.http.HttpServletResponse; 8 | import java.io.IOException; 9 | import java.io.PrintWriter; 10 | 11 | /** 12 | * @author waxijiang 13 | */ 14 | public class CommonResultTool { 15 | 16 | public static CommonResult success(){ 17 | return new CommonResult(StatusCode.SUCCESS.getCode(), StatusCode.SUCCESS.getMsg()); 18 | } 19 | 20 | public static CommonResult success(String msg, Object data){ 21 | return new CommonResult(StatusCode.SUCCESS.getCode(), msg, data); 22 | } 23 | 24 | public static CommonResult success(Object data){ 25 | return new CommonResult(StatusCode.SUCCESS.getCode(), StatusCode.SUCCESS.getMsg(), data); 26 | } 27 | 28 | public static CommonResult fail(StatusCode statusCode){ 29 | return new CommonResult(statusCode.getCode(), statusCode.getMsg()); 30 | } 31 | public static CommonResult fail(AuthenticationException exception){ 32 | return new CommonResult(411, exception.getMessage()); 33 | } 34 | public static CommonResult fail(StatusCode statusCode, String msg){ 35 | return new CommonResult(statusCode.getCode(), msg, null); 36 | } 37 | 38 | public static void toJson(Integer code, String msg, int total, int current, Object data, HttpServletResponse response) { 39 | 40 | ObjectMapper mapper = new ObjectMapper(); 41 | PrintWriter writer; 42 | try { 43 | response.flushBuffer(); 44 | writer = response.getWriter(); 45 | } catch (IOException e) { 46 | throw new RuntimeException(e); 47 | } 48 | try { 49 | CommonResult commonResult = new CommonResult().setCode(code).setMessage(msg).setData(data).setTotal(total).setCurrentPage(current); 50 | String value = mapper.writeValueAsString(commonResult); 51 | writer.write(value); 52 | } catch (JsonProcessingException e) { 53 | throw new RuntimeException(e); 54 | } finally { 55 | writer.close(); 56 | } 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/common/ShareStatus.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.common; 2 | 3 | public enum ShareStatus { 4 | 5 | /** 6 | * 分享状态 7 | */ 8 | NORMAL(1, "分享有效"), 9 | DESABLED(2, "分享已过期"), 10 | CANCELLED(3, "分享被取消"), 11 | DELETED(4, "原文件被删除,分享失效"); 12 | 13 | 14 | private final int status; 15 | private final String desc; 16 | private final Class exceptionClass; 17 | 18 | 19 | 20 | public static String getDesc(int status) { 21 | ShareStatus[] values = values(); 22 | for (ShareStatus value : values) { 23 | if (value.getCode() == status) { 24 | return value.getMsg(); 25 | } 26 | } 27 | return null; 28 | } 29 | ShareStatus(int status, String desc) { 30 | this.status = status; 31 | this.desc = desc; 32 | this.exceptionClass = Exception.class; 33 | } 34 | 35 | ShareStatus(int status, String desc, Class exceptionClass) { 36 | this.status = status; 37 | this.desc = desc; 38 | this.exceptionClass = exceptionClass; 39 | } 40 | 41 | public int getCode() { 42 | return status; 43 | } 44 | 45 | public String getMsg() { 46 | return desc; 47 | } 48 | 49 | public Class getExceptionClass() { 50 | return exceptionClass; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/common/StatusCode.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.common; 2 | 3 | 4 | public enum StatusCode { 5 | //成功 6 | SUCCESS(200, "请求成功"), 7 | //客户端 8 | SYNTAX_ERROR(400, "客户端请求语法错误"), 9 | UN_AUTHORIZED(401, "用户未认证"), 10 | NO_PERMISSION(403, "权限不足"), 11 | NOT_FOUND(404, "未找到相关资源"), 12 | METHOD_ERROR(405, "请求方法错误"), 13 | UNKNOWN_USERNAME(410, "用户名未找到"), 14 | WRONG_USERNAME_OR_PASSWORD(411, "用户名或密码错误"), 15 | CODE_WRONG(411, "验证码错误"), 16 | USER_DISABLED(412, "用户已被禁用"), 17 | USER_LOCKED(413, "用户已被锁定"), 18 | NO_ACTION_JOIN(414, "用户未参与任何行动"), 19 | USER_NOT_BINDING(415, "用户未绑定"), 20 | VERIFY_CODE_ERROR(416, "验证码错误"), 21 | MISSING_PARAM(417, "参数不足"), 22 | UPLOAD_FAIL(445, "上传失败"), 23 | FILE_EXSIT(422, "文件夹已存在"), 24 | //服务端错误 25 | INTERNAL_SERVER_ERROR(500, "服务器内部错误"); 26 | 27 | private final int code; 28 | private final String msg; 29 | private final Class exceptionClass; 30 | 31 | StatusCode(int code, String msg) { 32 | this.code = code; 33 | this.msg = msg; 34 | this.exceptionClass = Exception.class; 35 | } 36 | 37 | StatusCode(int code, String msg, Class exceptionClass) { 38 | this.code = code; 39 | this.msg = msg; 40 | this.exceptionClass = exceptionClass; 41 | } 42 | 43 | public int getCode() { 44 | return code; 45 | } 46 | 47 | public String getMsg() { 48 | return msg; 49 | } 50 | 51 | public Class getExceptionClass() { 52 | return exceptionClass; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/config/FilterConfig.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.config; 2 | 3 | import org.springframework.boot.web.servlet.FilterRegistrationBean; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import top.retain.nd.filter.LogFilter; 7 | 8 | @Configuration 9 | public class FilterConfig { 10 | 11 | @Bean 12 | public FilterRegistrationBean registFilter() { 13 | FilterRegistrationBean registration = new FilterRegistrationBean(); 14 | registration.setFilter(new LogFilter()); 15 | registration.addUrlPatterns("/*"); 16 | registration.setName("LogFilter"); 17 | registration.setOrder(1); 18 | return registration; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/config/MybatisPlusConfig.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.config; 2 | 3 | import com.baomidou.mybatisplus.annotation.DbType; 4 | import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; 5 | import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; 6 | import org.mybatis.spring.annotation.MapperScan; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | 10 | /** 11 | * @author Retain 12 | * @date 2021/9/29 16:56 13 | */ 14 | @Configuration 15 | @MapperScan("edu.hubu.homeaction.mapper.*") 16 | public class MybatisPlusConfig { 17 | /** 18 | * 分页配置 19 | * @return 20 | */ 21 | @Bean 22 | public MybatisPlusInterceptor mybatisPlusInterceptor() { 23 | MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); 24 | interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); 25 | return interceptor; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/config/RedisConfig.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.config; 2 | 3 | import com.fasterxml.jackson.annotation.JsonAutoDetect; 4 | import com.fasterxml.jackson.annotation.PropertyAccessor; 5 | import com.fasterxml.jackson.databind.ObjectMapper; 6 | import org.springframework.cache.CacheManager; 7 | import org.springframework.cache.annotation.CachingConfigurerSupport; 8 | import org.springframework.cache.annotation.EnableCaching; 9 | import org.springframework.context.annotation.Bean; 10 | import org.springframework.context.annotation.Configuration; 11 | import org.springframework.data.redis.cache.RedisCacheConfiguration; 12 | import org.springframework.data.redis.cache.RedisCacheManager; 13 | import org.springframework.data.redis.connection.RedisConnectionFactory; 14 | import org.springframework.data.redis.core.RedisTemplate; 15 | import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; 16 | import org.springframework.data.redis.serializer.RedisSerializationContext; 17 | import org.springframework.data.redis.serializer.StringRedisSerializer; 18 | 19 | import java.time.Duration; 20 | 21 | /** 22 | * @author Retain 23 | * @date 2021/3/1 11:13 24 | */ 25 | 26 | @Configuration 27 | @EnableCaching 28 | public class RedisConfig extends CachingConfigurerSupport { 29 | 30 | @Bean 31 | public CacheManager cacheManager(RedisTemplate template) { 32 | RedisCacheConfiguration defaultCacheConfiguration = 33 | RedisCacheConfiguration 34 | .defaultCacheConfig() 35 | // 设置key为String 36 | .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(template.getStringSerializer())) 37 | // 设置value 为自动转Json的Object 38 | .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(template.getValueSerializer())) 39 | // 不缓存null 40 | .disableCachingNullValues() 41 | // 缓存数据保存1小时 42 | .entryTtl(Duration.ofHours(1)); 43 | RedisCacheManager redisCacheManager = 44 | RedisCacheManager.RedisCacheManagerBuilder 45 | // Redis 连接工厂 46 | .fromConnectionFactory(template.getConnectionFactory()) 47 | // 缓存配置 48 | .cacheDefaults(defaultCacheConfiguration) 49 | // 配置同步修改或删除 put/evict 50 | .transactionAware() 51 | .build(); 52 | return redisCacheManager; 53 | } 54 | @Bean(name = "redisTemplate") 55 | public RedisTemplate redisTemplate(RedisConnectionFactory factory) { 56 | // 创建RedisTemplate对象 57 | RedisTemplate template = new RedisTemplate<>(); 58 | 59 | // 配置连接工厂 60 | template.setConnectionFactory(factory); 61 | // 定义Jackson2JsonRedisSerializer序列化对象 62 | Jackson2JsonRedisSerializer jacksonSeial = new Jackson2JsonRedisSerializer<>(Object.class); 63 | ObjectMapper om = new ObjectMapper(); 64 | // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public 65 | om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); 66 | // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会报异常 67 | om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); 68 | jacksonSeial.setObjectMapper(om); 69 | StringRedisSerializer stringSerial = new StringRedisSerializer(); 70 | // redis key 序列化方式使用stringSerial 71 | template.setKeySerializer(stringSerial); 72 | // redis value 序列化方式使用jackson 73 | template.setValueSerializer(stringSerial); 74 | // redis hash key 序列化方式使用stringSerial 75 | template.setHashKeySerializer(stringSerial); 76 | // redis hash value 序列化方式使用jackson 77 | template.setHashValueSerializer(jacksonSeial); 78 | template.afterPropertiesSet(); 79 | template.setEnableTransactionSupport(true); 80 | return template; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/config/RedisKeyExpirationListerner.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.config; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.springframework.beans.BeanUtils; 5 | import org.springframework.data.redis.connection.Message; 6 | import org.springframework.data.redis.listener.KeyExpirationEventMessageListener; 7 | import org.springframework.data.redis.listener.RedisMessageListenerContainer; 8 | import org.springframework.stereotype.Component; 9 | import top.retain.nd.common.ShareStatus; 10 | import top.retain.nd.entity.Share; 11 | import top.retain.nd.service.IShareService; 12 | 13 | import javax.annotation.Resource; 14 | 15 | import static top.retain.nd.service.impl.FileService.REDIS_SHARE_PREFIX; 16 | 17 | /** 18 | * 监听redisKey过期回调 19 | */ 20 | @Component 21 | @Slf4j 22 | public class RedisKeyExpirationListerner extends KeyExpirationEventMessageListener { 23 | 24 | 25 | @Resource 26 | IShareService shareService; 27 | /** 28 | * @param listenerContainer must not be {@literal null}. 29 | */ 30 | public RedisKeyExpirationListerner(RedisMessageListenerContainer listenerContainer) { 31 | super(listenerContainer); 32 | } 33 | 34 | /** 35 | * 使用该方法监听 ,当我们的key失效的时候执行改方法 36 | */ 37 | @Override 38 | public void onMessage(Message message, byte[] pattern) { 39 | String keyExpire = message.toString(); 40 | String id = keyExpire.substring(keyExpire.indexOf(':') + 1); 41 | log.info(keyExpire); 42 | // 对于指定前缀的key进行处理 43 | if (keyExpire.startsWith(REDIS_SHARE_PREFIX)) { 44 | Share share = new Share(); 45 | share.setId(id); 46 | Share byId = shareService.getById(id); 47 | BeanUtils.copyProperties(byId, share); 48 | share.setStatus(ShareStatus.DESABLED.getCode()); 49 | boolean b = shareService.updateById(share); 50 | log.info("key为:" + keyExpire + "的分享已经过期!更新状态结果:" + b); 51 | } 52 | 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/config/RedisListenerConfig.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.data.redis.connection.RedisConnectionFactory; 6 | import org.springframework.data.redis.listener.RedisMessageListenerContainer; 7 | 8 | @Configuration 9 | public class RedisListenerConfig { 10 | @Bean 11 | RedisMessageListenerContainer container(RedisConnectionFactory factory){ 12 | RedisMessageListenerContainer container=new RedisMessageListenerContainer(); 13 | container.setConnectionFactory(factory); 14 | return container; 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/config/Swagger2.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import springfox.documentation.builders.ApiInfoBuilder; 6 | import springfox.documentation.builders.PathSelectors; 7 | import springfox.documentation.builders.RequestHandlerSelectors; 8 | import springfox.documentation.service.ApiInfo; 9 | import springfox.documentation.spi.DocumentationType; 10 | import springfox.documentation.spring.web.plugins.Docket; 11 | import springfox.documentation.swagger2.annotations.EnableSwagger2; 12 | 13 | /** 14 | * @author Retain 15 | * @date 2021/11/3 22:40 16 | */ 17 | @Configuration 18 | @EnableSwagger2 19 | public class Swagger2 { 20 | @Bean 21 | public Docket createRestApi() { 22 | return new Docket(DocumentationType.SWAGGER_2) 23 | .apiInfo(apiInfo()) 24 | .select() 25 | .apis(RequestHandlerSelectors.basePackage("top.retain.nd.controller")) 26 | .paths(PathSelectors.any()) 27 | .build(); 28 | } 29 | 30 | /** 31 | * 创建该API的基本信息(这些基本信息会展现在文档页面中) 32 | * 访问地址:http://项目实际地址/swagger-ui.html 33 | * @return 34 | */ 35 | private ApiInfo apiInfo() { 36 | return new ApiInfoBuilder() 37 | .title("网盘API") 38 | .description("网盘API") 39 | .termsOfServiceUrl("http://localhost:8808/swagger-ui.html") 40 | .version("1.0") 41 | .build(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/config/WebMvcConfig.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.config; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; 5 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 6 | 7 | /** 8 | * @author Retain 9 | * @date 2021/11/3 22:51 10 | */ 11 | @Configuration 12 | class WebMvcConfig implements WebMvcConfigurer { 13 | @Override 14 | public void addResourceHandlers(ResourceHandlerRegistry registry) { 15 | registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/"); 16 | registry.addResourceHandler("swagger-ui.html") 17 | .addResourceLocations("classpath:/META-INF/resources/"); 18 | 19 | registry.addResourceHandler("/webjars/**") 20 | .addResourceLocations("classpath:/META-INF/resources/webjars/"); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/config/security/SecurityConfig.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.config.security; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.security.authentication.dao.DaoAuthenticationProvider; 6 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 7 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 8 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 9 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 10 | import org.springframework.security.core.userdetails.UserDetailsService; 11 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 12 | import org.springframework.security.crypto.password.PasswordEncoder; 13 | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; 14 | import org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter; 15 | import top.retain.nd.filter.JwtAuthenticationFilter; 16 | import top.retain.nd.filter.JwtLoginFilter; 17 | import top.retain.nd.filter.WrapperRequestFilter; 18 | import top.retain.nd.handler.CustomerAccessDeniedHandler; 19 | import top.retain.nd.handler.CustomizeLogoutSuccessHandler; 20 | import top.retain.nd.service.impl.UserServiceImpl; 21 | 22 | import javax.annotation.Resource; 23 | 24 | /** 25 | * @author retain 26 | */ 27 | @Configuration 28 | @EnableWebSecurity 29 | public class SecurityConfig extends WebSecurityConfigurerAdapter { 30 | 31 | @Resource 32 | private SmsCodeAuthenticationSecurityConfig smsCodeAuthenticationSecurityConfig; 33 | 34 | /** 35 | * 开放访问的请求 36 | */ 37 | private final static String[] PERMIT_ALL_MAPPING = { 38 | "/file/downloadDir", 39 | "/user/**", 40 | "/login", 41 | "/sms/**", 42 | "/swagger*//**", 43 | "/webjars/**", 44 | "/v2/api-docs/**", 45 | "/tag/**", 46 | "/file/link/**", 47 | "/share/getShareDetail/**", 48 | "/share/**" 49 | }; 50 | 51 | 52 | /** 53 | * 配置加密器 54 | */ 55 | @Bean 56 | public PasswordEncoder getPw() { 57 | return new BCryptPasswordEncoder(); 58 | } 59 | 60 | /** 61 | * 重写spring security 获取用户逻辑 62 | */ 63 | @Bean 64 | public UserDetailsService getUserDetailsService() { 65 | return new UserServiceImpl(); 66 | } 67 | 68 | /** 69 | * 重写AuthenticationProvider,使得可以抛出用户名不存在异常 70 | */ 71 | @Bean 72 | public DaoAuthenticationProvider authenticationProvider() { 73 | DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); 74 | provider.setHideUserNotFoundExceptions(false); 75 | provider.setUserDetailsService(getUserDetailsService()); 76 | provider.setPasswordEncoder(getPw()); 77 | return provider; 78 | } 79 | 80 | 81 | /** 82 | * 跨域配置 83 | */ 84 | // @Bean 85 | // public CorsConfigurationSource corsConfigurationSource() { 86 | // // 允许跨域访问的 URL 87 | // List allowedOriginsUrl = new ArrayList<>(); 88 | // allowedOriginsUrl.add("*"); 89 | // CorsConfiguration config = new CorsConfiguration(); 90 | // config.setAllowCredentials(true); 91 | // // 设置允许跨域访问的 URL 92 | // config.setAllowedOrigins(allowedOriginsUrl); 93 | // config.addAllowedHeader("*"); 94 | // config.addAllowedMethod("*"); 95 | // UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); 96 | // source.registerCorsConfiguration("/**", config); 97 | // return source; 98 | // } 99 | @Override 100 | protected void configure(HttpSecurity http) throws Exception { 101 | http.authorizeRequests() 102 | .antMatchers(PERMIT_ALL_MAPPING) 103 | .permitAll() 104 | .anyRequest() 105 | .authenticated() 106 | // 自定义的FilterSecurityInterceptor 107 | .and() 108 | // 添加过滤器链,前一个参数过滤器, 后一个参数过滤器添加的地方 109 | // 登陆过滤器 110 | .addFilterBefore(new JwtLoginFilter("/login", authenticationManager()), UsernamePasswordAuthenticationFilter.class) 111 | // 请求过滤器 112 | .addFilterBefore(new JwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class) 113 | // 添加一个过滤器来封装request 114 | .addFilterBefore(new WrapperRequestFilter(), WebAsyncManagerIntegrationFilter.class) 115 | // 开启跨域 116 | .cors() 117 | .and() 118 | // 开启 csrf 119 | .csrf() 120 | .disable() 121 | // .ignoringAntMatchers(PERMIT_ALL_MAPPING) 122 | // .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) 123 | // .and() 124 | .exceptionHandling().accessDeniedHandler(new CustomerAccessDeniedHandler()); 125 | // todo: 可能存在问题 126 | http.logout() 127 | .logoutSuccessHandler(new CustomizeLogoutSuccessHandler()) 128 | .deleteCookies("COOKIE-TOKEN") 129 | .deleteCookies("JSESSIONID"); 130 | http.apply(smsCodeAuthenticationSecurityConfig); 131 | } 132 | 133 | 134 | @Override 135 | protected void configure(AuthenticationManagerBuilder auth) throws Exception { 136 | 137 | auth.userDetailsService(getUserDetailsService()) 138 | .passwordEncoder(getPw()); 139 | 140 | } 141 | 142 | 143 | // @Override 144 | // public void configure(WebSecurity web) throws Exception { 145 | // web.ignoring().antMatchers(PERMIT_ALL_MAPPING); 146 | // } 147 | } 148 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/config/security/SmsCodeAuthenticationProvider.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.config.security; 2 | 3 | import cn.hutool.core.util.RandomUtil; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.beans.factory.annotation.Value; 6 | import org.springframework.security.authentication.AuthenticationProvider; 7 | import org.springframework.security.authentication.BadCredentialsException; 8 | import org.springframework.security.core.Authentication; 9 | import org.springframework.security.core.AuthenticationException; 10 | import org.springframework.security.core.userdetails.UserDetails; 11 | import org.springframework.security.core.userdetails.UserDetailsService; 12 | import org.springframework.stereotype.Component; 13 | import org.springframework.util.StringUtils; 14 | import top.retain.nd.entity.User; 15 | import top.retain.nd.service.IUserService; 16 | import top.retain.nd.service.impl.UserSmsServiceImpl; 17 | import top.retain.nd.util.SmsUtil; 18 | import top.retain.nd.util.VerifyCodeUtils; 19 | 20 | import javax.annotation.Resource; 21 | import java.util.Date; 22 | import java.util.Objects; 23 | import java.util.concurrent.TimeUnit; 24 | 25 | /** 26 | * @author Retain 27 | * @date 2021/10/19 15:44 28 | */ 29 | @Component 30 | @Slf4j 31 | public class SmsCodeAuthenticationProvider implements AuthenticationProvider { 32 | private UserDetailsService userDetailsService; 33 | @Resource 34 | UserSmsServiceImpl userSmsService; 35 | 36 | @Resource 37 | IUserService userService; 38 | private final VerifyCodeUtils verifyCodeUtils; 39 | 40 | @Value("${user.init-space}") 41 | private Long initSpace; 42 | 43 | private final SmsUtil smsUtil; 44 | 45 | public SmsCodeAuthenticationProvider(VerifyCodeUtils verifyCodeUtils, SmsUtil smsUtil) { 46 | this.verifyCodeUtils = verifyCodeUtils; 47 | this.smsUtil = smsUtil; 48 | } 49 | 50 | @Override 51 | public Authentication authenticate(Authentication authentication) throws AuthenticationException { 52 | SmsCodeAuthenticationToken authenticationToken = (SmsCodeAuthenticationToken) authentication; 53 | 54 | String phoneNumber = (String) authenticationToken.getPrincipal(); 55 | String code = (String) authenticationToken.getCredentials(); 56 | 57 | checkSmsCode(phoneNumber, code); 58 | // 根据手机号查询用户,没有则新建 59 | User user; 60 | if (Objects.isNull(userService.selectByPhone(phoneNumber))) { 61 | user = new User(); 62 | user.setName(RandomUtil.randomString(8)); 63 | user.setAccount(phoneNumber); 64 | String password = RandomUtil.randomString(6); 65 | user.setPassword(password); 66 | user.setPhoneNumber(phoneNumber); 67 | user.setTotalSpace(initSpace); 68 | userService.register(user); 69 | // 发送初始密码短信 70 | sendPasswordSms(phoneNumber, password); 71 | } 72 | UserDetails userDetails = userDetailsService.loadUserByUsername(phoneNumber); 73 | user = userService.selectByPhone(phoneNumber); 74 | user.setLastLoginTime(new Date()); 75 | userService.updateById(user); 76 | // 此时鉴权成功后,应当重新 new 一个拥有鉴权的 authenticationResult 返回 77 | SmsCodeAuthenticationToken authenticationResult = new SmsCodeAuthenticationToken(userDetails, userDetails.getAuthorities()); 78 | 79 | authenticationResult.setDetails(authenticationToken.getDetails()); 80 | 81 | return authenticationResult; 82 | } 83 | 84 | public void checkSmsCode(String phoneNumber, String code){ 85 | if (StringUtils.isEmpty(phoneNumber) || StringUtils.isEmpty(code)) { 86 | throw new BadCredentialsException("手机号或验证码不能为空"); 87 | } 88 | boolean matchResult = verifyCodeUtils.matchVerifyCode(phoneNumber, code); 89 | if(!matchResult) { 90 | throw new BadCredentialsException("验证码错误"); 91 | } 92 | } 93 | 94 | @Override 95 | public boolean supports(Class authentication) { 96 | // 判断 authentication 是不是 SmsCodeAuthenticationToken 的子类或子接口 97 | return SmsCodeAuthenticationToken.class.isAssignableFrom(authentication); 98 | } 99 | 100 | public UserDetailsService getUserDetailsService() { 101 | return userDetailsService; 102 | } 103 | 104 | public void setUserDetailsService(UserDetailsService userDetailsService) { 105 | this.userDetailsService = userDetailsService; 106 | } 107 | 108 | private void sendPasswordSms(String phoneNumber, String password) { 109 | new Thread(() -> { 110 | try { 111 | // 防止发送太频繁丢失短信 112 | TimeUnit.SECONDS.sleep(35); 113 | } catch (InterruptedException e) { 114 | e.printStackTrace(); 115 | } 116 | if (SmsUtil.sendSms(1176542, new String[]{phoneNumber}, new String[]{password})){ 117 | log.info(phoneNumber + "初始密码为: "+password + ", 已发送短信"); 118 | }else { 119 | } 120 | }).start(); 121 | 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/config/security/SmsCodeAuthenticationSecurityConfig.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.config.security; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.security.authentication.AuthenticationManager; 6 | import org.springframework.security.config.annotation.SecurityConfigurerAdapter; 7 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 8 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 9 | import org.springframework.security.web.DefaultSecurityFilterChain; 10 | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; 11 | import top.retain.nd.filter.SmsCodeAuthenticationFilter; 12 | import top.retain.nd.handler.CustomAuthenticationFailureHandler; 13 | import top.retain.nd.handler.CustomAuthenticationSuccessHandler; 14 | import top.retain.nd.handler.CustomizeLogoutSuccessHandler; 15 | import top.retain.nd.service.impl.UserSmsServiceImpl; 16 | 17 | /** 18 | * @author Retain 19 | * @date 2021/10/19 17:13 20 | */ 21 | @Configuration 22 | @EnableWebSecurity 23 | public class SmsCodeAuthenticationSecurityConfig extends SecurityConfigurerAdapter { 24 | @Autowired 25 | private UserSmsServiceImpl userDetailsService; 26 | @Autowired 27 | private CustomAuthenticationSuccessHandler customAuthenticationSuccessHandler; 28 | @Autowired 29 | private CustomAuthenticationFailureHandler customAuthenticationFailureHandler; 30 | 31 | @Autowired 32 | private SmsCodeAuthenticationProvider smsCodeAuthenticationProvider; 33 | 34 | @Override 35 | public void configure(HttpSecurity http) throws Exception { 36 | SmsCodeAuthenticationFilter smsCodeAuthenticationFilter = new SmsCodeAuthenticationFilter(); 37 | smsCodeAuthenticationFilter.setAuthenticationManager(http.getSharedObject(AuthenticationManager.class)); 38 | smsCodeAuthenticationFilter.setAuthenticationSuccessHandler(customAuthenticationSuccessHandler); 39 | smsCodeAuthenticationFilter.setAuthenticationFailureHandler(customAuthenticationFailureHandler); 40 | 41 | smsCodeAuthenticationProvider.setUserDetailsService(userDetailsService); 42 | 43 | http.authenticationProvider(smsCodeAuthenticationProvider) 44 | .addFilterAt(smsCodeAuthenticationFilter, UsernamePasswordAuthenticationFilter.class) 45 | .cors(); 46 | 47 | http.logout() 48 | .logoutSuccessHandler(new CustomizeLogoutSuccessHandler()) 49 | .deleteCookies("COOKIE-TOKEN") 50 | .deleteCookies("JSESSIONID"); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/config/security/SmsCodeAuthenticationToken.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.config.security; 2 | 3 | import org.springframework.security.authentication.AbstractAuthenticationToken; 4 | import org.springframework.security.core.SpringSecurityCoreVersion; 5 | 6 | /** 7 | * @author Retain 8 | * @date 2021/10/19 15:38 9 | */ 10 | public class SmsCodeAuthenticationToken extends AbstractAuthenticationToken { 11 | 12 | private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; 13 | /** 14 | * 登录的手机号码 15 | */ 16 | private final Object principal; 17 | private final Object credentials; 18 | 19 | /** 20 | * 构建一个有鉴权的 SmsCodeAuthenticationToken 21 | */ 22 | public SmsCodeAuthenticationToken(Object principal, Object credentials) { 23 | super(null); 24 | this.principal = principal; 25 | this.credentials = credentials; 26 | super.setAuthenticated(true); 27 | } 28 | 29 | /** 30 | * 构建拥有鉴权的 SmsCodeAuthenticationToken 31 | */ 32 | // public SmsCodeAuthenticationToken(Object principal, Collection authorities) { 33 | // super(authorities); 34 | // this.principal = principal; 35 | // // must use super, as we override 36 | // super.setAuthenticated(true); 37 | // credentials = null; 38 | // } 39 | 40 | @Override 41 | public Object getCredentials() { 42 | return this.credentials; 43 | } 44 | 45 | @Override 46 | public Object getPrincipal() { 47 | return this.principal; 48 | } 49 | 50 | @Override 51 | public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException { 52 | if (isAuthenticated) { 53 | throw new IllegalArgumentException( 54 | "Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead"); 55 | } 56 | 57 | super.setAuthenticated(false); 58 | } 59 | 60 | @Override 61 | public void eraseCredentials() { 62 | super.eraseCredentials(); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/config/security/TokenAuthenticationHelper.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.config.security; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import io.jsonwebtoken.Claims; 5 | import io.jsonwebtoken.Jwts; 6 | import io.jsonwebtoken.SignatureAlgorithm; 7 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 8 | import org.springframework.security.core.Authentication; 9 | import org.springframework.stereotype.Component; 10 | import org.springframework.web.util.WebUtils; 11 | import top.retain.nd.common.CommonResult; 12 | import top.retain.nd.common.CommonResultTool; 13 | import top.retain.nd.entity.User; 14 | 15 | import javax.servlet.http.Cookie; 16 | import javax.servlet.http.HttpServletRequest; 17 | import javax.servlet.http.HttpServletResponse; 18 | import java.io.IOException; 19 | import java.io.PrintWriter; 20 | import java.text.SimpleDateFormat; 21 | import java.util.Date; 22 | import java.util.TimeZone; 23 | 24 | @Component 25 | public class TokenAuthenticationHelper { 26 | 27 | /** 28 | * Token保存7天 29 | * */ 30 | private static final long EXPIRATION_TIME = 3600_000 * 24 * 7; 31 | 32 | /** 33 | * 记住我时 cookie token 过期时间 34 | * */ 35 | private static final int COOKIE_EXPIRATION_TIME = 1296000; 36 | 37 | private static final String SECRET_KEY = "SpringSecurityNB"; 38 | public static final String COOKIE_TOKEN = "COOKIE-TOKEN"; 39 | public static final String XSRF = "XSRF-TOKEN"; 40 | 41 | /** 42 | * 设置登陆成功后令牌返回 43 | * */ 44 | public static void addAuthentication(HttpServletRequest request, HttpServletResponse response, Authentication authResult) throws IOException { 45 | int cookExpirationTime = (int) (EXPIRATION_TIME / 1000); 46 | 47 | String jwt = Jwts.builder() 48 | // Subject 设置用户名 49 | .setSubject(authResult.getName()) 50 | // 过期时间 51 | .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME)) 52 | // 签名算法 53 | .signWith(SignatureAlgorithm.HS512, SECRET_KEY) 54 | .compact(); 55 | Cookie cookie = new Cookie(COOKIE_TOKEN, jwt); 56 | cookie.setHttpOnly(false); 57 | cookie.setPath("/"); 58 | //cookie.setMaxAge(cookExpirationTime); 59 | cookie.setMaxAge(cookExpirationTime); 60 | response.addCookie(cookie); 61 | 62 | // 向前端写入数据 63 | User user = (User) authResult.getPrincipal(); 64 | user.setPassword(null); 65 | user.setBucketName(null); 66 | user.setSafeCode(null); 67 | if (user.getLastLoginTime() != null) { 68 | SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); 69 | simpleDateFormat.setTimeZone(TimeZone.getTimeZone("GMT+8")); 70 | user.setLastLoginTimeStr(simpleDateFormat.format(user.getLastLoginTime())); 71 | } 72 | 73 | 74 | CommonResult success = CommonResultTool.success(user); 75 | 76 | response.setContentType("application/json; charset=UTF-8"); 77 | PrintWriter out = response.getWriter(); 78 | out.write(new ObjectMapper().writeValueAsString(success)); 79 | out.flush(); 80 | out.close(); 81 | } 82 | 83 | /** 84 | * 对请求的验证 85 | * */ 86 | public static Authentication getAuthentication(HttpServletRequest request) { 87 | 88 | Cookie cookie = WebUtils.getCookie(request, COOKIE_TOKEN); 89 | String token = cookie != null ? cookie.getValue() : null; 90 | 91 | if (token != null) { 92 | Claims claims = Jwts.parser() 93 | .setSigningKey(SECRET_KEY) 94 | .parseClaimsJws(token) 95 | .getBody(); 96 | 97 | String userName = claims.getSubject(); 98 | if (userName != null) { 99 | UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(userName, null, null); 100 | usernamePasswordAuthenticationToken.setDetails(claims); 101 | return usernamePasswordAuthenticationToken; 102 | } 103 | return null; 104 | } 105 | return null; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/controller/ControllerAdvice.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.controller; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.springframework.dao.DuplicateKeyException; 5 | import org.springframework.security.access.AccessDeniedException; 6 | import org.springframework.validation.BindException; 7 | import org.springframework.validation.BindingResult; 8 | import org.springframework.validation.FieldError; 9 | import org.springframework.web.bind.MethodArgumentNotValidException; 10 | import org.springframework.web.bind.MissingServletRequestParameterException; 11 | import org.springframework.web.bind.annotation.ExceptionHandler; 12 | import org.springframework.web.bind.annotation.RestControllerAdvice; 13 | import top.retain.nd.common.CommonResult; 14 | import top.retain.nd.common.CommonResultTool; 15 | import top.retain.nd.common.StatusCode; 16 | import top.retain.nd.exception.SmsCodeException; 17 | import top.retain.nd.exception.UserExistException; 18 | import top.retain.nd.exception.UserNotLoginException; 19 | 20 | import javax.annotation.Resource; 21 | import javax.servlet.http.HttpServletResponse; 22 | import java.io.FileNotFoundException; 23 | import java.nio.file.FileAlreadyExistsException; 24 | import java.nio.file.NoSuchFileException; 25 | import java.util.List; 26 | 27 | /** 28 | * @author Retain 29 | * @date 2021/10/3 16:15 30 | */ 31 | @Slf4j 32 | @RestControllerAdvice 33 | public class ControllerAdvice { 34 | @Resource 35 | private HttpServletResponse response; 36 | 37 | @ExceptionHandler(MethodArgumentNotValidException.class) 38 | public CommonResult validFormError(MethodArgumentNotValidException e) { 39 | BindingResult bindingResult = e.getBindingResult(); 40 | StringBuilder sb = new StringBuilder(); 41 | bindingResult.getFieldErrors().forEach(error -> sb.append(error.getField()).append(error.getDefaultMessage()).append(";")); 42 | log.error("错误消息:{}",e.getMessage(),e); 43 | return responseError(422, sb.toString()); 44 | } 45 | 46 | @ExceptionHandler(BindException.class) 47 | public CommonResult validError(BindException e) { 48 | List errors = e.getFieldErrors(); 49 | StringBuilder sb = new StringBuilder(); 50 | errors.forEach(error -> sb.append(error.getField()).append(' ').append(error.getDefaultMessage()).append(";")); 51 | log.error("错误消息:{}",e.getMessage(),e); 52 | 53 | return responseError(422, sb.toString()); 54 | } 55 | 56 | @ExceptionHandler(MissingServletRequestParameterException.class) 57 | public CommonResult requestParamsError(MissingServletRequestParameterException e) { 58 | log.error("错误消息:{}",e.getMessage(),e); 59 | 60 | return new CommonResult(422, e.getMessage(),null ); 61 | } 62 | 63 | @ExceptionHandler({IllegalArgumentException.class, FileAlreadyExistsException.class}) 64 | public CommonResult paramsError(Exception e) { 65 | log.error("错误消息:{}",e.getMessage(),e); 66 | 67 | return CommonResultTool.fail(StatusCode.FILE_EXSIT, e.getMessage()); 68 | } 69 | 70 | 71 | @ExceptionHandler(AccessDeniedException.class) 72 | public CommonResult handle(AccessDeniedException e) { 73 | return responseError(403, e.getMessage()); 74 | } 75 | 76 | @ExceptionHandler({ 77 | FileNotFoundException.class, 78 | NoSuchFileException.class, 79 | }) 80 | public CommonResult handle(Exception e) { 81 | if (log.isDebugEnabled()) { 82 | log.error("错误消息:{}",e.getMessage(),e); 83 | e.printStackTrace(); 84 | } 85 | return responseError(404, e.getMessage()); 86 | } 87 | 88 | @ExceptionHandler(Exception.class) 89 | public CommonResult defaultHandle(Exception e) { 90 | log.error("错误消息:{}",e.getMessage(),e); 91 | 92 | return responseError(500, e.getMessage()); 93 | } 94 | 95 | @ExceptionHandler(DuplicateKeyException.class) 96 | public CommonResult handle(DuplicateKeyException e) { 97 | log.error("错误消息:{}",e.getMessage(),e); 98 | 99 | return responseError(400, e.getMessage()); 100 | } 101 | 102 | @ExceptionHandler({UserNotLoginException.class}) 103 | public CommonResult handle(UserNotLoginException e) { 104 | log.error("错误消息:{}",e.getMessage(),e); 105 | 106 | return responseError(403, e.getMessage()); 107 | } 108 | 109 | @ExceptionHandler({UserExistException.class, SmsCodeException.class}) 110 | public CommonResult handle(UserExistException e) { 111 | log.error("错误消息:{}",e.getMessage(),e); 112 | return responseError(401, e.getMessage()); 113 | } 114 | 115 | @ExceptionHandler(RuntimeException.class) 116 | public CommonResult handle(RuntimeException e) { 117 | log.error("错误消息:{}",e.getMessage(),e); 118 | return new CommonResult(501, e.getMessage(),null ); 119 | } 120 | private CommonResult responseError(int code, String message) { 121 | 122 | response.setStatus(code); 123 | return new CommonResult(code, message, null); 124 | } 125 | 126 | } 127 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/controller/ExtendCodeController.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.controller; 2 | 3 | import io.swagger.annotations.Api; 4 | import io.swagger.annotations.ApiOperation; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.springframework.web.bind.annotation.*; 7 | import springfox.documentation.annotations.ApiIgnore; 8 | import top.retain.nd.common.CommonResult; 9 | import top.retain.nd.common.CommonResultTool; 10 | import top.retain.nd.common.StatusCode; 11 | import top.retain.nd.entity.ExtendCode; 12 | import top.retain.nd.service.IExtendCodeService; 13 | import top.retain.nd.util.SpringSecurityUtil; 14 | 15 | import javax.annotation.Resource; 16 | import javax.servlet.http.HttpSession; 17 | 18 | @RestController 19 | @Api("暗号接口") 20 | @RequestMapping("/extendCode") 21 | @Slf4j 22 | public class ExtendCodeController { 23 | 24 | @Resource 25 | private IExtendCodeService extendCodeService; 26 | 27 | @PostMapping("/match") 28 | @ApiOperation("扩容暗号匹配") 29 | public CommonResult match(@ApiIgnore HttpSession session 30 | , @RequestParam() String code) { 31 | // 校验code是否为空 32 | if (code == null || code.trim().length() == 0) { 33 | return CommonResultTool.fail(StatusCode.CODE_WRONG,"暗号不能为空"); 34 | } 35 | 36 | String account = SpringSecurityUtil.currentUser(session); 37 | return extendCodeService.match(account, code); 38 | } 39 | 40 | @PostMapping("/add") 41 | public CommonResult add(@RequestBody() ExtendCode code) { 42 | // 校验code是否为空 43 | if (code == null || code.getCode().length() == 0) { 44 | return CommonResultTool.fail(StatusCode.CODE_WRONG,"暗号不能为空"); 45 | } 46 | return extendCodeService.add(code); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/controller/SafeController.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.controller; 2 | 3 | import io.swagger.annotations.Api; 4 | import io.swagger.annotations.ApiOperation; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.springframework.web.bind.annotation.*; 7 | import springfox.documentation.annotations.ApiIgnore; 8 | import top.retain.nd.common.CommonResult; 9 | import top.retain.nd.common.CommonResultTool; 10 | import top.retain.nd.service.ISafeFileService; 11 | import top.retain.nd.util.SpringSecurityUtil; 12 | 13 | import javax.annotation.Resource; 14 | import javax.servlet.http.HttpSession; 15 | import java.util.Map; 16 | 17 | /** 18 | * @author Retain 19 | * @date 2021/11/22 12:44 20 | */ 21 | @RestController 22 | @RequestMapping("/safe") 23 | @Api("保险箱接口") 24 | @Slf4j 25 | public class SafeController { 26 | 27 | 28 | 29 | @Resource 30 | private ISafeFileService safeService; 31 | 32 | @GetMapping("/check") 33 | @ApiOperation("查询是否激活保险箱") 34 | public CommonResult check(@ApiIgnore HttpSession session) { 35 | Long account = Long.valueOf(SpringSecurityUtil.currentUser(session)); 36 | return CommonResultTool.success(safeService.check(account)); 37 | } 38 | @GetMapping("/checkEntered") 39 | @ApiOperation("查询是否进入过保险箱") 40 | public CommonResult checkEntered(@ApiIgnore HttpSession session) { 41 | Long account = Long.valueOf(SpringSecurityUtil.currentUser(session)); 42 | return CommonResultTool.success(safeService.checkEntered(account)); 43 | } 44 | @PostMapping("/activate") 45 | @ApiOperation("激活保险箱") 46 | public CommonResult activateSafe(@RequestParam String safeCode 47 | ,@ApiIgnore HttpSession session) { 48 | Long account = Long.valueOf(SpringSecurityUtil.currentUser(session)); 49 | return CommonResultTool.success(safeService.activate(account,safeCode)); 50 | } 51 | 52 | @PostMapping("/match") 53 | @ApiOperation("校验保险箱密钥") 54 | public CommonResult matchCode(@RequestBody Map map 55 | ,@ApiIgnore HttpSession session) { 56 | String safeCode = map.get("safeCode"); 57 | Long account = Long.valueOf(SpringSecurityUtil.currentUser(session)); 58 | return CommonResultTool.success(safeService.matchCode(account,safeCode)); 59 | } 60 | 61 | 62 | @PostMapping("/moveToSafe") 63 | @ApiOperation("移到保险箱") 64 | public CommonResult moveToSafe(@RequestParam("ossPath") String ossPath 65 | ,@ApiIgnore HttpSession session) { 66 | Long account = Long.valueOf(SpringSecurityUtil.currentUser(session)); 67 | return CommonResultTool.success(safeService.moveToSafe(account,ossPath)); 68 | } 69 | 70 | @PostMapping("/moveOutSafe") 71 | @ApiOperation("移出保险箱") 72 | public CommonResult moveOutSafe(@RequestParam("ossPath") String ossPath 73 | ,@ApiIgnore HttpSession session) { 74 | Long account = Long.valueOf(SpringSecurityUtil.currentUser(session)); 75 | return CommonResultTool.success(safeService.moveOutSafe(account,ossPath)); 76 | } 77 | 78 | @GetMapping("/list") 79 | @ApiOperation("列举保险箱文件") 80 | public CommonResult list(@ApiIgnore HttpSession session) { 81 | Long account = Long.valueOf(SpringSecurityUtil.currentUser(session)); 82 | return CommonResultTool.success(safeService.list(account)); 83 | } 84 | 85 | @PostMapping("/lockSafe") 86 | @ApiOperation("锁定保险箱") 87 | public CommonResult lockSafe(@ApiIgnore HttpSession session) { 88 | Long account = Long.valueOf(SpringSecurityUtil.currentUser(session)); 89 | return CommonResultTool.success(safeService.lockSafe(account)); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/controller/ShareController.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.controller; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 4 | import io.swagger.annotations.Api; 5 | import io.swagger.annotations.ApiOperation; 6 | import org.springframework.web.bind.annotation.*; 7 | import springfox.documentation.annotations.ApiIgnore; 8 | import top.retain.nd.common.CommonResult; 9 | import top.retain.nd.common.CommonResultTool; 10 | import top.retain.nd.common.ShareStatus; 11 | import top.retain.nd.entity.Share; 12 | import top.retain.nd.entity.User; 13 | import top.retain.nd.service.IShareService; 14 | import top.retain.nd.util.RedisUtils; 15 | import top.retain.nd.util.SpringSecurityUtil; 16 | 17 | import javax.annotation.Resource; 18 | import javax.servlet.http.HttpSession; 19 | import java.io.IOException; 20 | import java.text.SimpleDateFormat; 21 | import java.util.List; 22 | import java.util.TimeZone; 23 | 24 | import static top.retain.nd.service.impl.FileService.LINK_PREFIX; 25 | 26 | /** 27 | * @author Retain 28 | * @date 2021/12/4 16:31 29 | */ 30 | @RestController 31 | @RequestMapping("/share") 32 | @Api("分享接口") 33 | public class ShareController { 34 | 35 | @Resource 36 | RedisUtils redisUtils; 37 | 38 | // 外部分享接口 39 | 40 | @Resource 41 | private IShareService shareService; 42 | @GetMapping("/getShareDetail") 43 | @ApiOperation("获取分享链接信息") 44 | public CommonResult getShareDetail(@RequestParam("shareCode") String shareCode) throws IOException { 45 | return CommonResultTool.success(shareService.getShareDetail(shareCode)); 46 | } 47 | 48 | @PostMapping("/transfer") 49 | @ApiOperation("转存文件") 50 | public CommonResult transfer(@RequestParam("shareId") String shareId, 51 | @RequestParam("savePath") String savePath, 52 | @ApiIgnore HttpSession session) { 53 | String account = SpringSecurityUtil.currentUser(session); 54 | 55 | return CommonResultTool.success(shareService.transferFile(shareId, savePath, account)); 56 | } 57 | 58 | @GetMapping("/exist") 59 | @ApiOperation("文件是否仍存在") 60 | public CommonResult exist(@RequestParam("shareId") String shareId) { 61 | return CommonResultTool.success(shareService.exist(shareId)); 62 | } 63 | 64 | @PostMapping("/download") 65 | @ApiOperation("非下载,记录下载量") 66 | public CommonResult downloadCount(@RequestParam("shareId") String shareId) { 67 | return CommonResultTool.success(shareService.downloadCount(shareId)); 68 | } 69 | 70 | 71 | // 分享人接口 72 | 73 | @GetMapping("/list") 74 | @ApiOperation("查询我的分享") 75 | public CommonResult list(@ApiIgnore HttpSession session) { 76 | String account = SpringSecurityUtil.currentUser(session); 77 | User user = shareService.getUser(account); 78 | QueryWrapper wrapper = new QueryWrapper(); 79 | wrapper.eq("user_id", user.getId()); 80 | List list = shareService.list(wrapper); 81 | 82 | SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm"); 83 | simpleDateFormat.setTimeZone(TimeZone.getTimeZone("GMT+8")); 84 | for (Share share : list) { 85 | share.setStatusDesc(ShareStatus.getDesc(share.getStatus())); 86 | share.setCreateTimeStr(simpleDateFormat.format(share.getCreateTime())); 87 | share.setExpireTimeStr(simpleDateFormat.format(share.getExpireTime())); 88 | String shareCode = (String)redisUtils.get(share.getId()); 89 | if (shareCode != null) { 90 | share.setShareUrl(LINK_PREFIX + shareCode); 91 | }else { 92 | share.setShareUrl(""); 93 | } 94 | share.setUrl(""); 95 | } 96 | return CommonResultTool.success(list); 97 | } 98 | 99 | @PostMapping("/delete") 100 | @ApiOperation("取消分享") 101 | public CommonResult delete(@RequestParam String id) { 102 | return CommonResultTool.success(shareService.deleteShare(id)); 103 | } 104 | 105 | @PostMapping("/encodeUrl") 106 | @ApiOperation("设置文件提取码-url短链用") 107 | public CommonResult encodeByUrl(@RequestParam String code) { 108 | String shareId = (String) redisUtils.get(code); 109 | return CommonResultTool.success(shareService.encode(shareId)); 110 | } 111 | @PostMapping("/encode") 112 | @ApiOperation("设置文件提取码") 113 | public CommonResult encodeById(@RequestParam String id) { 114 | return CommonResultTool.success(shareService.encode(id)); 115 | } 116 | @GetMapping("/extract") 117 | @ApiOperation("提取文件") 118 | public CommonResult extract(@RequestParam String id, @RequestParam String code) { 119 | return CommonResultTool.success(shareService.extract(id, code)); 120 | } 121 | 122 | } 123 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/controller/TagController.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.controller; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 4 | import io.swagger.annotations.Api; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.springframework.web.bind.annotation.*; 7 | import springfox.documentation.annotations.ApiIgnore; 8 | import top.retain.nd.common.CommonResult; 9 | import top.retain.nd.common.CommonResultTool; 10 | import top.retain.nd.entity.Tag; 11 | import top.retain.nd.entity.User; 12 | import top.retain.nd.service.ITagService; 13 | import top.retain.nd.service.IUserService; 14 | import top.retain.nd.util.SpringSecurityUtil; 15 | 16 | import javax.annotation.Resource; 17 | import javax.servlet.http.HttpSession; 18 | import java.io.FileNotFoundException; 19 | import java.nio.file.FileAlreadyExistsException; 20 | 21 | /** 22 | * @author Retain 23 | * @date 2021/11/11 9:47 24 | */ 25 | @RestController 26 | @RequestMapping("/tag") 27 | @Api("标签类接口") 28 | @Slf4j 29 | public class TagController { 30 | 31 | @Resource 32 | private ITagService tagService; 33 | 34 | 35 | @Resource 36 | private IUserService userService; 37 | 38 | @PostMapping("/add") 39 | public CommonResult addTag(@ApiIgnore HttpSession session, 40 | @RequestBody Tag tag) throws FileAlreadyExistsException { 41 | Long account = Long.valueOf(SpringSecurityUtil.currentUser(session)); 42 | User user = userService.getOne(new QueryWrapper().eq("account", account)); 43 | return CommonResultTool.success(tagService.addTag(tag, user.getId())); 44 | } 45 | 46 | @PostMapping("/add/file") 47 | public CommonResult addTagFile(@ApiIgnore HttpSession session, 48 | @RequestParam String tagName, 49 | @RequestParam String ossPath) throws FileAlreadyExistsException, FileNotFoundException { 50 | Long account = Long.valueOf(SpringSecurityUtil.currentUser(session)); 51 | User user = userService.getOne(new QueryWrapper().eq("account", account)); 52 | return CommonResultTool.success(tagService.addFileToTag(tagName,user.getId(), ossPath)); 53 | } 54 | 55 | @GetMapping("/list") 56 | public CommonResult listTagFiles(@ApiIgnore HttpSession session, 57 | @RequestParam("tagName") String tagName) { 58 | Long account = Long.valueOf(SpringSecurityUtil.currentUser(session)); 59 | User user = userService.getOne(new QueryWrapper().eq("account", account)); 60 | return CommonResultTool.success(tagService.listTagFiles(tagName,user.getId())); 61 | } 62 | 63 | @GetMapping("/all") 64 | public CommonResult getAllTags(@ApiIgnore HttpSession session) { 65 | Long account = Long.valueOf(SpringSecurityUtil.currentUser(session)); 66 | User user = userService.getOne(new QueryWrapper().eq("account", account)); 67 | return CommonResultTool.success(tagService.getAllTags(user.getId())); 68 | } 69 | 70 | @PostMapping("/rename") 71 | public CommonResult rename(@ApiIgnore HttpSession session 72 | ,@RequestParam("tagId") String tagId 73 | ,@RequestParam("newName") String newName) { 74 | Long account = Long.valueOf(SpringSecurityUtil.currentUser(session)); 75 | User user = userService.getOne(new QueryWrapper().eq("account", account)); 76 | return CommonResultTool.success(tagService.rename(user.getId(), tagId, newName)); 77 | } 78 | 79 | @PostMapping("/delete") 80 | public CommonResult delete(@ApiIgnore HttpSession session 81 | ,@RequestParam("tagId") String tagId) { 82 | Long account = Long.valueOf(SpringSecurityUtil.currentUser(session)); 83 | User user = userService.getOne(new QueryWrapper().eq("account", account)); 84 | return CommonResultTool.success(tagService.delete(user.getId(), tagId)); 85 | } 86 | 87 | @PostMapping("/moveOutTag") 88 | public CommonResult moveOutTag(@ApiIgnore HttpSession session, 89 | @RequestParam String tagName, 90 | @RequestParam String ossPath) { 91 | Long account = Long.valueOf(SpringSecurityUtil.currentUser(session)); 92 | User user = userService.getOne(new QueryWrapper().eq("account", account)); 93 | return CommonResultTool.success(tagService.moveOutTag(tagName,user.getId(), ossPath)); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/controller/TaskController.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.controller; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 4 | import io.swagger.annotations.Api; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.springframework.web.bind.annotation.*; 7 | import springfox.documentation.annotations.ApiIgnore; 8 | import top.retain.nd.common.CommonResult; 9 | import top.retain.nd.common.CommonResultTool; 10 | import top.retain.nd.entity.Task; 11 | import top.retain.nd.entity.User; 12 | import top.retain.nd.service.ITaskService; 13 | import top.retain.nd.service.IUserService; 14 | import top.retain.nd.util.SpringSecurityUtil; 15 | 16 | import javax.annotation.Resource; 17 | import javax.servlet.http.HttpServletRequest; 18 | import javax.servlet.http.HttpSession; 19 | 20 | /** 21 | * @author Retain 22 | * @date 2021/11/24 9:04 23 | */ 24 | @RestController 25 | @RequestMapping("/task") 26 | @Api("任务类接口") 27 | @Slf4j 28 | public class TaskController { 29 | 30 | @Resource 31 | private IUserService userService; 32 | 33 | @Resource 34 | private ITaskService taskService; 35 | 36 | @PostMapping("/add") 37 | public CommonResult addTask(HttpServletRequest request, 38 | @RequestParam Long userId, 39 | @RequestBody Task task) { 40 | System.out.println(request); 41 | return CommonResultTool.success(taskService.addTask(task, userId)); 42 | } 43 | 44 | @GetMapping("/list/finished") 45 | public CommonResult listFinished(@ApiIgnore HttpSession session) { 46 | Long account = Long.valueOf(SpringSecurityUtil.currentUser(session)); 47 | User user = userService.getOne(new QueryWrapper().eq("account", account)); 48 | return CommonResultTool.success(taskService.getFinishedTasks(user.getId())); 49 | } 50 | @PostMapping("/update") 51 | public CommonResult update(@RequestParam Long userId, 52 | @RequestBody Task task, 53 | @RequestParam Boolean finished) { 54 | return CommonResultTool.success(taskService.updateTask(userId, task, finished)); 55 | } 56 | @PostMapping("/clear") 57 | public CommonResult clear(@ApiIgnore HttpSession session) { 58 | Long account = Long.valueOf(SpringSecurityUtil.currentUser(session)); 59 | User user = userService.getOne(new QueryWrapper().eq("account", account)); 60 | return CommonResultTool.success(taskService.clear(user.getId())); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/controller/UserController.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.controller; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 4 | import io.swagger.annotations.ApiOperation; 5 | import org.springframework.beans.BeanUtils; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.web.bind.annotation.*; 8 | import org.springframework.web.multipart.MultipartFile; 9 | import springfox.documentation.annotations.ApiIgnore; 10 | import top.retain.nd.common.CommonResult; 11 | import top.retain.nd.common.CommonResultTool; 12 | import top.retain.nd.dto.ForgetPasswordReq; 13 | import top.retain.nd.dto.ForgetSafeCodeReq; 14 | import top.retain.nd.dto.UpdateUserBasicInfoReq; 15 | import top.retain.nd.entity.User; 16 | import top.retain.nd.service.IUserService; 17 | import top.retain.nd.util.SpringSecurityUtil; 18 | 19 | import javax.servlet.http.HttpSession; 20 | import java.text.SimpleDateFormat; 21 | import java.util.Objects; 22 | import java.util.TimeZone; 23 | 24 | /** 25 | * @author Retain 26 | * @date 2021/9/29 18:42 27 | */ 28 | @RestController 29 | @RequestMapping("/user") 30 | public class UserController { 31 | 32 | 33 | @Autowired 34 | IUserService userService; 35 | 36 | 37 | @GetMapping("sts") 38 | public CommonResult getSts(@ApiIgnore HttpSession session) { 39 | String account = SpringSecurityUtil.currentUser(session); 40 | return CommonResultTool.success(userService.getSts(account)); 41 | } 42 | @GetMapping("/currentUser") 43 | public CommonResult currentUser(@ApiIgnore HttpSession session) { 44 | String account = SpringSecurityUtil.currentUser(session); 45 | User user = userService.getOne(new QueryWrapper().eq("account", account)); 46 | user.setPassword(""); 47 | user.setBucketName(""); 48 | user.setSafeCode(""); 49 | user.setIsSafeOn(null); 50 | SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); 51 | simpleDateFormat.setTimeZone(TimeZone.getTimeZone("GMT+8")); 52 | user.setLastLoginTimeStr(simpleDateFormat.format(user.getLastLoginTime())); 53 | user.setCreateTimeStr(simpleDateFormat.format(user.getCreateTime())); 54 | return CommonResultTool.success(user); 55 | } 56 | @RequestMapping("/register") 57 | public CommonResult register(@RequestBody User user) { 58 | Long userId = userService.register(user); 59 | return CommonResultTool.success(userId); 60 | } 61 | 62 | @RequestMapping("/sms/sendCode") 63 | public CommonResult login(@RequestParam("phoneNumber") String phoneNumber 64 | ) { 65 | return CommonResultTool.success(userService.sendVerifyCode(phoneNumber)); 66 | } 67 | 68 | @PostMapping("/updatePhoneNumber") 69 | @ApiOperation("更换手机号") 70 | public CommonResult updatePhoneNumber(@RequestParam("phoneNumber") String phoneNumber, 71 | @RequestParam("code") String code, 72 | @RequestParam("userId") Long userId 73 | ) { 74 | return CommonResultTool.success(userService.updatePhoneNumber(phoneNumber,code, userId)); 75 | } 76 | 77 | @PostMapping("/updatePassword") 78 | @ApiOperation("修改密码") 79 | public CommonResult updatePassword(@RequestParam("oldPassword") String oldPassword, 80 | @RequestParam("newPassword") String newPassword, 81 | @RequestParam("userId") Long userId 82 | ) { 83 | return CommonResultTool.success(userService.updatePassword(oldPassword,newPassword, userId)); 84 | } 85 | 86 | @PostMapping("/forgetPassword") 87 | @ApiOperation("忘记登录密码") 88 | public CommonResult forgetPassword(@RequestBody ForgetPasswordReq req) { 89 | String phoneNumber = req.getPhoneNumber(); 90 | String code = req.getVerifyCode(); 91 | String newPassword = req.getNewPassword(); 92 | return CommonResultTool.success(userService.forgetPassword(phoneNumber,code,newPassword)); 93 | } 94 | 95 | @PostMapping("/forgetSafeCode") 96 | @ApiOperation("忘记保险箱密码") 97 | public CommonResult forgetSafeCode(@RequestBody ForgetSafeCodeReq req) { 98 | String newSafeCode = req.getNewSafeCode(); 99 | String code = req.getVerifyCode(); 100 | Long userId = req.getUserId(); 101 | return CommonResultTool.success(userService.forgetSafeCode(newSafeCode,code,userId)); 102 | } 103 | 104 | @ApiOperation("修改用户基本信息,防止接口暴露修改重要信息") 105 | @PostMapping("/update") 106 | public CommonResult update(@RequestBody UpdateUserBasicInfoReq req, @RequestParam("userId") Long userId) { 107 | if (Objects.isNull(req) || Objects.isNull(userId)) { 108 | throw new RuntimeException("内容不能为空!"); 109 | } 110 | User user = new User(); 111 | BeanUtils.copyProperties(req, user); 112 | user.setId(userId); 113 | return CommonResultTool.success(userService.updateById(user)); 114 | } 115 | 116 | @ApiOperation("上传头像,返回url") 117 | @PostMapping("/avator") 118 | public CommonResult uploadAvator(@RequestParam MultipartFile file, @RequestParam("userId") Long userId) { 119 | if (Objects.isNull(file) || Objects.isNull(userId)) { 120 | throw new RuntimeException("内容不能为空!"); 121 | } 122 | return CommonResultTool.success(userService.uploadAvator(file, userId)); 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/dto/DownloadDirResp.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.dto; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class DownloadDirResp { 7 | private String url; 8 | private String name; 9 | private String foldPath; 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/dto/ForgetPasswordReq.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.dto; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * @author Retain 7 | * @date 2021/12/1 10:38 8 | */ 9 | @Data 10 | public class ForgetPasswordReq { 11 | private String phoneNumber; 12 | 13 | private String verifyCode; 14 | 15 | private String newPassword; 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/dto/ForgetSafeCodeReq.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.dto; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * @author Retain 7 | * @date 2021/12/1 11:14 8 | */ 9 | @Data 10 | public class ForgetSafeCodeReq { 11 | private String newSafeCode; 12 | private Long userId; 13 | private String verifyCode; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/dto/GetFileDetailResp.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.dto; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * @author Retain 7 | * @date 2021/11/22 19:15 8 | */ 9 | @Data 10 | public class GetFileDetailResp { 11 | private String name; 12 | private Long size; 13 | private String type; 14 | private String createTimeStr; 15 | private String ossPath; 16 | private String lastModified; 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/dto/GetFinishedTasksResp.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.dto; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * @author Retain 7 | * @date 2021/11/24 10:54 8 | */ 9 | @Data 10 | public class GetFinishedTasksResp { 11 | private String id; 12 | 13 | /** 14 | * 文件名 15 | */ 16 | private String fileName; 17 | 18 | /** 19 | * 文件大小 20 | */ 21 | private Double size; 22 | 23 | /** 24 | * 文件类型 25 | */ 26 | private String fileType; 27 | 28 | /** 29 | * 文件上传路径 30 | */ 31 | private String filePath; 32 | 33 | /** 34 | * 是否已完成 35 | */ 36 | private Boolean isFinished; 37 | 38 | private String createTimeStr; 39 | 40 | /** 41 | * 是否被取消 42 | */ 43 | private Boolean isCancelled; 44 | 45 | private Long userId; 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/dto/GetUserFIleSpaceResp.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.dto; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class GetUserFIleSpaceResp { 7 | 8 | private long used; 9 | private long total; 10 | private String spaceStr; 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/dto/ListFilesPagedResp.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.dto; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.Date; 6 | 7 | /** 8 | * @author Retain 9 | * @date 2021/10/3 15:20 10 | */ 11 | @Data 12 | public class ListFilesPagedResp { 13 | String key; 14 | long size; 15 | Date lastModified; 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/dto/STSResp.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.dto; 2 | 3 | import com.aliyuncs.auth.sts.AssumeRoleResponse; 4 | import lombok.Data; 5 | 6 | /** 7 | * @author Retain 8 | * @date 2021/12/18 18:09 9 | */ 10 | @Data 11 | public class STSResp { 12 | private AssumeRoleResponse.Credentials credentials; 13 | 14 | private String region; 15 | 16 | private String bucketName; 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/dto/UpdateUserBasicInfoReq.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.dto; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * @author Retain 7 | * @date 2021/11/30 11:34 8 | */ 9 | @Data 10 | public class UpdateUserBasicInfoReq { 11 | 12 | private String name; 13 | private String avator; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/entity/ExtendCode.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.FieldFill; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableName; 6 | import lombok.Data; 7 | 8 | import java.util.Date; 9 | 10 | @Data 11 | @TableName("extend_code") 12 | public class ExtendCode { 13 | 14 | private String id; 15 | private String code; 16 | @TableField("extend_size") 17 | private Long extendSize; 18 | @TableField( value = "create_time", fill = FieldFill.INSERT) 19 | private Date createTime; 20 | 21 | @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE) 22 | private Date updateTime; 23 | @TableField("expire_time") 24 | private Date expireTime; 25 | private boolean deleted; 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/entity/SafeFile.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.entity; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | import java.util.Date; 7 | 8 | /** 9 | * safe 10 | * @author Retain 11 | */ 12 | @Data 13 | public class SafeFile implements Serializable { 14 | private String id; 15 | 16 | /** 17 | * 保险箱所属用户 18 | */ 19 | private Long userId; 20 | 21 | /** 22 | * 用户文件 23 | */ 24 | private String fileId; 25 | 26 | private Date createTime; 27 | 28 | private Date updateTime; 29 | 30 | private Boolean deleted; 31 | 32 | private static final long serialVersionUID = 1L; 33 | 34 | @Override 35 | public boolean equals(Object that) { 36 | if (this == that) { 37 | return true; 38 | } 39 | if (that == null) { 40 | return false; 41 | } 42 | if (getClass() != that.getClass()) { 43 | return false; 44 | } 45 | SafeFile other = (SafeFile) that; 46 | return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId())) 47 | && (this.getUserId() == null ? other.getUserId() == null : this.getUserId().equals(other.getUserId())) 48 | && (this.getFileId() == null ? other.getFileId() == null : this.getFileId().equals(other.getFileId())) 49 | && (this.getCreateTime() == null ? other.getCreateTime() == null : this.getCreateTime().equals(other.getCreateTime())) 50 | && (this.getUpdateTime() == null ? other.getUpdateTime() == null : this.getUpdateTime().equals(other.getUpdateTime())) 51 | && (this.getDeleted() == null ? other.getDeleted() == null : this.getDeleted().equals(other.getDeleted())); 52 | } 53 | 54 | @Override 55 | public int hashCode() { 56 | final int prime = 31; 57 | int result = 1; 58 | result = prime * result + ((getId() == null) ? 0 : getId().hashCode()); 59 | result = prime * result + ((getUserId() == null) ? 0 : getUserId().hashCode()); 60 | result = prime * result + ((getFileId() == null) ? 0 : getFileId().hashCode()); 61 | result = prime * result + ((getCreateTime() == null) ? 0 : getCreateTime().hashCode()); 62 | result = prime * result + ((getUpdateTime() == null) ? 0 : getUpdateTime().hashCode()); 63 | result = prime * result + ((getDeleted() == null) ? 0 : getDeleted().hashCode()); 64 | return result; 65 | } 66 | 67 | @Override 68 | public String toString() { 69 | StringBuilder sb = new StringBuilder(); 70 | sb.append(getClass().getSimpleName()); 71 | sb.append(" ["); 72 | sb.append("Hash = ").append(hashCode()); 73 | sb.append(", id=").append(id); 74 | sb.append(", userId=").append(userId); 75 | sb.append(", fileId=").append(fileId); 76 | sb.append(", createTime=").append(createTime); 77 | sb.append(", updateTime=").append(updateTime); 78 | sb.append(", deleted=").append(deleted); 79 | sb.append(", serialVersionUID=").append(serialVersionUID); 80 | sb.append("]"); 81 | return sb.toString(); 82 | } 83 | } -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/entity/Share.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.FieldFill; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import lombok.Data; 6 | 7 | import java.io.Serializable; 8 | import java.util.Date; 9 | 10 | /** 11 | * share 12 | * @author Retain 13 | */ 14 | @Data 15 | public class Share implements Serializable { 16 | private String id; 17 | 18 | private String fileName; 19 | 20 | private String fileType; 21 | 22 | private String userName; 23 | 24 | @TableField(fill = FieldFill.INSERT) 25 | private Date createTime; 26 | 27 | @TableField(exist = false) 28 | private String createTimeStr; 29 | 30 | private Date expireTime; 31 | 32 | @TableField(exist = false) 33 | private String expireTimeStr; 34 | 35 | private Boolean hasExpired; 36 | 37 | private String url; 38 | 39 | @TableField("user_id") 40 | private Long userId; 41 | 42 | @TableField("file_path") 43 | private String filePath; 44 | 45 | @TableField("size") 46 | private Long size; 47 | 48 | @TableField("view_count") 49 | private int viewCount; 50 | 51 | @TableField("download_count") 52 | private int downloadCount; 53 | 54 | @TableField("transfer_count") 55 | private int transferCount; 56 | 57 | @TableField("status") 58 | private int status; 59 | 60 | @TableField("is_encoded") 61 | private boolean isEncoded; 62 | 63 | @TableField("code") 64 | private String code; 65 | 66 | @TableField(exist = false) 67 | private String shareUrl; 68 | 69 | @TableField(exist = false) 70 | private String statusDesc; 71 | private static final long serialVersionUID = 1L; 72 | 73 | @Override 74 | public boolean equals(Object that) { 75 | if (this == that) { 76 | return true; 77 | } 78 | if (that == null) { 79 | return false; 80 | } 81 | if (getClass() != that.getClass()) { 82 | return false; 83 | } 84 | Share other = (Share) that; 85 | return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId())) 86 | && (this.getFileName() == null ? other.getFileName() == null : this.getFileName().equals(other.getFileName())) 87 | && (this.getFileType() == null ? other.getFileType() == null : this.getFileType().equals(other.getFileType())) 88 | && (this.getUserName() == null ? other.getUserName() == null : this.getUserName().equals(other.getUserName())) 89 | && (this.getCreateTime() == null ? other.getCreateTime() == null : this.getCreateTime().equals(other.getCreateTime())) 90 | && (this.getExpireTime() == null ? other.getExpireTime() == null : this.getExpireTime().equals(other.getExpireTime())) 91 | && (this.getHasExpired() == null ? other.getHasExpired() == null : this.getHasExpired().equals(other.getHasExpired())) 92 | && (this.getUrl() == null ? other.getUrl() == null : this.getUrl().equals(other.getUrl())); 93 | } 94 | 95 | @Override 96 | public int hashCode() { 97 | final int prime = 31; 98 | int result = 1; 99 | result = prime * result + ((getId() == null) ? 0 : getId().hashCode()); 100 | result = prime * result + ((getFileName() == null) ? 0 : getFileName().hashCode()); 101 | result = prime * result + ((getFileType() == null) ? 0 : getFileType().hashCode()); 102 | result = prime * result + ((getUserName() == null) ? 0 : getUserName().hashCode()); 103 | result = prime * result + ((getCreateTime() == null) ? 0 : getCreateTime().hashCode()); 104 | result = prime * result + ((getExpireTime() == null) ? 0 : getExpireTime().hashCode()); 105 | result = prime * result + ((getHasExpired() == null) ? 0 : getHasExpired().hashCode()); 106 | result = prime * result + ((getUrl() == null) ? 0 : getUrl().hashCode()); 107 | return result; 108 | } 109 | 110 | @Override 111 | public String toString() { 112 | StringBuilder sb = new StringBuilder(); 113 | sb.append(getClass().getSimpleName()); 114 | sb.append(" ["); 115 | sb.append("Hash = ").append(hashCode()); 116 | sb.append(", id=").append(id); 117 | sb.append(", fileName=").append(fileName); 118 | sb.append(", fileType=").append(fileType); 119 | sb.append(", userName=").append(userName); 120 | sb.append(", createTime=").append(createTime); 121 | sb.append(", expireTime=").append(expireTime); 122 | sb.append(", hasExpired=").append(hasExpired); 123 | sb.append(", url=").append(url); 124 | sb.append(", serialVersionUID=").append(serialVersionUID); 125 | sb.append("]"); 126 | return sb.toString(); 127 | } 128 | } -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/entity/Tag.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.FieldFill; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import lombok.Data; 7 | 8 | import java.util.Date; 9 | 10 | /** 11 | * @author Retain 12 | * @date 2021/11/11 9:22 13 | */ 14 | @Data 15 | public class Tag { 16 | 17 | @TableId 18 | private String id; 19 | 20 | @TableField() 21 | private String name; 22 | 23 | @TableField( value = "create_time", fill = FieldFill.INSERT) 24 | private Date createTime; 25 | 26 | @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE) 27 | private Date updateTime; 28 | 29 | @TableField() 30 | private Boolean deleted; 31 | 32 | @TableField("user_id") 33 | private Long userId; 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/entity/TagFile.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.entity; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | import java.util.Date; 7 | 8 | /** 9 | * tag_file 10 | * @author 11 | */ 12 | @Data 13 | public class TagFile implements Serializable { 14 | private String id; 15 | 16 | private String fileId; 17 | 18 | private String tagId; 19 | 20 | private Date createTime; 21 | 22 | private Date updateTime; 23 | 24 | private Boolean deleted; 25 | 26 | private static final long serialVersionUID = 1L; 27 | 28 | @Override 29 | public boolean equals(Object that) { 30 | if (this == that) { 31 | return true; 32 | } 33 | if (that == null) { 34 | return false; 35 | } 36 | if (getClass() != that.getClass()) { 37 | return false; 38 | } 39 | TagFile other = (TagFile) that; 40 | return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId())) 41 | && (this.getFileId() == null ? other.getFileId() == null : this.getFileId().equals(other.getFileId())) 42 | && (this.getTagId() == null ? other.getTagId() == null : this.getTagId().equals(other.getTagId())) 43 | && (this.getCreateTime() == null ? other.getCreateTime() == null : this.getCreateTime().equals(other.getCreateTime())) 44 | && (this.getUpdateTime() == null ? other.getUpdateTime() == null : this.getUpdateTime().equals(other.getUpdateTime())) 45 | && (this.getDeleted() == null ? other.getDeleted() == null : this.getDeleted().equals(other.getDeleted())); 46 | } 47 | 48 | @Override 49 | public int hashCode() { 50 | final int prime = 31; 51 | int result = 1; 52 | result = prime * result + ((getId() == null) ? 0 : getId().hashCode()); 53 | result = prime * result + ((getFileId() == null) ? 0 : getFileId().hashCode()); 54 | result = prime * result + ((getTagId() == null) ? 0 : getTagId().hashCode()); 55 | result = prime * result + ((getCreateTime() == null) ? 0 : getCreateTime().hashCode()); 56 | result = prime * result + ((getUpdateTime() == null) ? 0 : getUpdateTime().hashCode()); 57 | result = prime * result + ((getDeleted() == null) ? 0 : getDeleted().hashCode()); 58 | return result; 59 | } 60 | 61 | @Override 62 | public String toString() { 63 | StringBuilder sb = new StringBuilder(); 64 | sb.append(getClass().getSimpleName()); 65 | sb.append(" ["); 66 | sb.append("Hash = ").append(hashCode()); 67 | sb.append(", id=").append(id); 68 | sb.append(", fileId=").append(fileId); 69 | sb.append(", tagId=").append(tagId); 70 | sb.append(", createTime=").append(createTime); 71 | sb.append(", updateTime=").append(updateTime); 72 | sb.append(", deleted=").append(deleted); 73 | sb.append(", serialVersionUID=").append(serialVersionUID); 74 | sb.append("]"); 75 | return sb.toString(); 76 | } 77 | } -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/entity/Task.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.FieldFill; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import lombok.Data; 6 | 7 | import java.io.Serializable; 8 | import java.util.Date; 9 | 10 | /** 11 | * task 12 | * @author Retain 13 | */ 14 | @Data 15 | public class Task implements Serializable { 16 | private String id; 17 | 18 | /** 19 | * 文件名 20 | */ 21 | private String fileName; 22 | 23 | /** 24 | * 文件大小 25 | */ 26 | private Double size; 27 | 28 | /** 29 | * 文件类型 30 | */ 31 | private String fileType; 32 | 33 | /** 34 | * 文件上传路径 35 | */ 36 | private String filePath; 37 | 38 | /** 39 | * 是否已完成 40 | */ 41 | private Boolean isFinished; 42 | 43 | @TableField( value = "create_time", fill = FieldFill.INSERT) 44 | private Date createTime; 45 | 46 | @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE) 47 | private Date updateTime; 48 | 49 | /** 50 | * 是否被取消 51 | */ 52 | private Boolean isCancelled; 53 | 54 | private Long userId; 55 | 56 | 57 | private static final long serialVersionUID = 1L; 58 | 59 | @Override 60 | public boolean equals(Object that) { 61 | if (this == that) { 62 | return true; 63 | } 64 | if (that == null) { 65 | return false; 66 | } 67 | if (getClass() != that.getClass()) { 68 | return false; 69 | } 70 | Task other = (Task) that; 71 | return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId())) 72 | && (this.getFileName() == null ? other.getFileName() == null : this.getFileName().equals(other.getFileName())) 73 | && (this.getSize() == null ? other.getSize() == null : this.getSize().equals(other.getSize())) 74 | && (this.getFileType() == null ? other.getFileType() == null : this.getFileType().equals(other.getFileType())) 75 | && (this.getFilePath() == null ? other.getFilePath() == null : this.getFilePath().equals(other.getFilePath())) 76 | && (this.getIsFinished() == null ? other.getIsFinished() == null : this.getIsFinished().equals(other.getIsFinished())) 77 | && (this.getCreateTime() == null ? other.getCreateTime() == null : this.getCreateTime().equals(other.getCreateTime())) 78 | && (this.getUpdateTime() == null ? other.getUpdateTime() == null : this.getUpdateTime().equals(other.getUpdateTime())) 79 | && (this.getIsCancelled() == null ? other.getIsCancelled() == null : this.getIsCancelled().equals(other.getIsCancelled())); 80 | } 81 | 82 | @Override 83 | public int hashCode() { 84 | final int prime = 31; 85 | int result = 1; 86 | result = prime * result + ((getId() == null) ? 0 : getId().hashCode()); 87 | result = prime * result + ((getFileName() == null) ? 0 : getFileName().hashCode()); 88 | result = prime * result + ((getSize() == null) ? 0 : getSize().hashCode()); 89 | result = prime * result + ((getFileType() == null) ? 0 : getFileType().hashCode()); 90 | result = prime * result + ((getFilePath() == null) ? 0 : getFilePath().hashCode()); 91 | result = prime * result + ((getIsFinished() == null) ? 0 : getIsFinished().hashCode()); 92 | result = prime * result + ((getCreateTime() == null) ? 0 : getCreateTime().hashCode()); 93 | result = prime * result + ((getUpdateTime() == null) ? 0 : getUpdateTime().hashCode()); 94 | result = prime * result + ((getIsCancelled() == null) ? 0 : getIsCancelled().hashCode()); 95 | return result; 96 | } 97 | 98 | @Override 99 | public String toString() { 100 | StringBuilder sb = new StringBuilder(); 101 | sb.append(getClass().getSimpleName()); 102 | sb.append(" ["); 103 | sb.append("Hash = ").append(hashCode()); 104 | sb.append(", id=").append(id); 105 | sb.append(", fileName=").append(fileName); 106 | sb.append(", size=").append(size); 107 | sb.append(", fileType=").append(fileType); 108 | sb.append(", filePath=").append(filePath); 109 | sb.append(", isfinished=").append(isFinished); 110 | sb.append(", createTime=").append(createTime); 111 | sb.append(", updateTime=").append(updateTime); 112 | sb.append(", isCancelled=").append(isCancelled); 113 | sb.append(", serialVersionUID=").append(serialVersionUID); 114 | sb.append("]"); 115 | return sb.toString(); 116 | } 117 | } -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/entity/User.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.*; 4 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 5 | import io.swagger.annotations.ApiModel; 6 | import lombok.Getter; 7 | import lombok.Setter; 8 | import lombok.ToString; 9 | import lombok.experimental.Accessors; 10 | import org.springframework.security.core.GrantedAuthority; 11 | import org.springframework.security.core.userdetails.UserDetails; 12 | 13 | import java.io.Serializable; 14 | import java.security.Principal; 15 | import java.util.Collection; 16 | import java.util.Date; 17 | 18 | /** 19 | * @author Retain 20 | * @date 2021/9/29 16:43 21 | */ 22 | @TableName("user") 23 | @ApiModel("用户表") 24 | @Getter 25 | @Setter 26 | @ToString 27 | @Accessors(chain = true) 28 | @JsonIgnoreProperties({"bucketName, safeCode"}) 29 | public class User implements Serializable, UserDetails, Principal { 30 | private static final long serialVersionUID = 1L; 31 | 32 | @TableId(value = "id", type = IdType.AUTO) 33 | private Long id; 34 | 35 | @TableField() 36 | private String name; 37 | 38 | 39 | @TableField() 40 | private String account; 41 | 42 | @TableField() 43 | private String password; 44 | 45 | @TableField() 46 | private String phoneNumber; 47 | @TableField(fill= FieldFill.INSERT, updateStrategy = FieldStrategy.NOT_NULL ) 48 | private Date createTime; 49 | 50 | @TableField(fill= FieldFill.INSERT_UPDATE) 51 | private Date updateTime; 52 | 53 | @TableField("deleted") 54 | private boolean deleted = false; 55 | 56 | @TableField 57 | private String bucketName; 58 | 59 | @TableField 60 | private String avator; 61 | 62 | @TableField("safe_on") 63 | private Boolean isSafeOn; 64 | 65 | @TableField("safe_code") 66 | private String safeCode; 67 | @TableField(value = "last_login_time", fill= FieldFill.INSERT) 68 | private Date lastLoginTime; 69 | 70 | @TableField("total_space") 71 | private Long totalSpace; 72 | 73 | /** 74 | * 格式化日期 75 | */ 76 | @TableField(exist = false) 77 | private String lastLoginTimeStr; 78 | 79 | @TableField(exist = false) 80 | private String createTimeStr; 81 | @Override 82 | public Collection getAuthorities() { 83 | return null; 84 | } 85 | 86 | @Override 87 | public String getUsername() { 88 | return getAccount(); 89 | } 90 | 91 | @Override 92 | public boolean isAccountNonExpired() { 93 | return true; 94 | } 95 | 96 | @Override 97 | public boolean isAccountNonLocked() { 98 | return true; 99 | } 100 | 101 | @Override 102 | public boolean isCredentialsNonExpired() { 103 | return true; 104 | } 105 | 106 | @Override 107 | public boolean isEnabled() { 108 | return !isDeleted(); 109 | } 110 | } 111 | 112 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/entity/UserCode.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.FieldFill; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import lombok.Data; 6 | 7 | import java.util.Date; 8 | 9 | @Data 10 | public class UserCode { 11 | private Long id; 12 | private Long userId; 13 | private String code; 14 | @TableField( value = "create_time", fill = FieldFill.INSERT) 15 | private Date createTime; 16 | 17 | @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE) 18 | private Date updateTime; 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/entity/UserFile.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.FieldFill; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableName; 7 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 8 | import lombok.Data; 9 | 10 | import java.util.Date; 11 | 12 | /** 13 | * @author Retain 14 | * @date 2021/11/6 17:16 15 | */ 16 | @Data 17 | @TableName("file") 18 | @JsonIgnoreProperties( {"userId", "updateTime", "deleted", "parentId"}) 19 | public class UserFile { 20 | @TableId 21 | private String id; 22 | 23 | @TableField() 24 | private String name; 25 | 26 | @TableField() 27 | private Long size; 28 | 29 | @TableField("user_id") 30 | private Long userId; 31 | 32 | @TableField() 33 | private String type; 34 | 35 | @TableField("is_dir") 36 | private Boolean isDir; 37 | 38 | @TableField( value = "create_time", fill = FieldFill.INSERT) 39 | private Date createTime; 40 | 41 | @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE) 42 | private Date updateTime; 43 | 44 | @TableField() 45 | private Boolean deleted; 46 | 47 | @TableField("oss_path") 48 | private String ossPath; 49 | 50 | @TableField("request_url") 51 | private String requestUrl; 52 | 53 | @TableField("parent_id") 54 | private String parentId; 55 | 56 | @TableField(exist = false) 57 | private String lastModified; 58 | 59 | @TableField("in_safe") 60 | private Boolean inSafe; 61 | 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/exception/CodeWrongException.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.exception; 2 | 3 | /** 4 | * @author Retain 5 | * @date 2021/12/1 11:19 6 | */ 7 | public class CodeWrongException extends RuntimeException{ 8 | /** 9 | * Constructs a new runtime exception with {@code null} as its 10 | * detail message. The cause is not initialized, and may subsequently be 11 | * initialized by a call to {@link #initCause}. 12 | */ 13 | public CodeWrongException() { 14 | super(); 15 | } 16 | 17 | /** 18 | * Constructs a new runtime exception with the specified detail message. 19 | * The cause is not initialized, and may subsequently be initialized by a 20 | * call to {@link #initCause}. 21 | * 22 | * @param message the detail message. The detail message is saved for 23 | * later retrieval by the {@link #getMessage()} method. 24 | */ 25 | public CodeWrongException(String message) { 26 | super(message); 27 | } 28 | 29 | /** 30 | * Constructs a new runtime exception with the specified detail message and 31 | * cause.

Note that the detail message associated with 32 | * {@code cause} is not automatically incorporated in 33 | * this runtime exception's detail message. 34 | * 35 | * @param message the detail message (which is saved for later retrieval 36 | * by the {@link #getMessage()} method). 37 | * @param cause the cause (which is saved for later retrieval by the 38 | * {@link #getCause()} method). (A null value is 39 | * permitted, and indicates that the cause is nonexistent or 40 | * unknown.) 41 | * @since 1.4 42 | */ 43 | public CodeWrongException(String message, Throwable cause) { 44 | super(message, cause); 45 | } 46 | 47 | /** 48 | * Constructs a new runtime exception with the specified cause and a 49 | * detail message of (cause==null ? null : cause.toString()) 50 | * (which typically contains the class and detail message of 51 | * cause). This constructor is useful for runtime exceptions 52 | * that are little more than wrappers for other throwables. 53 | * 54 | * @param cause the cause (which is saved for later retrieval by the 55 | * {@link #getCause()} method). (A null value is 56 | * permitted, and indicates that the cause is nonexistent or 57 | * unknown.) 58 | * @since 1.4 59 | */ 60 | public CodeWrongException(Throwable cause) { 61 | super(cause); 62 | } 63 | 64 | /** 65 | * Constructs a new runtime exception with the specified detail 66 | * message, cause, suppression enabled or disabled, and writable 67 | * stack trace enabled or disabled. 68 | * 69 | * @param message the detail message. 70 | * @param cause the cause. (A {@code null} value is permitted, 71 | * and indicates that the cause is nonexistent or unknown.) 72 | * @param enableSuppression whether or not suppression is enabled 73 | * or disabled 74 | * @param writableStackTrace whether or not the stack trace should 75 | * be writable 76 | * @since 1.7 77 | */ 78 | protected CodeWrongException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { 79 | super(message, cause, enableSuppression, writableStackTrace); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/exception/DownloadException.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.exception; 2 | 3 | /** 4 | * @author Retain 5 | * @date 2021/9/29 16:33 6 | */ 7 | public class DownloadException extends RuntimeException{ 8 | public DownloadException() { 9 | } 10 | 11 | public DownloadException(String message) { 12 | super(message); 13 | } 14 | 15 | public DownloadException(String message, Throwable cause) { 16 | super(message, cause); 17 | } 18 | 19 | public DownloadException(Throwable cause) { 20 | super(cause); 21 | } 22 | 23 | public DownloadException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { 24 | super(message, cause, enableSuppression, writableStackTrace); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/exception/FileHasExpiredOrNonExist.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.exception; 2 | 3 | /** 4 | * @author Retain 5 | * @date 2021/12/4 17:32 6 | */ 7 | public class FileHasExpiredOrNonExist extends RuntimeException { 8 | /** 9 | * Constructs a new runtime exception with {@code null} as its 10 | * detail message. The cause is not initialized, and may subsequently be 11 | * initialized by a call to {@link #initCause}. 12 | */ 13 | public FileHasExpiredOrNonExist() { 14 | super(); 15 | } 16 | 17 | /** 18 | * Constructs a new runtime exception with the specified detail message. 19 | * The cause is not initialized, and may subsequently be initialized by a 20 | * call to {@link #initCause}. 21 | * 22 | * @param message the detail message. The detail message is saved for 23 | * later retrieval by the {@link #getMessage()} method. 24 | */ 25 | public FileHasExpiredOrNonExist(String message) { 26 | super(message); 27 | } 28 | 29 | /** 30 | * Constructs a new runtime exception with the specified detail message and 31 | * cause.

Note that the detail message associated with 32 | * {@code cause} is not automatically incorporated in 33 | * this runtime exception's detail message. 34 | * 35 | * @param message the detail message (which is saved for later retrieval 36 | * by the {@link #getMessage()} method). 37 | * @param cause the cause (which is saved for later retrieval by the 38 | * {@link #getCause()} method). (A null value is 39 | * permitted, and indicates that the cause is nonexistent or 40 | * unknown.) 41 | * @since 1.4 42 | */ 43 | public FileHasExpiredOrNonExist(String message, Throwable cause) { 44 | super(message, cause); 45 | } 46 | 47 | /** 48 | * Constructs a new runtime exception with the specified cause and a 49 | * detail message of (cause==null ? null : cause.toString()) 50 | * (which typically contains the class and detail message of 51 | * cause). This constructor is useful for runtime exceptions 52 | * that are little more than wrappers for other throwables. 53 | * 54 | * @param cause the cause (which is saved for later retrieval by the 55 | * {@link #getCause()} method). (A null value is 56 | * permitted, and indicates that the cause is nonexistent or 57 | * unknown.) 58 | * @since 1.4 59 | */ 60 | public FileHasExpiredOrNonExist(Throwable cause) { 61 | super(cause); 62 | } 63 | 64 | /** 65 | * Constructs a new runtime exception with the specified detail 66 | * message, cause, suppression enabled or disabled, and writable 67 | * stack trace enabled or disabled. 68 | * 69 | * @param message the detail message. 70 | * @param cause the cause. (A {@code null} value is permitted, 71 | * and indicates that the cause is nonexistent or unknown.) 72 | * @param enableSuppression whether or not suppression is enabled 73 | * or disabled 74 | * @param writableStackTrace whether or not the stack trace should 75 | * be writable 76 | * @since 1.7 77 | */ 78 | protected FileHasExpiredOrNonExist(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { 79 | super(message, cause, enableSuppression, writableStackTrace); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/exception/SmsCodeException.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.exception; 2 | 3 | /** 4 | * @author Retain 5 | * @date 2021/10/21 10:27 6 | */ 7 | public class SmsCodeException extends Throwable { 8 | public SmsCodeException() { 9 | } 10 | 11 | public SmsCodeException(String message) { 12 | super(message); 13 | } 14 | 15 | public SmsCodeException(String message, Throwable cause) { 16 | super(message, cause); 17 | } 18 | 19 | public SmsCodeException(Throwable cause) { 20 | super(cause); 21 | } 22 | 23 | public SmsCodeException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { 24 | super(message, cause, enableSuppression, writableStackTrace); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/exception/TagFileAlreadyExistException.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.exception; 2 | 3 | /** 4 | * @author Retain 5 | * @date 2021/11/18 10:41 6 | */ 7 | public class TagFileAlreadyExistException extends RuntimeException{ 8 | /** 9 | * Constructs a new runtime exception with {@code null} as its 10 | * detail message. The cause is not initialized, and may subsequently be 11 | * initialized by a call to {@link #initCause}. 12 | */ 13 | public TagFileAlreadyExistException() { 14 | super(); 15 | } 16 | 17 | /** 18 | * Constructs a new runtime exception with the specified detail message. 19 | * The cause is not initialized, and may subsequently be initialized by a 20 | * call to {@link #initCause}. 21 | * 22 | * @param message the detail message. The detail message is saved for 23 | * later retrieval by the {@link #getMessage()} method. 24 | */ 25 | public TagFileAlreadyExistException(String message) { 26 | super(message); 27 | } 28 | 29 | /** 30 | * Constructs a new runtime exception with the specified detail message and 31 | * cause.

Note that the detail message associated with 32 | * {@code cause} is not automatically incorporated in 33 | * this runtime exception's detail message. 34 | * 35 | * @param message the detail message (which is saved for later retrieval 36 | * by the {@link #getMessage()} method). 37 | * @param cause the cause (which is saved for later retrieval by the 38 | * {@link #getCause()} method). (A null value is 39 | * permitted, and indicates that the cause is nonexistent or 40 | * unknown.) 41 | * @since 1.4 42 | */ 43 | public TagFileAlreadyExistException(String message, Throwable cause) { 44 | super(message, cause); 45 | } 46 | 47 | /** 48 | * Constructs a new runtime exception with the specified cause and a 49 | * detail message of (cause==null ? null : cause.toString()) 50 | * (which typically contains the class and detail message of 51 | * cause). This constructor is useful for runtime exceptions 52 | * that are little more than wrappers for other throwables. 53 | * 54 | * @param cause the cause (which is saved for later retrieval by the 55 | * {@link #getCause()} method). (A null value is 56 | * permitted, and indicates that the cause is nonexistent or 57 | * unknown.) 58 | * @since 1.4 59 | */ 60 | public TagFileAlreadyExistException(Throwable cause) { 61 | super(cause); 62 | } 63 | 64 | /** 65 | * Constructs a new runtime exception with the specified detail 66 | * message, cause, suppression enabled or disabled, and writable 67 | * stack trace enabled or disabled. 68 | * 69 | * @param message the detail message. 70 | * @param cause the cause. (A {@code null} value is permitted, 71 | * and indicates that the cause is nonexistent or unknown.) 72 | * @param enableSuppression whether or not suppression is enabled 73 | * or disabled 74 | * @param writableStackTrace whether or not the stack trace should 75 | * be writable 76 | * @since 1.7 77 | */ 78 | protected TagFileAlreadyExistException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { 79 | super(message, cause, enableSuppression, writableStackTrace); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/exception/TagNotExistException.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.exception; 2 | 3 | /** 4 | * @author Retain 5 | * @date 2021/11/18 10:19 6 | */ 7 | public class TagNotExistException extends RuntimeException{ 8 | /** 9 | * Constructs a new runtime exception with {@code null} as its 10 | * detail message. The cause is not initialized, and may subsequently be 11 | * initialized by a call to {@link #initCause}. 12 | */ 13 | public TagNotExistException() { 14 | super(); 15 | } 16 | 17 | /** 18 | * Constructs a new runtime exception with the specified detail message. 19 | * The cause is not initialized, and may subsequently be initialized by a 20 | * call to {@link #initCause}. 21 | * 22 | * @param message the detail message. The detail message is saved for 23 | * later retrieval by the {@link #getMessage()} method. 24 | */ 25 | public TagNotExistException(String message) { 26 | super(message); 27 | } 28 | 29 | /** 30 | * Constructs a new runtime exception with the specified detail message and 31 | * cause.

Note that the detail message associated with 32 | * {@code cause} is not automatically incorporated in 33 | * this runtime exception's detail message. 34 | * 35 | * @param message the detail message (which is saved for later retrieval 36 | * by the {@link #getMessage()} method). 37 | * @param cause the cause (which is saved for later retrieval by the 38 | * {@link #getCause()} method). (A null value is 39 | * permitted, and indicates that the cause is nonexistent or 40 | * unknown.) 41 | * @since 1.4 42 | */ 43 | public TagNotExistException(String message, Throwable cause) { 44 | super(message, cause); 45 | } 46 | 47 | /** 48 | * Constructs a new runtime exception with the specified cause and a 49 | * detail message of (cause==null ? null : cause.toString()) 50 | * (which typically contains the class and detail message of 51 | * cause). This constructor is useful for runtime exceptions 52 | * that are little more than wrappers for other throwables. 53 | * 54 | * @param cause the cause (which is saved for later retrieval by the 55 | * {@link #getCause()} method). (A null value is 56 | * permitted, and indicates that the cause is nonexistent or 57 | * unknown.) 58 | * @since 1.4 59 | */ 60 | public TagNotExistException(Throwable cause) { 61 | super(cause); 62 | } 63 | 64 | /** 65 | * Constructs a new runtime exception with the specified detail 66 | * message, cause, suppression enabled or disabled, and writable 67 | * stack trace enabled or disabled. 68 | * 69 | * @param message the detail message. 70 | * @param cause the cause. (A {@code null} value is permitted, 71 | * and indicates that the cause is nonexistent or unknown.) 72 | * @param enableSuppression whether or not suppression is enabled 73 | * or disabled 74 | * @param writableStackTrace whether or not the stack trace should 75 | * be writable 76 | * @since 1.7 77 | */ 78 | protected TagNotExistException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { 79 | super(message, cause, enableSuppression, writableStackTrace); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/exception/UploadException.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.exception; 2 | 3 | /** 4 | * @author Retain 5 | * @date 2021/9/29 16:33 6 | */ 7 | public class UploadException extends RuntimeException{ 8 | public UploadException() { 9 | } 10 | 11 | public UploadException(String message) { 12 | super(message); 13 | } 14 | 15 | public UploadException(String message, Throwable cause) { 16 | super(message, cause); 17 | } 18 | 19 | public UploadException(Throwable cause) { 20 | super(cause); 21 | } 22 | 23 | public UploadException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { 24 | super(message, cause, enableSuppression, writableStackTrace); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/exception/UserExistException.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.exception; 2 | 3 | /** 4 | * @author Retain 5 | * @date 2021/9/29 18:59 6 | */ 7 | public class UserExistException extends RuntimeException{ 8 | public UserExistException() { 9 | } 10 | 11 | public UserExistException(String message) { 12 | super(message); 13 | } 14 | 15 | public UserExistException(String message, Throwable cause) { 16 | super(message, cause); 17 | } 18 | 19 | public UserExistException(Throwable cause) { 20 | super(cause); 21 | } 22 | 23 | public UserExistException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { 24 | super(message, cause, enableSuppression, writableStackTrace); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/exception/UserNotLoginException.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.exception; 2 | 3 | /** 4 | * @author Retain 5 | * @date 2021/10/3 16:12 6 | */ 7 | public class UserNotLoginException extends RuntimeException{ 8 | public UserNotLoginException() { 9 | } 10 | 11 | public UserNotLoginException(String message) { 12 | super(message); 13 | } 14 | 15 | public UserNotLoginException(String message, Throwable cause) { 16 | super(message, cause); 17 | } 18 | 19 | public UserNotLoginException(Throwable cause) { 20 | super(cause); 21 | } 22 | 23 | public UserNotLoginException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { 24 | super(message, cause, enableSuppression, writableStackTrace); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/filter/CorsFilter.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.filter; 2 | 3 | import javax.servlet.*; 4 | import javax.servlet.annotation.WebFilter; 5 | import javax.servlet.http.HttpServletRequest; 6 | import javax.servlet.http.HttpServletResponse; 7 | import java.io.IOException; 8 | 9 | @SuppressWarnings(value = "unused") 10 | @WebFilter(urlPatterns = "/*", filterName = "corsFilter") 11 | public class CorsFilter implements Filter { 12 | 13 | @Override 14 | public void init(FilterConfig filterConfig) throws ServletException { 15 | } 16 | 17 | @Override 18 | public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { 19 | HttpServletResponse res = (HttpServletResponse) servletResponse; 20 | HttpServletRequest request = (HttpServletRequest) servletRequest; 21 | // res.setContentType("text/html;charset=UTF-8"); 22 | res.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin")); 23 | res.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE,PUT,PATCH"); 24 | res.setHeader("Access-Control-Max-Age", "0"); 25 | res.setHeader("Access-Control-Allow-Headers", "Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With,Cookie"); 26 | res.setHeader("Access-Control-Allow-Credentials", "true"); 27 | res.setHeader("XDomainRequestAllowed", "1"); 28 | filterChain.doFilter(request, res); 29 | } 30 | 31 | @Override 32 | public void destroy() { 33 | 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/filter/JwtAuthenticationFilter.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.filter; 2 | 3 | 4 | import com.fasterxml.jackson.databind.ObjectMapper; 5 | import io.jsonwebtoken.ExpiredJwtException; 6 | import io.jsonwebtoken.MalformedJwtException; 7 | import io.jsonwebtoken.SignatureException; 8 | import io.jsonwebtoken.UnsupportedJwtException; 9 | import org.springframework.security.core.Authentication; 10 | import org.springframework.security.core.context.SecurityContextHolder; 11 | import org.springframework.web.filter.OncePerRequestFilter; 12 | import top.retain.nd.common.CommonResultTool; 13 | import top.retain.nd.common.StatusCode; 14 | import top.retain.nd.config.security.TokenAuthenticationHelper; 15 | 16 | import javax.servlet.FilterChain; 17 | import javax.servlet.ServletException; 18 | import javax.servlet.http.HttpServletRequest; 19 | import javax.servlet.http.HttpServletResponse; 20 | import java.io.IOException; 21 | import java.io.PrintWriter; 22 | 23 | 24 | /** 25 | * @author waxijiang 26 | * jwt 对请求的验证 27 | */ 28 | public class JwtAuthenticationFilter extends OncePerRequestFilter { 29 | 30 | @Override 31 | protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException { 32 | try { 33 | // 对用 token 获取到的用户进行校验 34 | Authentication authentication = TokenAuthenticationHelper.getAuthentication(httpServletRequest); 35 | // 凭证有则放行 36 | SecurityContextHolder.getContext().setAuthentication(authentication); 37 | filterChain.doFilter(httpServletRequest, httpServletResponse); 38 | 39 | 40 | } catch (ExpiredJwtException | UnsupportedJwtException | MalformedJwtException | 41 | SignatureException | IllegalArgumentException e) { 42 | // 错误时 43 | httpServletResponse.setContentType("application/json; charset=UTF-8"); 44 | PrintWriter out = httpServletResponse.getWriter(); 45 | out.write(new ObjectMapper().writeValueAsString(CommonResultTool.fail(StatusCode.UN_AUTHORIZED, "Token " + 46 | "expired,登陆已过期"))); 47 | out.flush(); 48 | out.close(); 49 | // throw new RuntimeException(e); 50 | // httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Token expired,登陆已过期"); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/filter/JwtLoginFilter.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.filter; 2 | 3 | import com.fasterxml.jackson.core.JsonParseException; 4 | import com.fasterxml.jackson.databind.ObjectMapper; 5 | import org.springframework.security.authentication.*; 6 | import org.springframework.security.core.Authentication; 7 | import org.springframework.security.core.AuthenticationException; 8 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 9 | import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; 10 | import org.springframework.security.web.util.matcher.AntPathRequestMatcher; 11 | import org.springframework.web.util.HtmlUtils; 12 | import top.retain.nd.common.CommonResult; 13 | import top.retain.nd.common.CommonResultTool; 14 | import top.retain.nd.common.StatusCode; 15 | import top.retain.nd.config.security.TokenAuthenticationHelper; 16 | import top.retain.nd.entity.User; 17 | 18 | import javax.servlet.FilterChain; 19 | import javax.servlet.ServletException; 20 | import javax.servlet.http.HttpServletRequest; 21 | import javax.servlet.http.HttpServletResponse; 22 | import java.io.IOException; 23 | import java.io.PrintWriter; 24 | 25 | /** 26 | * JWT 登陆过滤器 27 | */ 28 | public class JwtLoginFilter extends AbstractAuthenticationProcessingFilter { 29 | 30 | /** 31 | * @param defaultFilterProcessesUrl 配置要过滤的地址,即登陆地址 32 | * @param authenticationManager 认证管理器,校验身份时会用到 33 | */ 34 | public JwtLoginFilter(String defaultFilterProcessesUrl, AuthenticationManager authenticationManager) { 35 | super(new AntPathRequestMatcher(defaultFilterProcessesUrl)); 36 | // 为 AbstractAuthenticationProcessingFilter 中的属性赋值 37 | setAuthenticationManager(authenticationManager); 38 | } 39 | 40 | 41 | /** 42 | * 提取用户账号密码进行验证 43 | */ 44 | @Override 45 | public Authentication attemptAuthentication(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws AuthenticationException, IOException, ServletException { 46 | try { 47 | // 获取 User 对象 48 | // readValue 第一个参数 输入流,第二个参数 要转换的对象 49 | User user = new ObjectMapper().readValue(httpServletRequest.getInputStream(), User.class); 50 | // 对 html 标签进行转义,防止 XSS 攻击 51 | String username = user.getUsername(); 52 | username = HtmlUtils.htmlEscape(username); 53 | UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( 54 | username, 55 | user.getPassword() 56 | ); 57 | // 进行登陆验证 58 | return getAuthenticationManager().authenticate(token); 59 | } catch (JsonParseException e) { 60 | throw new InsufficientAuthenticationException("认证信息不足"); 61 | } 62 | } 63 | 64 | /** 65 | * 登陆成功回调 66 | */ 67 | @Override 68 | protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException { 69 | // 登陆成功 70 | TokenAuthenticationHelper.addAuthentication(request, response, authResult); 71 | } 72 | 73 | /** 74 | * 登陆失败回调 75 | */ 76 | @Override 77 | protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException { 78 | // 默认错误 79 | CommonResult commonResult = CommonResultTool.fail(StatusCode.INTERNAL_SERVER_ERROR); 80 | // 用户名错误 81 | if (failed instanceof UsernameNotFoundException) { 82 | commonResult = CommonResultTool.fail(StatusCode.UNKNOWN_USERNAME); 83 | // 用户已被删除 84 | } else if (failed instanceof DisabledException) { 85 | commonResult = CommonResultTool.fail(StatusCode.USER_DISABLED); 86 | // 用户密码错误 87 | } else if (failed instanceof BadCredentialsException) { 88 | commonResult = CommonResultTool.fail(StatusCode.WRONG_USERNAME_OR_PASSWORD); 89 | // 用户已被禁用(锁定) 90 | } else if (failed instanceof LockedException) { 91 | commonResult = CommonResultTool.fail(StatusCode.USER_LOCKED); 92 | } else if (failed instanceof InsufficientAuthenticationException) { 93 | commonResult = CommonResultTool.fail(StatusCode.SYNTAX_ERROR, failed.getLocalizedMessage()); 94 | } 95 | 96 | response.setContentType("application/json; charset=UTF-8"); 97 | PrintWriter out = response.getWriter(); 98 | out.write(new ObjectMapper().writeValueAsString(commonResult)); 99 | out.flush(); 100 | out.close(); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/filter/LogFilter.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.filter; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.springframework.core.Ordered; 5 | import org.springframework.web.filter.OncePerRequestFilter; 6 | import org.springframework.web.util.ContentCachingRequestWrapper; 7 | import org.springframework.web.util.ContentCachingResponseWrapper; 8 | import org.springframework.web.util.WebUtils; 9 | import javax.servlet.FilterChain; 10 | import javax.servlet.ServletException; 11 | import javax.servlet.http.HttpServletRequest; 12 | import javax.servlet.http.HttpServletResponse; 13 | import java.io.IOException; 14 | import java.io.UnsupportedEncodingException; 15 | import java.util.Enumeration; 16 | 17 | @Slf4j 18 | public class LogFilter extends OncePerRequestFilter implements Ordered { 19 | // put filter at the end of all other filters to make sure we are processing after all others 20 | private int order = Ordered.LOWEST_PRECEDENCE - 8; 21 | public static final String SPLIT_STRING_M = "="; 22 | public static final String SPLIT_STRING_DOT = ", "; 23 | 24 | @Override 25 | public int getOrder() { 26 | return order; 27 | } 28 | 29 | @Override 30 | protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, 31 | FilterChain filterChain) throws ServletException, IOException { 32 | ContentCachingRequestWrapper wrapperRequest = new ContentCachingRequestWrapper(request); 33 | ContentCachingResponseWrapper wrapperResponse = new ContentCachingResponseWrapper(response); 34 | String urlParams = getRequestParams(request); 35 | filterChain.doFilter(wrapperRequest, wrapperResponse); 36 | 37 | String requestBodyStr = getRequestBody(wrapperRequest); 38 | log.info("**USER:" + request.getRemoteUser()); 39 | log.info("**URL : " + request.getRequestURL().toString()); 40 | log.info("**HTTP_METHOD : " + request.getMethod()); 41 | log.info("**IP : " + request.getRemoteAddr()); 42 | log.info("**params[{}] | request body:{}", urlParams, requestBodyStr); 43 | 44 | String responseBodyStr = getResponseBody(wrapperResponse); 45 | log.info("**response body:{}", responseBodyStr); 46 | wrapperResponse.copyBodyToResponse(); 47 | } 48 | 49 | /** 50 | * 打印请求参数 51 | * 52 | * @param request 53 | */ 54 | private String getRequestBody(ContentCachingRequestWrapper request) { 55 | ContentCachingRequestWrapper wrapper = WebUtils.getNativeRequest(request, ContentCachingRequestWrapper.class); 56 | if (wrapper != null) { 57 | byte[] buf = wrapper.getContentAsByteArray(); 58 | if (buf.length > 0) { 59 | String payload; 60 | try { 61 | payload = new String(buf, 0, buf.length, wrapper.getCharacterEncoding()); 62 | } catch (UnsupportedEncodingException e) { 63 | payload = "[unknown]"; 64 | } 65 | return payload.replaceAll(" ", ""); 66 | } 67 | } 68 | return ""; 69 | } 70 | 71 | /** 72 | * 打印返回参数 73 | * 74 | * @param response 75 | */ 76 | private String getResponseBody(ContentCachingResponseWrapper response) { 77 | ContentCachingResponseWrapper wrapper = WebUtils.getNativeResponse(response, 78 | ContentCachingResponseWrapper.class); 79 | if (wrapper != null) { 80 | byte[] buf = wrapper.getContentAsByteArray(); 81 | if (buf.length > 0) { 82 | String payload; 83 | try { 84 | payload = new String(buf, 0, buf.length, wrapper.getCharacterEncoding()); 85 | } catch (UnsupportedEncodingException e) { 86 | payload = "[unknown]"; 87 | } 88 | return payload; 89 | } 90 | } 91 | return ""; 92 | } 93 | 94 | /** 95 | * 获取请求地址上的参数 96 | * 97 | * @param request 98 | * @return 99 | */ 100 | public static String getRequestParams(HttpServletRequest request) { 101 | StringBuilder sb = new StringBuilder(); 102 | Enumeration enu = request.getParameterNames(); 103 | //获取请求参数 104 | while (enu.hasMoreElements()) { 105 | String name = enu.nextElement(); 106 | sb.append(name + SPLIT_STRING_M).append(request.getParameter(name)); 107 | if (enu.hasMoreElements()) { 108 | sb.append(SPLIT_STRING_DOT); 109 | } 110 | } 111 | return sb.toString(); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/filter/SmsCodeAuthenticationFilter.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.filter; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import org.springframework.security.authentication.*; 5 | import org.springframework.security.core.Authentication; 6 | import org.springframework.security.core.AuthenticationException; 7 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 8 | import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; 9 | import org.springframework.security.web.util.matcher.AntPathRequestMatcher; 10 | import org.springframework.util.Assert; 11 | import top.retain.nd.common.CommonResult; 12 | import top.retain.nd.common.CommonResultTool; 13 | import top.retain.nd.common.StatusCode; 14 | import top.retain.nd.config.security.SmsCodeAuthenticationToken; 15 | import top.retain.nd.config.security.TokenAuthenticationHelper; 16 | 17 | import javax.servlet.FilterChain; 18 | import javax.servlet.ServletException; 19 | import javax.servlet.http.HttpServletRequest; 20 | import javax.servlet.http.HttpServletResponse; 21 | import java.io.IOException; 22 | import java.io.PrintWriter; 23 | 24 | /** 25 | * @author Retain 26 | * @date 2021/10/19 15:42 27 | */ 28 | public class SmsCodeAuthenticationFilter extends AbstractAuthenticationProcessingFilter { 29 | /** 30 | * form表单中手机号码的字段name 31 | */ 32 | public static final String SPRING_SECURITY_FORM_MOBILE_KEY = "phoneNumber"; 33 | 34 | private String mobileParameter = SPRING_SECURITY_FORM_MOBILE_KEY; 35 | /** 36 | * 是否仅 POST 方式 37 | */ 38 | private boolean postOnly = true; 39 | 40 | public SmsCodeAuthenticationFilter() { 41 | // 短信登录的请求 post 方式的 /sms/login 42 | super(new AntPathRequestMatcher("/sms/login", "POST")); 43 | } 44 | public SmsCodeAuthenticationFilter(String defaultFilterProcessesUrl, AuthenticationManager authenticationManager) { 45 | super(new AntPathRequestMatcher(defaultFilterProcessesUrl)); 46 | // 为 AbstractAuthenticationProcessingFilter 中的属性赋值 47 | setAuthenticationManager(authenticationManager); 48 | } 49 | 50 | @Override 51 | public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { 52 | if (postOnly && !"POST".equals(request.getMethod())) { 53 | throw new AuthenticationServiceException( 54 | "Authentication method not supported: " + request.getMethod()); 55 | } 56 | 57 | String mobile = request.getParameter(mobileParameter); 58 | String code = request.getParameter("code"); 59 | 60 | if (mobile == null) { 61 | mobile = ""; 62 | } 63 | 64 | mobile = mobile.trim(); 65 | 66 | SmsCodeAuthenticationToken authRequest = new SmsCodeAuthenticationToken(mobile, code); 67 | 68 | // Allow subclasses to set the "details" property 69 | setDetails(request, authRequest); 70 | 71 | return this.getAuthenticationManager().authenticate(authRequest); 72 | } 73 | 74 | 75 | protected void setDetails(HttpServletRequest request, SmsCodeAuthenticationToken authRequest) { 76 | authRequest.setDetails(authenticationDetailsSource.buildDetails(request)); 77 | } 78 | 79 | public String getMobileParameter() { 80 | return mobileParameter; 81 | } 82 | 83 | public void setMobileParameter(String mobileParameter) { 84 | Assert.hasText(mobileParameter, "Mobile parameter must not be empty or null"); 85 | this.mobileParameter = mobileParameter; 86 | } 87 | 88 | public void setPostOnly(boolean postOnly) { 89 | this.postOnly = postOnly; 90 | } 91 | 92 | @Override 93 | protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException { 94 | TokenAuthenticationHelper.addAuthentication(request, response, authResult); 95 | } 96 | 97 | @Override 98 | protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException { 99 | // 默认错误 100 | CommonResult commonResult = CommonResultTool.fail(StatusCode.INTERNAL_SERVER_ERROR); 101 | // 用户名错误 102 | if (failed instanceof UsernameNotFoundException) { 103 | commonResult = CommonResultTool.fail(StatusCode.UNKNOWN_USERNAME); 104 | // 用户已被删除 105 | } else if (failed instanceof DisabledException) { 106 | commonResult = CommonResultTool.fail(StatusCode.USER_DISABLED); 107 | // 验证码错误 108 | } else if (failed instanceof BadCredentialsException) { 109 | commonResult = CommonResultTool.fail(StatusCode.CODE_WRONG); 110 | // 用户已被禁用(锁定) 111 | } else if (failed instanceof LockedException) { 112 | commonResult = CommonResultTool.fail(StatusCode.USER_LOCKED); 113 | } else if (failed instanceof InsufficientAuthenticationException) { 114 | commonResult = CommonResultTool.fail(StatusCode.SYNTAX_ERROR, failed.getLocalizedMessage()); 115 | } 116 | 117 | response.setContentType("application/json; charset=UTF-8"); 118 | PrintWriter out = response.getWriter(); 119 | out.write(new ObjectMapper().writeValueAsString(commonResult)); 120 | out.flush(); 121 | out.close(); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/filter/WrapperRequestFilter.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.filter; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import top.retain.nd.util.RequestWrapper; 5 | 6 | import javax.servlet.*; 7 | import javax.servlet.http.HttpServletRequest; 8 | import java.io.IOException; 9 | 10 | 11 | @Slf4j 12 | public class WrapperRequestFilter implements Filter { 13 | @Override 14 | public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { 15 | // 如果是请求过滤 16 | if (!servletRequest.getInputStream().isFinished() && !servletRequest.getContentType().contains("multipart" + 17 | "/form" + 18 | "-data;")) { 19 | ServletRequest requestWrapper = null; 20 | requestWrapper = new RequestWrapper((HttpServletRequest) servletRequest); 21 | log.info("包装request"); 22 | filterChain.doFilter(requestWrapper, servletResponse); 23 | } else { 24 | filterChain.doFilter(servletRequest, servletResponse); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/handler/CustomAuthenticationFailureHandler.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.handler; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.http.HttpStatus; 7 | import org.springframework.security.core.AuthenticationException; 8 | import org.springframework.security.web.authentication.AuthenticationFailureHandler; 9 | import org.springframework.stereotype.Component; 10 | 11 | import javax.servlet.ServletException; 12 | import javax.servlet.http.HttpServletRequest; 13 | import javax.servlet.http.HttpServletResponse; 14 | import java.io.IOException; 15 | 16 | /** 17 | * @author Retain 18 | * @date 2021/10/19 17:15 19 | */ 20 | @Component 21 | @Slf4j 22 | public class CustomAuthenticationFailureHandler implements AuthenticationFailureHandler { 23 | @Autowired 24 | private ObjectMapper objectMapper; 25 | 26 | 27 | @Override 28 | public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { 29 | log.info("登陆失败"); 30 | 31 | response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value()); 32 | response.setContentType("application/json;charset=UTF-8"); 33 | response.getWriter().write(objectMapper.writeValueAsString(exception.getMessage())); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/handler/CustomAuthenticationSuccessHandler.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.handler; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.security.core.Authentication; 7 | import org.springframework.security.web.authentication.AuthenticationSuccessHandler; 8 | import org.springframework.stereotype.Component; 9 | 10 | import javax.servlet.ServletException; 11 | import javax.servlet.http.HttpServletRequest; 12 | import javax.servlet.http.HttpServletResponse; 13 | import java.io.IOException; 14 | 15 | /** 16 | * @author Retain 17 | * @date 2021/10/19 15:58 18 | */ 19 | @Component 20 | @Slf4j 21 | public class CustomAuthenticationSuccessHandler implements AuthenticationSuccessHandler { 22 | @Autowired 23 | private ObjectMapper objectMapper; 24 | 25 | 26 | @Override 27 | public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { 28 | log.info("登录成功"); 29 | 30 | response.setContentType("application/json;charset=UTF-8"); 31 | response.getWriter().write(objectMapper.writeValueAsString(authentication)); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/handler/CustomMetaObjectHandler.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.handler; 2 | 3 | import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.apache.ibatis.reflection.MetaObject; 6 | import org.springframework.stereotype.Component; 7 | 8 | import java.util.Date; 9 | 10 | /** 11 | * @author Retain 12 | * @date 2021/2/25 16:48 13 | */ 14 | @Component 15 | @Slf4j 16 | public class CustomMetaObjectHandler implements MetaObjectHandler{ 17 | 18 | 19 | @Override 20 | public void insertFill(MetaObject metaObject) { 21 | log.info("**创建中...自动填充时间**"); 22 | this.strictInsertFill(metaObject, "createTime", Date.class, new Date()); 23 | this.strictInsertFill(metaObject, "lastLoginTime", Date.class, new Date()); 24 | this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date()); // 起始版本 3.3.0(推荐) 25 | 26 | } 27 | 28 | /** 29 | * 创建时不会填充!只会在更新时填充 30 | * @param metaObject 31 | */ 32 | @Override 33 | public void updateFill(MetaObject metaObject) { 34 | log.info("**自动填充更新时间**"); 35 | this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date()); // 起始版本 3.3.0(推荐) 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/handler/CustomerAccessDeniedHandler.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.handler; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | 5 | import org.springframework.security.access.AccessDeniedException; 6 | import org.springframework.security.web.access.AccessDeniedHandler; 7 | import top.retain.nd.common.CommonResultTool; 8 | import top.retain.nd.common.StatusCode; 9 | 10 | import javax.servlet.ServletException; 11 | import javax.servlet.http.HttpServletRequest; 12 | import javax.servlet.http.HttpServletResponse; 13 | import java.io.IOException; 14 | import java.io.PrintWriter; 15 | 16 | /** 17 | * @author Retain 18 | */ 19 | public class CustomerAccessDeniedHandler implements AccessDeniedHandler { 20 | @Override 21 | public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException { 22 | httpServletResponse.setContentType("application/json; charset=UTF-8"); 23 | PrintWriter out = httpServletResponse.getWriter(); 24 | out.write(new ObjectMapper().writeValueAsString(CommonResultTool.fail(StatusCode.NO_PERMISSION))); 25 | out.flush(); 26 | out.close(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/handler/CustomizeLogoutSuccessHandler.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.handler; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | 5 | import org.springframework.security.core.Authentication; 6 | import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; 7 | import org.springframework.stereotype.Component; 8 | import top.retain.nd.common.CommonResult; 9 | import top.retain.nd.common.CommonResultTool; 10 | 11 | import javax.servlet.ServletException; 12 | import javax.servlet.http.HttpServletRequest; 13 | import javax.servlet.http.HttpServletResponse; 14 | import java.io.IOException; 15 | 16 | /** 17 | * @author waxijiang 18 | */ 19 | @Component 20 | public class CustomizeLogoutSuccessHandler implements LogoutSuccessHandler { 21 | @Override 22 | public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException { 23 | CommonResult result = CommonResultTool.success("登出成功!"); 24 | httpServletResponse.setContentType("text/json;charset=utf-8"); 25 | httpServletResponse.getWriter().write(new ObjectMapper().writeValueAsString(result)); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/mapper/IExtendCodeMapper.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.mapper; 2 | 3 | 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 | import top.retain.nd.entity.ExtendCode; 6 | 7 | public interface IExtendCodeMapper extends BaseMapper { 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/mapper/IFileMapper.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import org.apache.ibatis.annotations.Param; 5 | import top.retain.nd.entity.UserFile; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @author Retain 11 | * @date 2021/11/6 19:37 12 | */ 13 | public interface IFileMapper extends BaseMapper { 14 | List listFilePrefix(@Param("prefix") String prefix, @Param("userId") Long userId); 15 | List listRootFiles(@Param("userId") Long userId); 16 | UserFile getParentDirByPath(@Param("prefix") String prefix,@Param("userId") Long userId); 17 | // String selectParentId(@Param("name") String name, @Param("userId") Long userId); 18 | 19 | 20 | UserFile getFileByPath(@Param("userId") Long userId,@Param("ossPath")String ossPath); 21 | UserFile getDeletedFileByPath(@Param("userId") Long userId,@Param("ossPath")String ossPath); 22 | 23 | List getChildFilesById(@Param("userId") Long userId,@Param("parentId") String parentId); 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/mapper/ISafeFileMapper.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import top.retain.nd.entity.SafeFile; 5 | import top.retain.nd.entity.UserFile; 6 | 7 | import java.util.List; 8 | 9 | public interface ISafeFileMapper extends BaseMapper { 10 | 11 | List list(Long userId); 12 | } -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/mapper/IShareMapper.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import top.retain.nd.entity.Share; 5 | 6 | public interface IShareMapper extends BaseMapper { 7 | } -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/mapper/ITagFileMapper.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import top.retain.nd.entity.TagFile; 5 | import top.retain.nd.entity.UserFile; 6 | 7 | import java.util.List; 8 | 9 | public interface ITagFileMapper extends BaseMapper { 10 | 11 | List listTagFiles(String tagName,String tagId); 12 | List getTagFiles(String tagId); 13 | 14 | 15 | } -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/mapper/ITagMapper.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import org.apache.ibatis.annotations.Param; 5 | import top.retain.nd.entity.Tag; 6 | 7 | /** 8 | * @author Retain 9 | * @date 2021/11/11 9:38 10 | */ 11 | public interface ITagMapper extends BaseMapper { 12 | Tag getTagById(@Param("id") String tagId, @Param("userId") Long userId); 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/mapper/ITaskMapper.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import top.retain.nd.entity.Task; 5 | 6 | public interface ITaskMapper extends BaseMapper { 7 | 8 | Task getLatestTask(Long userId,Task task); 9 | 10 | } -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/mapper/IUserCodeMapper.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import top.retain.nd.entity.UserCode; 5 | 6 | public interface IUserCodeMapper extends BaseMapper { 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/mapper/IUserMapper.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import org.apache.ibatis.annotations.Mapper; 5 | import org.springframework.web.bind.annotation.PathVariable; 6 | import top.retain.nd.entity.User; 7 | 8 | /** 9 | * @author Retain 10 | * @date 2021/9/29 17:00 11 | */ 12 | @Mapper 13 | public interface IUserMapper extends BaseMapper { 14 | Boolean login(@PathVariable("account") String account, @PathVariable("password") String password); 15 | String getUserBucket(@PathVariable("account") String account); 16 | User selectByPhone(@PathVariable("phoneNumber") String phoneNumber); 17 | 18 | User selectByAccount(@PathVariable("account") String account); 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/mappers/ExtendCodemapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/mappers/FileMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 12 | 15 | 18 | 19 | 22 | 25 | 26 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/mappers/ISafeFileMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/mappers/IShareMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/mappers/ITagFileMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 12 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/mappers/ITaskMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/mappers/TagMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/mappers/UserCode.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/mappers/UserMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 13 | 14 | 15 | 16 | 19 | 20 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/service/IExtendCodeService.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import top.retain.nd.common.CommonResult; 5 | import top.retain.nd.entity.ExtendCode; 6 | 7 | public interface IExtendCodeService extends IService { 8 | CommonResult match(String account, String code); 9 | 10 | CommonResult add(ExtendCode code); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/service/IFileService.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.service; 2 | 3 | import com.aliyun.oss.model.OSSObjectSummary; 4 | import com.baomidou.mybatisplus.extension.service.IService; 5 | import top.retain.nd.dto.DownloadDirResp; 6 | import top.retain.nd.dto.GetFileDetailResp; 7 | import top.retain.nd.dto.GetUserFIleSpaceResp; 8 | import top.retain.nd.dto.ListFilesPagedResp; 9 | import top.retain.nd.entity.UserFile; 10 | 11 | import javax.servlet.http.HttpServletResponse; 12 | import java.util.Date; 13 | import java.util.List; 14 | 15 | /** 16 | * @author Retain 17 | * @date 2021/9/29 18:43 18 | */ 19 | public interface IFileService extends IService { 20 | List listFilesPaged(String account, Integer currentPage, Integer maxKeys); 21 | Boolean deleteFile(String account,String filePath); 22 | Boolean deleteDir(String account,String filePath); 23 | void streamDownload(String account, String objectPath, HttpServletResponse response); 24 | String browserDownload(String account, String objectPath); 25 | List listFilesByPrefixPaged(String account, Integer currentPage, Integer size, String prefix); 26 | Boolean saveUploadFile(Long userId,UserFile file); 27 | 28 | List listFilesByPrefix(String account, String prefix); 29 | 30 | UserFile getFileByPath(Long userId, String ossPath); 31 | 32 | String generateUrl(String account, String ossPath, Date expireSeconds); 33 | 34 | String createQr(String shareUrl); 35 | 36 | boolean rename(String account, String ossPath, String newName); 37 | 38 | boolean moveToBin(String account, String ossPath); 39 | 40 | void sortWithDir(List list); 41 | 42 | GetFileDetailResp detail(String account, String ossPath); 43 | 44 | List listBinFiles(String account); 45 | 46 | boolean clearBinFiles(String account); 47 | 48 | boolean withdrawBinFile(String account, String ossPath); 49 | 50 | List downloadDir(String account,String shareId, String objectPath); 51 | 52 | 53 | String generatePreviewUrl(String account, String ossPath, Date date); 54 | 55 | boolean doesFileExists(String account, String ossPath); 56 | 57 | GetUserFIleSpaceResp getUserFileSpace(String account); 58 | 59 | List getDirFiles(Long userId, UserFile dirFile); 60 | 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/service/ISafeFileService.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import top.retain.nd.entity.SafeFile; 5 | import top.retain.nd.entity.UserFile; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @author Retain 11 | * @date 2021/11/22 12:41 12 | */ 13 | public interface ISafeFileService extends IService { 14 | boolean activate(Long account, String safeCode); 15 | 16 | boolean moveToSafe(Long account, String ossPath); 17 | 18 | boolean matchCode(Long account, String safeCode); 19 | 20 | List list(Long account); 21 | 22 | boolean check(Long account); 23 | 24 | boolean moveOutSafe(Long account, String ossPath); 25 | 26 | boolean checkEntered(Long account); 27 | 28 | boolean lockSafe(Long account); 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/service/IShareService.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import top.retain.nd.entity.Share; 5 | import top.retain.nd.entity.User; 6 | 7 | /** 8 | * @author Retain 9 | * @date 2021/12/5 11:39 10 | */ 11 | public interface IShareService extends IService { 12 | Share getShareDetail(String shareCode); 13 | 14 | boolean transferFile(String shareId, String savePath, String account); 15 | 16 | boolean exist(String shareId); 17 | 18 | boolean downloadCount(String shareId); 19 | 20 | User getUser(String account); 21 | 22 | boolean deleteShare( String id); 23 | 24 | boolean cancelShareByPath(Long userId,String ossPath); 25 | 26 | String encode(String id); 27 | 28 | boolean extract(String id, String code); 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/service/ITagFileService.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import top.retain.nd.entity.TagFile; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * @author Retain 10 | * @date 2021/11/17 18:19 11 | */ 12 | public interface ITagFileService extends IService { 13 | // int addFileToTag(Tag tag, Long userId, UserFile file); 14 | TagFile getTagFile(String fileId, String tagId); 15 | List getTagFiles(String tagId); 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/service/ITagService.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import top.retain.nd.entity.Tag; 5 | import top.retain.nd.entity.UserFile; 6 | 7 | import java.io.FileNotFoundException; 8 | import java.nio.file.FileAlreadyExistsException; 9 | import java.util.List; 10 | 11 | /** 12 | * @author Retain 13 | * @date 2021/11/11 9:40 14 | */ 15 | public interface ITagService extends IService { 16 | Tag getTagById( String tagId, Long userId); 17 | Tag getTagByName(String tagName, Long userId); 18 | int addTag(Tag tag, Long userId) throws FileAlreadyExistsException; 19 | 20 | int addFileToTag(String tagName, Long userId, String ossPath) throws FileNotFoundException; 21 | 22 | List listTagFiles(String tagName, Long userId); 23 | 24 | List getAllTags(Long userId); 25 | 26 | boolean rename(Long userId, String tagId, String newName); 27 | 28 | boolean delete(Long userId, String tagId); 29 | 30 | boolean moveOutTag(String tagName, Long userId, String ossPath); 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/service/ITaskService.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import top.retain.nd.dto.GetFinishedTasksResp; 5 | import top.retain.nd.entity.Task; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @author Retain 11 | * @date 2021/11/24 9:02 12 | */ 13 | public interface ITaskService extends IService { 14 | boolean addTask(Task task, Long userId); 15 | List getFinishedTasks(Long userId); 16 | 17 | boolean updateTask(Long userId, Task task, Boolean finished); 18 | 19 | boolean clear(Long userId); 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/service/IUserCodeService.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import top.retain.nd.entity.UserCode; 5 | 6 | public interface IUserCodeService extends IService { 7 | 8 | UserCode getUserCode(Long userId,String code); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/service/IUserService.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import org.springframework.web.multipart.MultipartFile; 5 | import top.retain.nd.dto.STSResp; 6 | import top.retain.nd.entity.User; 7 | 8 | /** 9 | * @author Retain 10 | * @date 2021/9/29 18:43 11 | */ 12 | public interface IUserService extends IService { 13 | 14 | Long register(User user); 15 | String getUserBucket(String account); 16 | Boolean sendVerifyCode(String phoneNumber); 17 | public User selectByPhone(String phone); 18 | 19 | String uploadAvator(MultipartFile multipartFile, Long userId); 20 | 21 | boolean updatePhoneNumber(String phoneNumber, String code, Long userId); 22 | 23 | boolean updatePassword(String oldPassword, String newPassword, Long userId); 24 | 25 | boolean forgetPassword(String phoneNumber, String code, String newPassword); 26 | 27 | boolean forgetSafeCode(String newSafeCode, String code, Long userId); 28 | 29 | STSResp getSts(String account); 30 | 31 | boolean extendUserSpace(Long userId,Long spaceSize); 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/service/impl/ExtendCodeServiceImpl.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 4 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 5 | import org.springframework.stereotype.Service; 6 | import org.springframework.transaction.annotation.Transactional; 7 | import top.retain.nd.common.CommonResult; 8 | import top.retain.nd.common.CommonResultTool; 9 | import top.retain.nd.common.StatusCode; 10 | import top.retain.nd.entity.ExtendCode; 11 | import top.retain.nd.entity.User; 12 | import top.retain.nd.entity.UserCode; 13 | import top.retain.nd.mapper.IExtendCodeMapper; 14 | import top.retain.nd.service.IExtendCodeService; 15 | import top.retain.nd.service.IUserCodeService; 16 | import top.retain.nd.service.IUserService; 17 | 18 | import javax.annotation.Resource; 19 | import java.util.Objects; 20 | 21 | @Service 22 | public class ExtendCodeServiceImpl extends ServiceImpl implements IExtendCodeService { 23 | 24 | @Resource 25 | IUserService userService; 26 | 27 | @Resource 28 | IUserCodeService userCodeService; 29 | @Override 30 | @Transactional 31 | public CommonResult match(String account, String code) { 32 | User user = getUser(account); 33 | ExtendCode extendCode = getByCode(code); 34 | if (Objects.isNull(extendCode)) { 35 | return CommonResultTool.fail(StatusCode.SYNTAX_ERROR, "暗号不存在噢"); 36 | } 37 | if (System.currentTimeMillis() > extendCode.getExpireTime().getTime()) { 38 | return CommonResultTool.fail(StatusCode.SYNTAX_ERROR, "暗号已经过期啦"); 39 | } 40 | UserCode userCode = userCodeService.getUserCode(user.getId(), code); 41 | if (Objects.nonNull(userCode)) { 42 | return CommonResultTool.fail(StatusCode.SYNTAX_ERROR, "您已经使用过了该暗号了噢"); 43 | } 44 | 45 | boolean b = userService.extendUserSpace(user.getId(), extendCode.getExtendSize()); 46 | if (!b) { 47 | throw new RuntimeException("扩容失败"); 48 | } 49 | UserCode newUserCode = new UserCode(); 50 | newUserCode.setCode(code); 51 | newUserCode.setUserId(user.getId()); 52 | 53 | boolean save = userCodeService.save(newUserCode); 54 | if (!save) { 55 | throw new RuntimeException("扩容失败"); 56 | } 57 | return CommonResultTool.success("扩容成功!将会很快生效"); 58 | } 59 | 60 | @Override 61 | public CommonResult add(ExtendCode code) { 62 | if (code.getExpireTime().getTime() < System.currentTimeMillis()) { 63 | return CommonResultTool.fail(StatusCode.SYNTAX_ERROR, "过期时间不能小于当前时间"); 64 | } 65 | ExtendCode one = getByCode(code.getCode()); 66 | if (Objects.nonNull(one)) { 67 | if (one.getExpireTime().getTime() > System.currentTimeMillis()) { 68 | return CommonResultTool.fail(StatusCode.SYNTAX_ERROR, "暗号已经存在了噢"); 69 | } 70 | } 71 | boolean save = this.save(code); 72 | if (!save) { 73 | return CommonResultTool.fail(StatusCode.SYNTAX_ERROR, "暗号添加失败"); 74 | } 75 | return CommonResultTool.success("暗号添加成功"); 76 | } 77 | 78 | private User getUser(String account) { 79 | return userService.getOne(new QueryWrapper().eq("account", account)); 80 | } 81 | 82 | // 根据code获取暗号 83 | public ExtendCode getByCode(String code) { 84 | return this.getOne(new QueryWrapper().eq("code", code)); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/service/impl/SafeFileServiceImpl.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 4 | import com.baomidou.mybatisplus.core.toolkit.StringUtils; 5 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 6 | import org.springframework.stereotype.Service; 7 | import top.retain.nd.entity.SafeFile; 8 | import top.retain.nd.entity.User; 9 | import top.retain.nd.entity.UserFile; 10 | import top.retain.nd.mapper.ISafeFileMapper; 11 | import top.retain.nd.service.IFileService; 12 | import top.retain.nd.service.ISafeFileService; 13 | import top.retain.nd.service.IUserService; 14 | import top.retain.nd.util.RedisUtils; 15 | 16 | import javax.annotation.Resource; 17 | import java.util.List; 18 | import java.util.Objects; 19 | 20 | /** 21 | * @author Retain 22 | * @date 2021/11/22 12:42 23 | */ 24 | @Service 25 | public class SafeFileServiceImpl extends ServiceImpl implements ISafeFileService { 26 | 27 | public static final String SAFE_PERMIT = "SAFE-"; 28 | @Resource 29 | private RedisUtils redisUtils; 30 | @Resource 31 | private IUserService userService; 32 | 33 | @Resource 34 | private IFileService fileService; 35 | 36 | @Resource 37 | private ISafeFileMapper safeFileMapper; 38 | 39 | private User getUser(Long account) { 40 | return userService.getOne(new QueryWrapper().eq("account", account)); 41 | } 42 | 43 | @Override 44 | public boolean activate(Long account, String safeCode) { 45 | User user = getUser(account); 46 | user.setSafeCode(safeCode); 47 | user.setIsSafeOn(true); 48 | return userService.updateById(user); 49 | } 50 | 51 | @Override 52 | public boolean moveToSafe(Long account, String ossPath) { 53 | User user = getUser(account); 54 | if (!user.getIsSafeOn()) { 55 | throw new RuntimeException("保险箱还未激活!"); 56 | } 57 | UserFile file = fileService.getFileByPath(user.getId(), ossPath); 58 | if (Objects.isNull(file)) { 59 | throw new RuntimeException("文件不存在!"); 60 | } 61 | if (file.getDeleted()) { 62 | throw new RuntimeException("文件夹已被移到回收站!"); 63 | } 64 | file.setInSafe(true); 65 | fileService.updateById(file); 66 | SafeFile safeFile = new SafeFile(); 67 | safeFile.setFileId(file.getId()); 68 | safeFile.setUserId(user.getId()); 69 | return this.save(safeFile); 70 | } 71 | 72 | @Override 73 | public boolean matchCode(Long account, String safeCode) { 74 | User user = getUser(account); 75 | 76 | if (StringUtils.isBlank(safeCode)) { 77 | throw new RuntimeException("密钥不能为空!"); 78 | } 79 | boolean equals = safeCode.equals(user.getSafeCode()); 80 | // 密钥正确,存入redis,后面10分钟不需要输入密码 81 | String key = SAFE_PERMIT + user.getPhoneNumber(); 82 | if (equals && !redisUtils.hasKey(key)) { 83 | redisUtils.set(key,"1", 600L); 84 | } 85 | return equals; 86 | } 87 | 88 | @Override 89 | public List list(Long account) { 90 | User user = getUser(account); 91 | return safeFileMapper.list(user.getId()); 92 | } 93 | 94 | @Override 95 | public boolean check(Long account) { 96 | User user = getUser(account); 97 | return user.getIsSafeOn(); 98 | } 99 | 100 | @Override 101 | public boolean moveOutSafe(Long account, String ossPath) { 102 | User user = getUser(account); 103 | UserFile file = fileService.getFileByPath(user.getId(), ossPath); 104 | if (Objects.isNull(file)) { 105 | throw new RuntimeException("文件不存在!"); 106 | } 107 | if (file.getDeleted()) { 108 | throw new RuntimeException("文件夹已被移到回收站!"); 109 | } 110 | file.setInSafe(false); 111 | this.remove(new QueryWrapper().eq("user_id", user.getId()).eq("file_id", file.getId())); 112 | return fileService.updateById(file); 113 | 114 | } 115 | 116 | @Override 117 | public boolean checkEntered(Long account) { 118 | User user = getUser(account); 119 | if (redisUtils.hasKey(SAFE_PERMIT + user.getPhoneNumber())){ 120 | return true; 121 | }else { 122 | return false; 123 | } 124 | } 125 | 126 | @Override 127 | public boolean lockSafe(Long account) { 128 | User user = getUser(account); 129 | String key = SAFE_PERMIT + user.getPhoneNumber(); 130 | if (redisUtils.hasKey(key)){ 131 | redisUtils.delete(key); 132 | } 133 | return true; 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/service/impl/TagFileServiceImpl.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 4 | import com.baomidou.mybatisplus.core.toolkit.StringUtils; 5 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 6 | import org.springframework.stereotype.Service; 7 | import top.retain.nd.entity.TagFile; 8 | import top.retain.nd.mapper.ITagFileMapper; 9 | import top.retain.nd.service.ITagFileService; 10 | 11 | import javax.annotation.Resource; 12 | import java.util.List; 13 | 14 | /** 15 | * @author Retain 16 | * @date 2021/11/17 18:20 17 | */ 18 | @Service 19 | public class TagFileServiceImpl extends ServiceImpl implements ITagFileService { 20 | 21 | @Resource 22 | private ITagFileMapper tagFileMapper; 23 | @Override 24 | public TagFile getTagFile(String fileId, String tagId) { 25 | if (StringUtils.isBlank(fileId)) { 26 | return null; 27 | } 28 | return this.getOne(new QueryWrapper().eq("file_id", fileId) 29 | .eq("tag_id", tagId)); 30 | } 31 | 32 | @Override 33 | public List getTagFiles(String tagId) { 34 | return tagFileMapper.getTagFiles(tagId); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/service/impl/TagServiceImpl.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 4 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 5 | import org.springframework.stereotype.Service; 6 | import org.springframework.util.CollectionUtils; 7 | import org.springframework.util.StringUtils; 8 | import top.retain.nd.entity.Tag; 9 | import top.retain.nd.entity.TagFile; 10 | import top.retain.nd.entity.UserFile; 11 | import top.retain.nd.exception.TagFileAlreadyExistException; 12 | import top.retain.nd.exception.TagNotExistException; 13 | import top.retain.nd.mapper.ITagFileMapper; 14 | import top.retain.nd.mapper.ITagMapper; 15 | import top.retain.nd.service.IFileService; 16 | import top.retain.nd.service.ITagFileService; 17 | import top.retain.nd.service.ITagService; 18 | 19 | import javax.annotation.Resource; 20 | import java.io.FileNotFoundException; 21 | import java.nio.file.FileAlreadyExistsException; 22 | import java.text.SimpleDateFormat; 23 | import java.util.List; 24 | import java.util.Objects; 25 | import java.util.TimeZone; 26 | import java.util.stream.Collectors; 27 | 28 | /** 29 | * @author Retain 30 | * @date 2021/11/11 9:40 31 | */ 32 | @Service 33 | public class TagServiceImpl extends ServiceImpl implements ITagService { 34 | 35 | @Resource 36 | ITagFileService tagFileService; 37 | @Resource ITagMapper tagMapper; 38 | 39 | 40 | @Resource 41 | IFileService fileService; 42 | 43 | @Resource 44 | ITagFileMapper tagFileMapper; 45 | @Override 46 | public Tag getTagById(String tagId, Long userId) { 47 | return tagMapper.getTagById(tagId, userId); 48 | } 49 | 50 | @Override 51 | public Tag getTagByName(String tagName, Long userId) { 52 | if (StringUtils.isEmpty(tagName)) { 53 | return null; 54 | } 55 | return tagMapper.selectOne(new QueryWrapper().eq("name", tagName).eq("user_id", userId)); 56 | } 57 | 58 | @Override 59 | public int addTag(Tag tag, Long userId) throws FileAlreadyExistsException { 60 | Tag tag1 = getTagByName(tag.getName(), userId); 61 | if (Objects.nonNull(tag1)) { 62 | throw new FileAlreadyExistsException("标签已存在"); 63 | } 64 | tag.setUserId(userId); 65 | return tagMapper.insert(tag); 66 | } 67 | @Override 68 | public int addFileToTag(String tagName, Long userId, String ossPath) throws FileNotFoundException { 69 | UserFile file = fileService.getFileByPath(userId, ossPath); 70 | 71 | if (Objects.isNull(file)) { 72 | throw new FileNotFoundException("文件不存在!"); 73 | } 74 | Tag tag = getTagByName(tagName, userId); 75 | if (Objects.isNull(tag)) { 76 | throw new TagNotExistException("标签不存在!"); 77 | } 78 | TagFile tagFile1 = tagFileService.getTagFile(file.getId(), tag.getId()); 79 | if (Objects.nonNull(tagFile1)) { 80 | throw new TagFileAlreadyExistException("该标签下已存在该文件!"); 81 | } 82 | TagFile tagFile = new TagFile(); 83 | tagFile.setFileId(file.getId()); 84 | tagFile.setTagId(tag.getId()); 85 | return tagFileMapper.insert(tagFile); 86 | } 87 | 88 | @Override 89 | public List listTagFiles(String tagName, Long userId) { 90 | Tag tag = getTagByName(tagName, userId); 91 | if (Objects.isNull(tag)) { 92 | throw new TagNotExistException("标签不存在!"); 93 | } 94 | SimpleDateFormat simpleDateFormat = new SimpleDateFormat("MM/dd HH:mm"); 95 | simpleDateFormat.setTimeZone(TimeZone.getTimeZone("GMT+8")); 96 | List userFiles = tagFileMapper.listTagFiles(tagName, tag.getId()); 97 | userFiles.forEach(f -> f.setLastModified(simpleDateFormat.format(f.getUpdateTime()))); 98 | fileService.sortWithDir(userFiles); 99 | return userFiles; 100 | } 101 | 102 | @Override 103 | public List getAllTags(Long userId) { 104 | return this.list(new QueryWrapper().eq("user_id", userId)); 105 | } 106 | 107 | @Override 108 | public boolean rename(Long userId, String tagId, String newName) { 109 | Tag tag = getTagById(tagId, userId); 110 | if (Objects.isNull(tag)) { 111 | throw new TagNotExistException("标签不存在!"); 112 | } 113 | Tag tagByName = getTagByName(newName, userId); 114 | if (Objects.nonNull(tagByName)) { 115 | throw new TagFileAlreadyExistException("标签已存在,请重新输入!"); 116 | } 117 | tag.setName(newName); 118 | return updateById(tag); 119 | } 120 | 121 | @Override 122 | public boolean delete(Long userId, String tagId) { 123 | Tag tag = getTagById(tagId, userId); 124 | if (Objects.isNull(tag)) { 125 | throw new TagNotExistException("标签不存在!"); 126 | } 127 | List tagFiles = tagFileService.getTagFiles(tag.getId()); 128 | if (!CollectionUtils.isEmpty(tagFiles)) { 129 | List ids = tagFiles.stream().map(TagFile::getId).collect(Collectors.toList()); 130 | boolean tagFile = tagFileService.removeByIds(ids); 131 | if (!tagFile) { 132 | throw new RuntimeException("删除标签文件失败,请稍后再试"); 133 | } 134 | } 135 | 136 | return this.removeById(tag.getId()); 137 | } 138 | 139 | @Override 140 | public boolean moveOutTag(String tagName, Long userId, String ossPath) { 141 | Tag tag = this.getTagByName(tagName, userId); 142 | if (Objects.isNull(tag)) { 143 | throw new TagNotExistException("标签不存在!"); 144 | } 145 | 146 | UserFile file = fileService.getFileByPath(userId, ossPath); 147 | if (Objects.isNull(file) || file.getDeleted()) { 148 | throw new RuntimeException("文件不存在!"); 149 | } 150 | TagFile tagFile = tagFileService.getTagFile(file.getId(), tag.getId()); 151 | if (Objects.isNull(tagFile)) { 152 | throw new RuntimeException("该收藏夹下不存在该文件!"); 153 | } 154 | return tagFileService.removeById(tagFile.getId()); 155 | } 156 | 157 | 158 | // public List getAllTags(Long userId) { 159 | // 160 | // } 161 | } 162 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/service/impl/TaskServiceImpl.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 4 | import com.baomidou.mybatisplus.core.toolkit.StringUtils; 5 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 6 | import org.springframework.beans.BeanUtils; 7 | import org.springframework.stereotype.Service; 8 | import top.retain.nd.dto.GetFinishedTasksResp; 9 | import top.retain.nd.entity.Task; 10 | import top.retain.nd.mapper.ITaskMapper; 11 | import top.retain.nd.service.ITaskService; 12 | 13 | import javax.annotation.Resource; 14 | import java.text.SimpleDateFormat; 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | import java.util.Objects; 18 | import java.util.TimeZone; 19 | 20 | /** 21 | * @author Retain 22 | * @date 2021/11/24 9:03 23 | */ 24 | @Service 25 | public class TaskServiceImpl extends ServiceImpl implements ITaskService { 26 | 27 | @Resource 28 | private ITaskMapper taskMapper; 29 | 30 | @Override 31 | public boolean addTask(Task task, Long userId) { 32 | if (StringUtils.isBlank(task.getFilePath())) { 33 | throw new RuntimeException("任务路径不能为空!"); 34 | } 35 | Task dbTask = taskMapper.getLatestTask(userId, task); 36 | if (Objects.nonNull(dbTask) && !dbTask.getIsFinished()) { 37 | throw new RuntimeException("该任务已提交且还未执行完成!"); 38 | } 39 | task.setIsCancelled(false); 40 | task.setUserId(userId); 41 | return this.save(task); 42 | 43 | } 44 | 45 | 46 | // public Task getTaskByFileAttr(Long userId,Task task) { 47 | // 48 | // return this.getOne(new QueryWrapper() 49 | // .eq("user_id", userId) 50 | // .eq("file_path", task.getFilePath()) 51 | // .eq("file_name", task.getFileName()) 52 | // .eq("size", task.getSize()) 53 | // .eq("is_finished", task.getIsFinished()) 54 | // .eq("is_cancelled", task.getIsCancelled())); 55 | // } 56 | 57 | @Override 58 | public List getFinishedTasks(Long userId) { 59 | SimpleDateFormat simpleDateFormat = new SimpleDateFormat("MM/dd HH:mm"); 60 | simpleDateFormat.setTimeZone(TimeZone.getTimeZone("GMT+8")); 61 | List list = this.list(new QueryWrapper().eq("user_id", userId) 62 | .eq("is_finished", true) 63 | .eq("is_cancelled", false) 64 | .orderByDesc("create_time")); 65 | List res = new ArrayList(); 66 | list.forEach(e -> { 67 | GetFinishedTasksResp resp = new GetFinishedTasksResp(); 68 | BeanUtils.copyProperties(e,resp); 69 | resp.setCreateTimeStr(simpleDateFormat.format(e.getCreateTime())); 70 | res.add(resp); 71 | }); 72 | return res; 73 | } 74 | 75 | @Override 76 | public boolean updateTask(Long userId, Task task,Boolean finished) { 77 | task.setUserId(userId); 78 | task.setIsCancelled(false); 79 | Task dbTask = taskMapper.getLatestTask(userId, task); 80 | if (Objects.isNull(dbTask)) { 81 | throw new RuntimeException("任务不存在!"); 82 | } 83 | if (finished) { 84 | task.setIsFinished(true); 85 | }else { 86 | task.setIsCancelled(true); 87 | } 88 | task.setId(dbTask.getId()); 89 | return this.updateById(task); 90 | } 91 | 92 | @Override 93 | public boolean clear(Long userId) { 94 | return this.remove(new QueryWrapper() 95 | .eq("user_id", userId) 96 | .eq("is_finished", true) 97 | .eq("is_cancelled",false)); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/service/impl/UserCodeServiceImpl.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 4 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 5 | import org.springframework.stereotype.Service; 6 | import top.retain.nd.entity.UserCode; 7 | import top.retain.nd.mapper.IUserCodeMapper; 8 | import top.retain.nd.service.IUserCodeService; 9 | 10 | @Service 11 | public class UserCodeServiceImpl extends ServiceImpl implements IUserCodeService { 12 | @Override 13 | public UserCode getUserCode(Long userId, String code) { 14 | return this.getOne(new QueryWrapper() 15 | .eq("user_id", userId) 16 | .eq("code", code)); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/service/impl/UserSmsServiceImpl.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.service.impl; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.springframework.security.core.userdetails.UserDetails; 5 | import org.springframework.security.core.userdetails.UserDetailsService; 6 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 7 | import org.springframework.stereotype.Service; 8 | import top.retain.nd.entity.User; 9 | import top.retain.nd.mapper.IUserMapper; 10 | 11 | import javax.annotation.Resource; 12 | 13 | /** 14 | * @author Retain 15 | * @date 2021/10/19 16:22 16 | */ 17 | @Service("UserSmsServiceImpl") 18 | @Slf4j 19 | public class UserSmsServiceImpl implements UserDetailsService { 20 | 21 | @Resource 22 | IUserMapper userMapper; 23 | @Override 24 | public UserDetails loadUserByUsername(String phoneNumber) throws UsernameNotFoundException { 25 | if (phoneNumber == null || "".equals(phoneNumber)) { 26 | throw new UsernameNotFoundException("用户未找到"); 27 | } 28 | //根据用户名查询用户 29 | User user = userMapper.selectByPhone(phoneNumber); 30 | if (user == null) { 31 | throw new UsernameNotFoundException("账号未找到"); 32 | } 33 | log.info("查询到当前登陆用户id<" + user.getAccount() + ">"); 34 | return user; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/util/FileUtils.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.util; 2 | 3 | import com.aliyun.oss.common.utils.StringUtils; 4 | 5 | import java.io.File; 6 | import java.io.IOException; 7 | import java.text.DecimalFormat; 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | import java.util.Objects; 11 | 12 | /** 13 | * @author Retain 14 | * @date 2021/10/18 15:11 15 | */ 16 | public class FileUtils { 17 | 18 | // public static void main(String[] args) { 19 | // List dirFiles = getDirFiles("C:\\Users\\Retain\\Desktop\\upload"); 20 | // dirFiles.forEach(System.out::println); 21 | // } 22 | 23 | /** 24 | * 获取文件夹所有文件 25 | * @param file 文件夹本地路径 26 | * @return 所有文件path 27 | */ 28 | public static List getDirFiles(File file) { 29 | List files = null; 30 | if (file.isFile()) { 31 | System.out.println("您输入的是文件路径,请重新输入!"); 32 | } else if (!file.exists()) { 33 | System.out.println("您输入的文件夹不存在,请重新输入"); 34 | }else { 35 | try { 36 | files = getFiles(file, new ArrayList<>()); 37 | } catch (IOException e) { 38 | e.printStackTrace(); 39 | } 40 | } 41 | return files; 42 | } 43 | 44 | private static List getFiles(File dir, List files) throws IOException { 45 | File[] subFiles = dir.listFiles(); 46 | assert subFiles != null; 47 | for (File f1 : subFiles) { 48 | if (f1.isFile()){ 49 | files.add(f1.getCanonicalPath()); 50 | }else if (f1.isDirectory()) { 51 | // 空文件夹直接返回 52 | if (Objects.requireNonNull(f1.listFiles()).length == 0) { 53 | files.add(f1.getCanonicalPath()); 54 | }else { 55 | getFiles(f1, files); 56 | } 57 | } 58 | } 59 | return files; 60 | } 61 | 62 | public static Boolean isDir(String name) { 63 | if (StringUtils.isNullOrEmpty(name)) { 64 | return false; 65 | } 66 | if (name.lastIndexOf('.') > 0) { 67 | return false; 68 | } 69 | return true; 70 | } 71 | public static Boolean hasDir(String name) { 72 | if (StringUtils.isNullOrEmpty(name)) { 73 | return false; 74 | } 75 | if (name.lastIndexOf('/') > 0) { 76 | return true; 77 | } 78 | return false; 79 | } 80 | public static String[] seperate(String ossPath) { 81 | if (StringUtils.isNullOrEmpty(ossPath)) { 82 | return null; 83 | } 84 | String[] split = ossPath.split("/"); 85 | return split; 86 | } 87 | 88 | 89 | // 文件大小转换 90 | public static String getFileSize(long fileS) { 91 | DecimalFormat df = new DecimalFormat("#.00"); 92 | String fileSizeString = ""; 93 | if (fileS < 1024) { 94 | fileSizeString = df.format((double) fileS) + "B"; 95 | } else if (fileS < 1048576) { 96 | fileSizeString = df.format((double) fileS / 1024) + "KB"; 97 | } else if (fileS < 1073741824) { 98 | fileSizeString = df.format((double) fileS / 1048576) + "MB"; 99 | } else if (fileS < 1099511627776L){ 100 | fileSizeString = df.format((double) fileS / 1073741824) + "GB"; 101 | } else { 102 | fileSizeString = df.format((double) fileS / 1099511627776L) + "TB"; 103 | } 104 | return fileSizeString; 105 | } 106 | 107 | } 108 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/util/QRCodeUtils.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.util; 2 | 3 | import com.google.zxing.BarcodeFormat; 4 | import com.google.zxing.EncodeHintType; 5 | import com.google.zxing.MultiFormatWriter; 6 | import com.google.zxing.common.BitMatrix; 7 | import org.springframework.stereotype.Component; 8 | 9 | import javax.annotation.Resource; 10 | import javax.imageio.ImageIO; 11 | import java.awt.image.BufferedImage; 12 | import java.io.File; 13 | import java.io.IOException; 14 | import java.io.OutputStream; 15 | import java.util.HashMap; 16 | import java.util.Map; 17 | 18 | /** 19 | * @author Retain 20 | * @date 2021/11/21 12:20 21 | */ 22 | @Component 23 | public class QRCodeUtils { 24 | 25 | @Resource 26 | OSSUtils ossUtils; 27 | private static String PATH = "/www/wwwroot/nd/target/classes/qr"; 28 | 29 | 30 | public String createQrCode(String url, String fileName) { 31 | String reqUrl= ""; 32 | try { 33 | Map hints = new HashMap<>(); 34 | hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); 35 | BitMatrix bitMatrix = new MultiFormatWriter().encode(url, BarcodeFormat.QR_CODE, 400, 400, hints); 36 | File file = new File(PATH, fileName); 37 | if (file.exists() || ((file.getParentFile().exists() || file.getParentFile().mkdirs()) && file.createNewFile())) { 38 | writeToFile(bitMatrix, "jpg", file); 39 | System.out.println("成功:" + file); 40 | reqUrl = ossUtils.uploadImg(file); 41 | } 42 | 43 | } catch (Exception e) { 44 | e.printStackTrace(); 45 | } 46 | return reqUrl; 47 | } 48 | 49 | void writeToFile(BitMatrix matrix, String format, File file) throws IOException { 50 | BufferedImage image = toBufferedImage(matrix); 51 | if (!ImageIO.write(image, format, file)) { 52 | throw new IOException("Could not write an image of format " + format + " to " + file); 53 | } 54 | } 55 | 56 | void writeToStream(BitMatrix matrix, String format, OutputStream stream) throws IOException { 57 | BufferedImage image = toBufferedImage(matrix); 58 | if (!ImageIO.write(image, format, stream)) { 59 | throw new IOException("Could not write an image of format " + format); 60 | } 61 | } 62 | 63 | private static final int BLACK = 0x00000000; 64 | private static final int WHITE = 0xFFFFFFFF; 65 | 66 | private BufferedImage toBufferedImage(BitMatrix matrix) { 67 | int width = matrix.getWidth(); 68 | int height = matrix.getHeight(); 69 | BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); 70 | for (int x = 0; x < width; x++) { 71 | for (int y = 0; y < height; y++) { 72 | image.setRGB(x, y, matrix.get(x, y) ? BLACK : WHITE); 73 | } 74 | } 75 | return image; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/util/RequestWrapper.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.util; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | 5 | import javax.servlet.ReadListener; 6 | import javax.servlet.ServletInputStream; 7 | import javax.servlet.ServletRequest; 8 | import javax.servlet.http.HttpServletRequest; 9 | import javax.servlet.http.HttpServletRequestWrapper; 10 | import java.io.*; 11 | import java.nio.charset.Charset; 12 | 13 | /** 14 | * @Author: retain 15 | * @Date: 2021/4/2 16 | * @Content: 包装request, 解决request body只能读取一次的问题. 17 | */ 18 | @Slf4j 19 | public class RequestWrapper extends HttpServletRequestWrapper { 20 | 21 | /** 22 | * 存储body数据的容器 23 | */ 24 | private final byte[] body; 25 | 26 | public RequestWrapper(HttpServletRequest request) throws IOException { 27 | super(request); 28 | 29 | // 将body数据存储起来 30 | String bodyStr = getBodyString(request); 31 | body = bodyStr.getBytes(Charset.defaultCharset()); 32 | } 33 | 34 | /** 35 | * 获取请求Body 36 | * 37 | * @param request request 38 | * @return String 39 | */ 40 | public String getBodyString(final ServletRequest request) { 41 | try { 42 | return inputStream2String(request.getInputStream()); 43 | } catch (IOException e) { 44 | log.error("request body读取错误", e); 45 | throw new RuntimeException(e); 46 | } 47 | } 48 | 49 | /** 50 | * 获取请求Body 51 | * 52 | * @return String 53 | */ 54 | public String getBodyString() { 55 | final InputStream inputStream = new ByteArrayInputStream(body); 56 | 57 | return inputStream2String(inputStream); 58 | } 59 | 60 | /** 61 | * 将inputStream里的数据读取出来并转换成字符串 62 | * 63 | * @param inputStream inputStream 64 | * @return String 65 | */ 66 | private String inputStream2String(InputStream inputStream) { 67 | StringBuilder sb = new StringBuilder(); 68 | BufferedReader reader = null; 69 | 70 | try { 71 | reader = new BufferedReader(new InputStreamReader(inputStream, Charset.defaultCharset())); 72 | String line; 73 | while ((line = reader.readLine()) != null) { 74 | sb.append(line).append("\n"); 75 | } 76 | } catch (IOException e) { 77 | log.error("", e); 78 | throw new RuntimeException(e); 79 | } finally { 80 | if (reader != null) { 81 | try { 82 | reader.close(); 83 | } catch (IOException e) { 84 | log.error("流已经关闭", e); 85 | } 86 | } 87 | } 88 | 89 | return sb.toString(); 90 | } 91 | 92 | @Override 93 | public BufferedReader getReader() throws IOException { 94 | return new BufferedReader(new InputStreamReader(getInputStream())); 95 | } 96 | 97 | @Override 98 | public ServletInputStream getInputStream() throws IOException { 99 | 100 | final ByteArrayInputStream inputStream = new ByteArrayInputStream(body); 101 | 102 | return new ServletInputStream() { 103 | @Override 104 | public int read() throws IOException { 105 | return inputStream.read(); 106 | } 107 | 108 | @Override 109 | public boolean isFinished() { 110 | return false; 111 | } 112 | 113 | @Override 114 | public boolean isReady() { 115 | return false; 116 | } 117 | 118 | @Override 119 | public void setReadListener(ReadListener readListener) { 120 | } 121 | }; 122 | } 123 | 124 | 125 | } 126 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/util/SmsUtil.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.util; 2 | 3 | 4 | import cn.hutool.json.JSONException; 5 | import com.github.qcloudsms.SmsSingleSender; 6 | import com.github.qcloudsms.SmsSingleSenderResult; 7 | import com.github.qcloudsms.httpclient.HTTPException; 8 | import lombok.extern.slf4j.Slf4j; 9 | import org.springframework.beans.factory.annotation.Value; 10 | import org.springframework.stereotype.Component; 11 | 12 | import java.io.IOException; 13 | import java.util.Arrays; 14 | 15 | @Slf4j 16 | @Component 17 | public class SmsUtil { 18 | 19 | public static final String SMS_SUCCESS = "OK"; 20 | private final static int appid = 1400489215; 21 | private final static String appkey = "*"; 22 | private static String profiles; 23 | 24 | 25 | @Value("${spring.profiles.active}") 26 | public void setProfiles(String profile) { 27 | profiles = profile; 28 | // profiles = Constants.TEST_PROFILE; 29 | } 30 | 31 | // 876859:第一条通知模板 877079:第二条通知模板 879648: 绑定验证码模板 32 | public static boolean sendSms(int templateId, String[] phoneNumbers, String[] params) { 33 | if ("dev".equals(profiles)) { 34 | log.info("SmsUtil工具类发送验证码到" + Arrays.toString(phoneNumbers)); 35 | } else { 36 | log.info("SmsUtil工具类发送验证码到" + Arrays.toString(phoneNumbers)); 37 | String smsSign = "*"; 38 | try { 39 | SmsSingleSender sender = new SmsSingleSender(appid, appkey); 40 | for (String number : phoneNumbers) { 41 | SmsSingleSenderResult result = sender.sendWithParam("86", number, 42 | templateId, params, smsSign, "", ""); 43 | if (!SMS_SUCCESS.equalsIgnoreCase(result.errMsg)) { 44 | log.info("发送失败!" + number+"原因:"+result.errMsg); 45 | } 46 | log.info("发送成功!" + number); 47 | } 48 | } catch (HTTPException | JSONException | IOException e) { 49 | e.printStackTrace(); 50 | } 51 | } 52 | return true; 53 | } 54 | // String[] phoneNumbers = {"13551796434","17762474097"}; 55 | 56 | // public static String[] getNoticeFields(JSONObject jsonObject, int type){ 57 | // List params=new ArrayList<>(); 58 | // // todo: 不好拓展, 有待重构 59 | // switch (type){ 60 | // case 0: 61 | // getSpecificFields(params,jsonObject,CONVENE_FIELDS); 62 | // break; 63 | // case 1: 64 | // getSpecificFields(params,jsonObject,CLUE_FIELDS); 65 | // break; 66 | // case 2: 67 | // getSpecificFields(params,jsonObject,EMERGENCY_FIELDS); 68 | // break; 69 | // case 3 : 70 | // getSpecificFields(params,jsonObject,END_ACTION_FIELD); 71 | // break; 72 | // default : 73 | // System.err.println("未匹配到短信参数!"); 74 | // break; 75 | // } 76 | // return ArrayUtil.toArray(params.listIterator(),String.class); 77 | // } 78 | 79 | // private static void getSpecificFields(List list, JSONObject jsonObject, List fields){ 80 | // if (jsonObject.keySet().containsAll(fields)){ 81 | // fields.forEach(v->{ 82 | // Object o = jsonObject.get(v); 83 | // list.add(o.toString()); 84 | // }); 85 | // } 86 | // } 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/util/SpringSecurityUtil.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.util; 2 | 3 | import org.springframework.security.core.context.SecurityContextImpl; 4 | import org.springframework.stereotype.Component; 5 | import top.retain.nd.exception.UserNotLoginException; 6 | 7 | import javax.servlet.http.HttpSession; 8 | 9 | /** 10 | * @author Retain 11 | * @date 2021/10/3 14:54 12 | */ 13 | @Component 14 | public class SpringSecurityUtil { 15 | public static String currentUser(HttpSession session) { 16 | SecurityContextImpl securityContext = (SecurityContextImpl) session.getAttribute("SPRING_SECURITY_CONTEXT"); 17 | if (securityContext == null) { 18 | throw new UserNotLoginException("请先登录!"); 19 | } 20 | return String.valueOf(securityContext.getAuthentication().getPrincipal()); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/util/VerifyCodeUtils.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.util; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.stereotype.Component; 6 | 7 | 8 | /** 9 | * 验证码生成工具类 10 | * 11 | * @author Retain 12 | */ 13 | @Component 14 | @Slf4j 15 | public class VerifyCodeUtils { 16 | 17 | 18 | 19 | public static final String CODE_PREFIX="code:"; 20 | 21 | @Autowired 22 | RedisUtils redisUtils; 23 | 24 | public static final int VERIFY_CODE_LEN = 6; 25 | 26 | public static String generate() { 27 | return String.valueOf((int) ((Math.random() * 9 + 1) * Math.pow(10, VERIFY_CODE_LEN - 1))); 28 | } 29 | 30 | /** 31 | * 验证验证码 32 | * @param phoneNumber 33 | * @param code 34 | * @return 35 | */ 36 | public boolean matchVerifyCode(String phoneNumber,String code) { 37 | // 不存在验证码或验证码错误 38 | boolean match = redisUtils.hasKey(CODE_PREFIX + phoneNumber) && code.equals(redisUtils.get(CODE_PREFIX + phoneNumber)); 39 | if (match) { 40 | redisUtils.delete(CODE_PREFIX + phoneNumber); 41 | } 42 | return match; 43 | } 44 | 45 | /** 46 | * 发送验证码 47 | * @param phoneNumber 48 | * @return 49 | */ 50 | public boolean sendVerifyCode(String phoneNumber) { 51 | String code = generate(); 52 | log.info("手机号:"+phoneNumber+"验证码:"+code); 53 | String[] params={code,"10"}; 54 | // 存入缓存 55 | boolean set = redisUtils.set(CODE_PREFIX + phoneNumber, code); 56 | // 有效时间10分钟 57 | redisUtils.expire(CODE_PREFIX + phoneNumber,600L); 58 | if (set) { 59 | log.info("验证码成功存入缓存"); 60 | if (SmsUtil.sendSms(879648, new String[]{phoneNumber}, params)){ 61 | log.info("短信成功发送到 "+phoneNumber); 62 | return true; 63 | } 64 | } 65 | return false; 66 | // TODO: 2021/3/1 这里执行完毕后不会关闭连接, 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/top/retain/nd/vo/UserVo.java: -------------------------------------------------------------------------------- 1 | package top.retain.nd.vo; 2 | 3 | import java.io.Serializable; 4 | import java.util.Date; 5 | 6 | /** 7 | * @author Retain 8 | * @date 2021/11/9 21:12 9 | */ 10 | public class UserVo implements Serializable { 11 | private Long id; 12 | private String name; 13 | private String account; 14 | private String phoneNumber; 15 | private Date createTime; 16 | private Date updateTime; 17 | private boolean deleted; 18 | private String avater; 19 | } 20 | -------------------------------------------------------------------------------- /src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | spring: 2 | profiles: 3 | active: prod 4 | # resources: 5 | # add-mappings: false 6 | mvc: 7 | throw-exception-if-no-handler-found: true 8 | converters: 9 | preferred-json-mapper: jackson 10 | static-path-pattern: /static/** 11 | # 数据库初始化配置 12 | datasource: 13 | schema: classpath:sql/schema.sql 14 | data: classpath:sql/data.sql 15 | initialization-mode: never 16 | dbcp2: 17 | test-on-borrow: true 18 | test-while-idle: true 19 | servlet: 20 | multipart: 21 | max-file-size: 10MB 22 | max-request-size: 1GB 23 | jackson: 24 | serialization: 25 | FAIL_ON_EMPTY_BEANS: off 26 | redis: 27 | password: * 28 | lettuce: 29 | shutdown-timeout: 500000 30 | 31 | port: 6379 32 | server: 33 | port: 8808 34 | mybatis-plus: 35 | mapper-locations: top/retain/nd/mappers/*.xml 36 | configuration: 37 | log-impl: org.apache.ibatis.logging.stdout.StdOutImpl 38 | 39 | user: 40 | init-space: 21474836480 # 默认20G,可手动配置,注册时自动读取 41 | logging: 42 | level: 43 | root: info 44 | OSS: 45 | ram: 46 | accessKeyId: * 47 | accessKeySecret: * 48 | roleArn: * 49 | endpoint: * 50 | accessKeyId: * 51 | accessKeySecret: * 52 | region: * 53 | #bucket可以在控制台创建,也可以使用java代码创建 54 | 55 | --- 56 | spring: 57 | profiles: dev 58 | redis: 59 | host: * 60 | datasource: 61 | url: jdbc:mysql://localhost:3306/network_disk?serverTimezone=Asia/Shanghai 62 | driver-class-name: com.mysql.cj.jdbc.Driver 63 | username: root 64 | password: qwer 65 | --- 66 | spring: 67 | profiles: prod 68 | redis: 69 | host: * 70 | datasource: 71 | url: jdbc:mysql://*:3306/network_disk?serverTimezone=Asia/Shanghai 72 | driver-class-name: com.mysql.cj.jdbc.Driver 73 | username: * 74 | password: * -------------------------------------------------------------------------------- /src/main/resources/logback-spring.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | logback 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | INFO 29 | 30 | 31 | ${CONSOLE_LOG_PATTERN} 32 | 33 | UTF-8 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | ${log.path}/log_info.log 44 | 45 | 46 | %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n 47 | UTF-8 48 | 49 | 50 | 51 | 52 | ${log.path}/info/log-info-%d{yyyy-MM-dd}.%i.log 53 | 54 | 100MB 55 | 56 | 57 | 15 58 | 59 | 60 | 61 | INFO 62 | ACCEPT 63 | DENY 64 | 65 | 66 | 67 | 68 | 69 | 70 | ${log.path}/log_warn.log 71 | 72 | 73 | %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n 74 | UTF-8 75 | 76 | 77 | 78 | ${log.path}/warn/log-warn-%d{yyyy-MM-dd}.%i.log 79 | 80 | 100MB 81 | 82 | 83 | 15 84 | 85 | 86 | 87 | warn 88 | ACCEPT 89 | DENY 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | ${log.path}/log_error.log 99 | 100 | 101 | %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n 102 | UTF-8 103 | 104 | 105 | 106 | ${log.path}/error/log-error-%d{yyyy-MM-dd}.%i.log 107 | 108 | 100MB 109 | 110 | 111 | 15 112 | 113 | 114 | 115 | ERROR 116 | ACCEPT 117 | DENY 118 | 119 | 120 | 121 | 129 | 134 | 135 | 136 | 137 | 138 | 139 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | -------------------------------------------------------------------------------- /src/main/resources/sql/data.sql: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Retainv/cloud-disk-based-on-oss/510a27a09d046d961bc60132cdde990c40c250e3/src/main/resources/sql/data.sql --------------------------------------------------------------------------------