v1.3 版本发布,详细信息查看发行版说明

pull/111/head
郑杰 2018-12-31 16:59:03 +08:00
parent d329b0c8b0
commit 1ec10e3d38
48 changed files with 1776 additions and 88 deletions

View File

@ -1,6 +1,6 @@
# eladmin
项目基于 Spring Boot 2.1.0 、 Spring boot Jpa、 Spring Security、redis、Vue的前后端分离的权限管理系统 权限控制采用 RBAC 思想,支持 动态路由、项目1.0版本提供一个纯净的后台管理,第三方工具将在后面的版本中添加
项目基于 Spring Boot 2.1.0 、 Spring boot Jpa、 Spring Security、redis、Vue的前后端分离的权限管理系统 权限控制采用 RBAC 思想,支持动态路由
#### 前端源码
- 码云:[https://gitee.com/elunez/eladmin-qt](https://gitee.com/elunez/eladmin-qt)
@ -14,21 +14,29 @@
#### 预览地址
[http://auauz.net](http://auauz.net)
- 用户名: admin
##### 用户账号
- 管理员: admin
- 测试用户: test
##### 默认密码
- 密码: 123456
#### 系统功能模块
- 用户管理 提供用户的相关配置
- 个人中心 提供修改头像,密码,邮箱验等功能
- 角色管理 角色菜单分配权限
- 权限管理 权限细化到接口
- 菜单管理 已实现动态路由,后端可配置化
- 系统日志 记录用户访问监控异常信息
- 实时控制台 显示logback实时日志
- 实时控制台 显示logback实时日志,可显示异常堆栈信息
- redis管理 将redis的操作可视化提供对redis的基本操作
- redis限流 对系统的流量进行控制,由[everhopingandwaiting](https://github.com/everhopingandwaiting)提供
- SQL监控 采用 druid 监控数据库访问性能
- 三方工具: 邮件工具sm.ms免费图床
- 三方工具: 邮件工具sm.ms免费图床,支付宝支付,七牛云存储
- 富文本编辑器
#### 后端技术栈
@ -64,11 +72,15 @@
</tr>
<tr>
<td><img src="https://i.loli.net/2018/12/22/5c1e10c7a9f7d.png"/></td>
<td><img src="https://i.imgur.com/FzVaAlS.png"/></td>
</tr>
<tr>
<td><img src="https://i.imgur.com/ah3X2HG.png"/></td>
</tr>
</table>
#### 反馈交流
- QQ交流群891137268
- QQ交流群<a target="_blank" href="//shang.qq.com/wpa/qunwpa?idkey=90830191a40600e3a07acdcc4864890fca50c8e3ca1772e7e288a561d576f6c4"><img border="0" src="//pub.idqqimg.com/wpa/images/group.png" alt="Quella/el-admin" title="Quella/el-admin"></a>
- 作者邮箱elunez@qq.com

14
pom.xml
View File

@ -161,6 +161,20 @@
<version>1.4.7</version>
</dependency>
<!--七牛云存储-->
<dependency>
<groupId>com.qiniu</groupId>
<artifactId>qiniu-java-sdk</artifactId>
<version>[7.2.0, 7.2.99]</version>
</dependency>
<!--支付宝依赖-->
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>3.1.0</version>
</dependency>
</dependencies>
<repositories>

View File

@ -11,12 +11,36 @@
Target Server Version : 50559
File Encoding : 65001
Date: 28/12/2018 17:50:46
Date: 31/12/2018 15:52:01
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for alipay_config
-- ----------------------------
DROP TABLE IF EXISTS `alipay_config`;
CREATE TABLE `alipay_config` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`appID` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`charset` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`format` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`gatewayUrl` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`notifyUrl` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`privateKey` varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`publicKey` varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`returnUrl` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`signType` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`sysServiceProviderId` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Records of alipay_config
-- ----------------------------
INSERT INTO `alipay_config` VALUES (1, '2016091700532697', 'utf-8', 'JSON', 'https://openapi.alipaydev.com/gateway.do', 'http://api.auauz.net/api/aliPay/notify', 'MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC5js8sInU10AJ0cAQ8UMMyXrQ+oHZEkVt5lBwsStmTJ7YikVYgbskx1YYEXTojRsWCb+SH/kDmDU4pK/u91SJ4KFCRMF2411piYuXU/jF96zKrADznYh/zAraqT6hvAIVtQAlMHN53nx16rLzZ/8jDEkaSwT7+HvHiS+7sxSojnu/3oV7BtgISoUNstmSe8WpWHOaWv19xyS+Mce9MY4BfseFhzTICUymUQdd/8hXA28/H6osUfAgsnxAKv7Wil3aJSgaJczWuflYOve0dJ3InZkhw5Cvr0atwpk8YKBQjy5CdkoHqvkOcIB+cYHXJKzOE5tqU7inSwVbHzOLQ3XbnAgMBAAECggEAVJp5eT0Ixg1eYSqFs9568WdetUNCSUchNxDBu6wxAbhUgfRUGZuJnnAll63OCTGGck+EGkFh48JjRcBpGoeoHLL88QXlZZbC/iLrea6gcDIhuvfzzOffe1RcZtDFEj9hlotg8dQj1tS0gy9pN9g4+EBH7zeu+fyv+qb2e/v1l6FkISXUjpkD7RLQr3ykjiiEw9BpeKb7j5s7Kdx1NNIzhkcQKNqlk8JrTGDNInbDM6inZfwwIO2R1DHinwdfKWkvOTODTYa2MoAvVMFT9Bec9FbLpoWp7ogv1JMV9svgrcF9XLzANZ/OQvkbe9TV9GWYvIbxN6qwQioKCWO4GPnCAQKBgQDgW5MgfhX8yjXqoaUy/d1VjI8dHeIyw8d+OBAYwaxRSlCfyQ+tieWcR2HdTzPca0T0GkWcKZm0ei5xRURgxt4DUDLXNh26HG0qObbtLJdu/AuBUuCqgOiLqJ2f1uIbrz6OZUHns+bT/jGW2Ws8+C13zTCZkZt9CaQsrp3QOGDx5wKBgQDTul39hp3ZPwGNFeZdkGoUoViOSd5Lhowd5wYMGAEXWRLlU8z+smT5v0POz9JnIbCRchIY2FAPKRdVTICzmPk2EPJFxYTcwaNbVqL6lN7J2IlXXMiit5QbiLauo55w7plwV6LQmKm9KV7JsZs5XwqF7CEovI7GevFzyD3w+uizAQKBgC3LY1eRhOlpWOIAhpjG6qOoohmeXOphvdmMlfSHq6WYFqbWwmV4rS5d/6LNpNdL6fItXqIGd8I34jzql49taCmi+A2nlR/E559j0mvM20gjGDIYeZUz5MOE8k+K6/IcrhcgofgqZ2ZED1ksHdB/E8DNWCswZl16V1FrfvjeWSNnAoGAMrBplCrIW5xz+J0Hm9rZKrs+AkK5D4fUv8vxbK/KgxZ2KaUYbNm0xv39c+PZUYuFRCz1HDGdaSPDTE6WeWjkMQd5mS6ikl9hhpqFRkyh0d0fdGToO9yLftQKOGE/q3XUEktI1XvXF0xyPwNgUCnq0QkpHyGVZPtGFxwXiDvpvgECgYA5PoB+nY8iDiRaJNko9w0hL4AeKogwf+4TbCw+KWVEn6jhuJa4LFTdSqp89PktQaoVpwv92el/AhYjWOl/jVCm122f9b7GyoelbjMNolToDwe5pF5RnSpEuDdLy9MfE8LnE3PlbE7E5BipQ3UjSebkgNboLHH/lNZA5qvEtvbfvQ==', 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAut9evKRuHJ/2QNfDlLwvN/S8l9hRAgPbb0u61bm4AtzaTGsLeMtScetxTWJnVvAVpMS9luhEJjt+Sbk5TNLArsgzzwARgaTKOLMT1TvWAK5EbHyI+eSrc3s7Awe1VYGwcubRFWDm16eQLv0k7iqiw+4mweHSz/wWyvBJVgwLoQ02btVtAQErCfSJCOmt0Q/oJQjj08YNRV4EKzB19+f5A+HQVAKy72dSybTzAK+3FPtTtNen/+b5wGeat7c32dhYHnGorPkPeXLtsqqUTp1su5fMfd4lElNdZaoCI7osZxWWUo17vBCZnyeXc9fk0qwD9mK6yRAxNbrY72Xx5VqIqwIDAQAB', 'http://api.auauz.ne/api/aliPay/return', 'RSA2', '2088102176044281');
-- ----------------------------
-- Table structure for email_config
-- ----------------------------
@ -31,6 +55,24 @@ CREATE TABLE `email_config` (
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Table structure for log
-- ----------------------------
DROP TABLE IF EXISTS `log`;
CREATE TABLE `log` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`createTime` datetime NULL DEFAULT NULL,
`description` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`exceptionDetail` varchar(1500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`logType` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`method` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`params` varchar(1500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`requestIp` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`time` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4214 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Table structure for menu
-- ----------------------------
@ -46,7 +88,7 @@ CREATE TABLE `menu` (
`icon` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`path` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 18 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
) ENGINE = InnoDB AUTO_INCREMENT = 20 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Records of menu
@ -59,7 +101,7 @@ INSERT INTO `menu` VALUES (5, '2018-12-18 15:17:28', b'0', '菜单管理', 'syst
INSERT INTO `menu` VALUES (6, '2018-12-18 15:17:48', b'0', '系统监控', NULL, 0, 10, 'monitor', 'monitor');
INSERT INTO `menu` VALUES (7, '2018-12-18 15:18:26', b'0', '系统日志', 'monitor/log/index', 6, 11, 'log', 'logs');
INSERT INTO `menu` VALUES (8, '2018-12-18 15:19:01', b'0', '系统缓存', 'monitor/redis/index', 6, 12, 'redis', 'redis');
INSERT INTO `menu` VALUES (9, '2018-12-18 15:19:34', b'1', 'SQL监控', NULL, 6, 14, 'sqlMonitor', 'http://localhost/druid');
INSERT INTO `menu` VALUES (9, '2018-12-18 15:19:34', b'1', 'SQL监控', NULL, 6, 14, 'sqlMonitor', 'http://localhost:8000/druid');
INSERT INTO `menu` VALUES (10, '2018-12-19 13:38:16', b'0', '组件管理', NULL, 0, 50, 'zujian', 'components');
INSERT INTO `menu` VALUES (11, '2018-12-19 13:38:49', b'0', '图标库', 'components/IconSelect', 10, 51, 'icon', 'icon');
INSERT INTO `menu` VALUES (12, '2018-12-24 20:37:35', b'0', '实时控制台', 'monitor/log/msg', 6, 13, 'codeConsole', 'msg');
@ -68,6 +110,8 @@ INSERT INTO `menu` VALUES (14, '2018-12-27 10:13:09', b'0', '邮件工具', 'too
INSERT INTO `menu` VALUES (15, '2018-12-27 11:58:25', b'0', '富文本', 'components/Editor', 10, 52, 'fwb', 'tinymce');
INSERT INTO `menu` VALUES (16, '2018-12-28 09:36:53', b'0', 'SM.MS图床', 'tools/picture/index', 13, 22, 'image', 'pictures');
INSERT INTO `menu` VALUES (17, '2018-12-28 15:09:49', b'1', '项目地址', '', 0, 0, 'github', 'https://github.com/elunez/eladmin');
INSERT INTO `menu` VALUES (18, '2018-12-31 11:12:15', b'0', '七牛云存储', 'tools/qiniu/index', 13, 23, 'qiniu', 'qiniu');
INSERT INTO `menu` VALUES (19, '2018-12-31 14:52:38', b'0', '支付宝工具', 'tools/aliPay/index', 13, 24, 'alipay', 'aliPay');
-- ----------------------------
-- Table structure for menus_roles
@ -102,6 +146,8 @@ INSERT INTO `menus_roles` VALUES (14, 1);
INSERT INTO `menus_roles` VALUES (15, 1);
INSERT INTO `menus_roles` VALUES (16, 1);
INSERT INTO `menus_roles` VALUES (17, 1);
INSERT INTO `menus_roles` VALUES (18, 1);
INSERT INTO `menus_roles` VALUES (19, 1);
INSERT INTO `menus_roles` VALUES (1, 2);
INSERT INTO `menus_roles` VALUES (2, 2);
INSERT INTO `menus_roles` VALUES (3, 2);
@ -111,8 +157,11 @@ INSERT INTO `menus_roles` VALUES (6, 2);
INSERT INTO `menus_roles` VALUES (9, 2);
INSERT INTO `menus_roles` VALUES (12, 2);
INSERT INTO `menus_roles` VALUES (13, 2);
INSERT INTO `menus_roles` VALUES (14, 2);
INSERT INTO `menus_roles` VALUES (16, 2);
INSERT INTO `menus_roles` VALUES (17, 2);
INSERT INTO `menus_roles` VALUES (18, 2);
INSERT INTO `menus_roles` VALUES (19, 2);
-- ----------------------------
-- Table structure for permission
@ -176,12 +225,37 @@ CREATE TABLE `picture` (
`username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`width` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 38 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
) ENGINE = InnoDB AUTO_INCREMENT = 47 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Records of picture
-- Table structure for qiniu_config
-- ----------------------------
INSERT INTO `picture` VALUES (34, '2018-12-28 16:02:42', 'https://sm.ms/delete/JDAtayhFMH56wCXE', '1', '220', '3.73KB ', 'https://i.loli.net/2018/12/28/5c25d8a253445.jpg', 'admin', '229');
DROP TABLE IF EXISTS `qiniu_config`;
CREATE TABLE `qiniu_config` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`accessKey` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`bucket` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`host` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`secretKey` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`type` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`zone` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Table structure for qiniu_content
-- ----------------------------
DROP TABLE IF EXISTS `qiniu_content`;
CREATE TABLE `qiniu_content` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`bucket` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`size` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`type` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`updateTime` datetime NULL DEFAULT NULL,
`url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 10 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Table structure for role
@ -246,8 +320,8 @@ CREATE TABLE `user` (
-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, 'https://i.loli.net/2018/12/06/5c08894d8de21.jpg', '2018-08-23 09:11:56', 'zhengjie@tom.com', 1, '14e1b600b1fd579f47433b88e8d85291', 'admin', '2018-11-23 10:12:36');
INSERT INTO `user` VALUES (3, 'https://i.loli.net/2018/12/06/5c08894d8de21.jpg', '2018-12-27 20:05:26', 'test@qq.com', 1, '14e1b600b1fd579f47433b88e8d85291', 'test', NULL);
INSERT INTO `user` VALUES (1, 'https://i.loli.net/2018/12/31/5c297270b20e2.jpg', '2018-08-23 09:11:56', 'elunez@qq.com', 1, '14e1b600b1fd579f47433b88e8d85291', 'admin', '2018-11-23 10:12:36');
INSERT INTO `user` VALUES (3, 'https://i.loli.net/2018/12/30/5c2871d6aa101.jpg', '2018-12-27 20:05:26', 'test@qq.com', 1, '14e1b600b1fd579f47433b88e8d85291', 'test', NULL);
-- ----------------------------
-- Table structure for users_roles
@ -279,8 +353,27 @@ CREATE TABLE `verification_code` (
`status` bit(1) NULL DEFAULT NULL,
`type` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`value` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`scenes` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
) ENGINE = InnoDB AUTO_INCREMENT = 32 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Table structure for visits
-- ----------------------------
DROP TABLE IF EXISTS `visits`;
CREATE TABLE `visits` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`date` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`ip_counts` bigint(20) NULL DEFAULT NULL,
`pv_counts` bigint(20) NULL DEFAULT NULL,
`weekDay` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`createTime` datetime NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 47 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Records of visits
-- ----------------------------
INSERT INTO `visits` VALUES (46, '2018-12-31', 1, 3, 'Mon', '2018-12-31 15:50:19');
SET FOREIGN_KEY_CHECKS = 1;

View File

@ -13,6 +13,9 @@ import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.PrintWriter;
import java.io.StringWriter;
/**
* @author jie
* @date 2018-11-24

View File

@ -3,6 +3,8 @@ package me.zhengjie.common.exception;
import lombok.Getter;
import org.springframework.http.HttpStatus;
import static org.springframework.http.HttpStatus.BAD_REQUEST;
/**
* @author jie
* @date 2018-11-23
@ -10,7 +12,15 @@ import org.springframework.http.HttpStatus;
*/
@Getter
public class BadRequestException extends RuntimeException{
private Integer status = BAD_REQUEST.value();
public BadRequestException(String msg){
super(msg);
}
public BadRequestException(HttpStatus status,String msg){
super(msg);
this.status = status.value();
}
}

View File

@ -6,10 +6,14 @@ import me.zhengjie.common.exception.EntityExistException;
import me.zhengjie.common.exception.EntityNotFoundException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.io.PrintWriter;
import java.io.StringWriter;
import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.http.HttpStatus.FORBIDDEN;
import static org.springframework.http.HttpStatus.NOT_FOUND;
/**
@ -20,6 +24,32 @@ import static org.springframework.http.HttpStatus.NOT_FOUND;
@RestControllerAdvice
public class GlobalExceptionHandler {
/**
*
* @param e
* @return
*/
@ExceptionHandler(Exception.class)
public ResponseEntity handleException(Exception e){
// 打印堆栈信息
log.error(getStackTrace(e));
ApiError apiError = new ApiError(BAD_REQUEST.value(),e.getMessage());
return buildResponseEntity(apiError);
}
/**
* 访AccessDeniedException
* @param e
* @return
*/
@ExceptionHandler(AccessDeniedException.class)
public ResponseEntity handleAccessDeniedException(AccessDeniedException e){
// 打印堆栈信息
log.error(getStackTrace(e));
ApiError apiError = new ApiError(FORBIDDEN.value(),e.getMessage());
return buildResponseEntity(apiError);
}
/**
*
* @param e
@ -27,8 +57,9 @@ public class GlobalExceptionHandler {
*/
@ExceptionHandler(value = BadRequestException.class)
public ResponseEntity<ApiError> badRequestException(BadRequestException e) {
log.error(e.getMessage());
ApiError apiError = new ApiError(BAD_REQUEST.value(),e.getMessage());
// 打印堆栈信息
log.error(getStackTrace(e));
ApiError apiError = new ApiError(e.getStatus(),e.getMessage());
return buildResponseEntity(apiError);
}
@ -39,7 +70,8 @@ public class GlobalExceptionHandler {
*/
@ExceptionHandler(value = EntityExistException.class)
public ResponseEntity<ApiError> entityExistException(EntityExistException e) {
log.error(e.getMessage());
// 打印堆栈信息
log.error(getStackTrace(e));
ApiError apiError = new ApiError(BAD_REQUEST.value(),e.getMessage());
return buildResponseEntity(apiError);
}
@ -51,7 +83,8 @@ public class GlobalExceptionHandler {
*/
@ExceptionHandler(value = EntityNotFoundException.class)
public ResponseEntity<ApiError> entityNotFoundException(EntityNotFoundException e) {
log.error(e.getMessage());
// 打印堆栈信息
log.error(getStackTrace(e));
ApiError apiError = new ApiError(NOT_FOUND.value(),e.getMessage());
return buildResponseEntity(apiError);
}
@ -63,7 +96,8 @@ public class GlobalExceptionHandler {
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ApiError> handleMethodArgumentNotValidException(MethodArgumentNotValidException e){
log.error(e.getMessage());
// 打印堆栈信息
log.error(getStackTrace(e));
String[] str = e.getBindingResult().getAllErrors().get(0).getCodes()[1].split("\\.");
StringBuffer msg = new StringBuffer(str[1]+":");
msg.append(e.getBindingResult().getAllErrors().get(0).getDefaultMessage());
@ -79,4 +113,21 @@ public class GlobalExceptionHandler {
private ResponseEntity<ApiError> buildResponseEntity(ApiError apiError) {
return new ResponseEntity(apiError, HttpStatus.valueOf(apiError.getStatus()));
}
/**
*
* @param throwable
* @return
*/
private String getStackTrace(Throwable throwable)
{
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
try {
throwable.printStackTrace(pw);
return "\n"+sw.toString();
} finally {
pw.close();
}
}
}

View File

@ -7,21 +7,13 @@ package me.zhengjie.common.utils;
*/
public class ElAdminConstant {
/**
* zone
*/
public static class QiNiu{
public static final String RESET_PASS = "重置密码";
public static final String HUAD = "华东";
public static final String RESET_MAIL = "重置邮箱";
public static final String HUAB = "华北";
public static final String EMAIL_CODE = "<p>你的验证码为:";
public static final String HUAN = "华南";
public static final String BEIM = "北美";
public static final String DNY = "东南亚";
}
public static final String EMAIL_CONTENT = "<p style='text-align: right;'>----- 邮件来自<span style='color: rgb(194, 79, 74);'>&nbsp;<a href='http://auauz.net' target='_blank'>eladmin</a></span>&nbsp;后台管理系统,系统邮件请勿回复</p>";
/**
*

View File

@ -78,12 +78,18 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
.antMatchers("/auth/**").permitAll()
.antMatchers("/websocket/**").permitAll()
.antMatchers("/druid/**").anonymous()
// 支付宝回调
.antMatchers("/api/aliPay/return").anonymous()
.antMatchers("/api/aliPay/notify").anonymous()
// swagger start
.antMatchers("/swagger-ui.html").anonymous()
.antMatchers("/swagger-resources/**").anonymous()
.antMatchers("/webjars/**").anonymous()
.antMatchers("/*/api-docs").anonymous()
// swagger end
.antMatchers("/test/**").anonymous()
.antMatchers(HttpMethod.OPTIONS, "/**").anonymous()
// 所有请求都需要认证
@ -96,21 +102,21 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
public void configure(WebSecurity web) throws Exception {
// AuthenticationTokenFilter will ignore the below paths
web
.ignoring()
.antMatchers(
HttpMethod.POST,
authenticationPath
)
// allow anonymous resource requests
.and()
.ignoring()
.antMatchers(
HttpMethod.GET,
"/*.html",
"/**/*.html",
"/**/*.css",
"/**/*.js"
);
web.ignoring()
.antMatchers(
HttpMethod.POST,
authenticationPath
)
// allow anonymous resource requests
.and()
.ignoring()
.antMatchers(
HttpMethod.GET,
"/*.html",
"/**/*.html",
"/**/*.css",
"/**/*.js"
);
}
}

View File

@ -5,6 +5,8 @@ import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.sql.Timestamp;
import java.util.*;
/**
@ -32,6 +34,8 @@ public class JwtUser implements UserDetails {
private final boolean enabled;
private Timestamp createTime;
@JsonIgnore
private final Date lastPasswordResetDate;

View File

@ -64,6 +64,7 @@ public class JwtUserDetailsService implements UserDetailsService {
user.getEmail(),
mapToGrantedAuthorities(user.getRoles(),permissionRepository),
user.getEnabled(),
user.getCreateTime(),
user.getLastPasswordResetTime()
);
}

View File

@ -5,12 +5,10 @@ import io.jsonwebtoken.impl.DefaultClock;
import me.zhengjie.common.exception.BadRequestException;
import me.zhengjie.core.security.JwtUser;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AccountExpiredException;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import javax.servlet.http.HttpServletRequest;
import java.io.Serializable;
import java.util.Date;
@ -18,13 +16,9 @@ import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
import static org.springframework.http.HttpStatus.UNAUTHORIZED;
@Component
public class JwtTokenUtil implements Serializable {
static final String CLAIM_KEY_USERNAME = "sub";
static final String CLAIM_KEY_CREATED = "iat";
private static final long serialVersionUID = -3301605591108950415L;
private Clock clock = DefaultClock.INSTANCE;
@ -129,7 +123,7 @@ public class JwtTokenUtil implements Serializable {
String authToken = request.getHeader(tokenHeader);
if(StringUtils.isEmpty(authToken)||authToken.length()<7){
throw new AccountExpiredException("令牌已过期或无效");
throw new BadRequestException(HttpStatus.FORBIDDEN,"Token令牌无效");
}
final String token = authToken.substring(7);
@ -137,11 +131,7 @@ public class JwtTokenUtil implements Serializable {
try {
username = getUsernameFromToken(token);
} catch (ExpiredJwtException e){
throw new AccountExpiredException("令牌已过期或无效");
}
if(StringUtils.isEmpty(username)){
throw new AccountExpiredException("令牌已过期或无效");
throw new BadRequestException(HttpStatus.UNAUTHORIZED,"Token令牌已过期");
}
return username;

View File

@ -20,19 +20,12 @@ public class LogFilter extends Filter<ILoggingEvent>{
public FilterReply decide(ILoggingEvent event) {
String exception = "";
IThrowableProxy iThrowableProxy1 = event.getThrowableProxy();
if(iThrowableProxy1!=null){
exception = "<span class='excehtext'>"+iThrowableProxy1.getClassName()+" "+iThrowableProxy1.getMessage()+"</span></br>";
for(int i=0; i<iThrowableProxy1.getStackTraceElementProxyArray().length;i++){
exception += "<span class='excetext'>"+iThrowableProxy1.getStackTraceElementProxyArray()[i].toString()+"</span></br>";
}
}
LogMessage loggerMessage = new LogMessage(
event.getFormattedMessage() /* repair format message*/
, DateFormat.getDateTimeInstance().format(new Date(event.getTimeStamp())),
event.getFormattedMessage(),
DateFormat.getDateTimeInstance().format(new Date(event.getTimeStamp())),
event.getThreadName(),
event.getLoggerName(),
event.getLevel().levelStr,
exception
event.getLevel().levelStr
);
LoggerQueue.getInstance().push(loggerMessage);
return FilterReply.ACCEPT;

View File

@ -45,6 +45,10 @@ public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
try {
LogMessage log = LoggerQueue.getInstance().poll();
if(log!=null){
// 格式化异常堆栈信息
if("ERROR".equals(log.getLevel()) && "me.zhengjie.common.exception.handler.GlobalExceptionHandler".equals(log.getClassName())){
log.setBody("<pre>"+log.getBody()+"</pre>");
}
if(log.getClassName().equals("jdbc.resultsettable")){
log.setBody("<br><pre>"+log.getBody()+"</pre>");
}

View File

@ -16,5 +16,4 @@ public class LogMessage {
private String threadName;
private String className;
private String level;
private String exception;
}

View File

@ -38,6 +38,7 @@ public class Logging {
/**
*
*/
@Column(length = 1500)
private String params;
/**
@ -58,6 +59,7 @@ public class Logging {
/**
*
*/
@Column(length = 1500)
private String exceptionDetail;
/**

View File

@ -83,7 +83,9 @@ public class LoggingServiceImpl implements LoggingService {
username = user.getUsername();
}
logging.setMethod(methodName);
if (params.length() > 1000){
params = params.substring(0,999);
}
logging.setUsername(username);
logging.setParams(params + " }");
loggingRepository.save(logging);

View File

@ -1,9 +1,12 @@
package me.zhengjie.system.domain;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.CreationTimestamp;
import javax.persistence.*;
import javax.validation.constraints.NotBlank;
import java.sql.Timestamp;
/**
@ -12,6 +15,8 @@ import java.sql.Timestamp;
*/
@Data
@Entity
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "verification_code")
public class VerificationCode {
@ -22,7 +27,12 @@ public class VerificationCode {
private String code;
/**
* true false
* 使
*/
private String scenes;
/**
* true false ++
*/
private Boolean status = true;
@ -30,11 +40,13 @@ public class VerificationCode {
/**
* phone email
*/
@NotBlank
private String type;
/**
* phoneemail
*/
@NotBlank
private String value;
/**
@ -42,4 +54,11 @@ public class VerificationCode {
*/
@CreationTimestamp
private Timestamp createTime;
public VerificationCode(String code, String scenes, @NotBlank String type, @NotBlank String value) {
this.code = code;
this.scenes = scenes;
this.type = type;
this.value = value;
}
}

View File

@ -3,6 +3,7 @@ package me.zhengjie.system.repository;
import me.zhengjie.system.domain.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
@ -27,4 +28,31 @@ public interface UserRepository extends JpaRepository<User, Long>, JpaSpecificat
*/
@Query("from User u join fetch u.roles where u.email = :email")
User findByEmail(@Param("email") String email);
/**
*
* @param id
* @param pass
*/
@Modifying
@Query(value = "update user set password = ?2 where id = ?1",nativeQuery = true)
void updatePass(Long id, String pass);
/**
*
* @param id
* @param url
*/
@Modifying
@Query(value = "update user set avatar = ?2 where id = ?1",nativeQuery = true)
void updateAvatar(Long id, String url);
/**
*
* @param id
* @param email
*/
@Modifying
@Query(value = "update user set email = ?2 where id = ?1",nativeQuery = true)
void updateEmail(Long id, String email);
}

View File

@ -9,4 +9,12 @@ import org.springframework.data.jpa.repository.JpaRepository;
*/
public interface VerificationCodeRepository extends JpaRepository<VerificationCode, Long> {
/**
*
* @param scenes
* @param type
* @param value
* @return
*/
VerificationCode findByScenesAndTypeAndValueAndStatusIsTrue(String scenes,String type,String value);
}

View File

@ -2,17 +2,31 @@ package me.zhengjie.system.rest;
import me.zhengjie.common.aop.log.Log;
import me.zhengjie.common.exception.BadRequestException;
import me.zhengjie.common.utils.ElAdminConstant;
import me.zhengjie.common.utils.RequestHolder;
import me.zhengjie.core.security.JwtUser;
import me.zhengjie.core.utils.EncryptUtils;
import me.zhengjie.core.utils.JwtTokenUtil;
import me.zhengjie.system.domain.User;
import me.zhengjie.system.domain.VerificationCode;
import me.zhengjie.system.service.UserService;
import me.zhengjie.system.service.VerificationCodeService;
import me.zhengjie.system.service.dto.UserDTO;
import me.zhengjie.system.service.query.UserQueryService;
import me.zhengjie.tools.domain.Picture;
import me.zhengjie.tools.service.PictureService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.util.HashMap;
import java.util.Map;
/**
* @author jie
@ -28,6 +42,20 @@ public class UserController {
@Autowired
private UserQueryService userQueryService;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Autowired
@Qualifier("jwtUserDetailsService")
private UserDetailsService userDetailsService;
@Autowired
private PictureService pictureService;
@Autowired
private VerificationCodeService verificationCodeService;
private static final String ENTITY_NAME = "user";
@GetMapping(value = "/users/{id}")
@ -71,4 +99,66 @@ public class UserController {
userService.delete(id);
return new ResponseEntity(HttpStatus.OK);
}
/**
*
* @param pass
* @return
*/
@GetMapping(value = "/users/validPass/{pass}")
public ResponseEntity validPass(@PathVariable String pass){
JwtUser jwtUser = (JwtUser)userDetailsService.loadUserByUsername(jwtTokenUtil.getUserName(RequestHolder.getHttpServletRequest()));
Map map = new HashMap();
map.put("status",200);
if(!jwtUser.getPassword().equals(EncryptUtils.encryptPassword(pass))){
map.put("status",400);
}
return new ResponseEntity(map,HttpStatus.OK);
}
/**
*
* @param pass
* @return
*/
@GetMapping(value = "/users/updatePass/{pass}")
public ResponseEntity updatePass(@PathVariable String pass){
JwtUser jwtUser = (JwtUser)userDetailsService.loadUserByUsername(jwtTokenUtil.getUserName(RequestHolder.getHttpServletRequest()));
if(jwtUser.getPassword().equals(EncryptUtils.encryptPassword(pass))){
throw new BadRequestException("新密码不能与旧密码相同");
}
userService.updatePass(jwtUser,EncryptUtils.encryptPassword(pass));
return new ResponseEntity(HttpStatus.OK);
}
/**
*
* @param file
* @return
*/
@PostMapping(value = "/users/updateAvatar")
public ResponseEntity updateAvatar(@RequestParam MultipartFile file){
JwtUser jwtUser = (JwtUser)userDetailsService.loadUserByUsername(jwtTokenUtil.getUserName(RequestHolder.getHttpServletRequest()));
Picture picture = pictureService.upload(file,jwtUser.getUsername());
userService.updateAvatar(jwtUser,picture.getUrl());
return new ResponseEntity(HttpStatus.OK);
}
/**
*
* @param user
* @param user
* @return
*/
@PostMapping(value = "/users/updateEmail/{code}")
public ResponseEntity updateEmail(@PathVariable String code,@RequestBody User user){
JwtUser jwtUser = (JwtUser)userDetailsService.loadUserByUsername(jwtTokenUtil.getUserName(RequestHolder.getHttpServletRequest()));
if(!jwtUser.getPassword().equals(EncryptUtils.encryptPassword(user.getPassword()))){
throw new BadRequestException("密码错误");
}
VerificationCode verificationCode = new VerificationCode(code, ElAdminConstant.RESET_MAIL,"email",user.getEmail());
verificationCodeService.validated(verificationCode);
userService.updateEmail(jwtUser,user.getEmail());
return new ResponseEntity(HttpStatus.OK);
}
}

View File

@ -1,10 +1,18 @@
package me.zhengjie.system.rest;
import me.zhengjie.common.utils.ElAdminConstant;
import me.zhengjie.common.utils.RequestHolder;
import me.zhengjie.core.security.JwtUser;
import me.zhengjie.core.utils.JwtTokenUtil;
import me.zhengjie.system.domain.VerificationCode;
import me.zhengjie.system.service.VerificationCodeService;
import me.zhengjie.tools.domain.vo.EmailVo;
import me.zhengjie.tools.service.EmailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.web.bind.annotation.*;
/**
@ -18,10 +26,33 @@ public class VerificationCodeController {
@Autowired
private VerificationCodeService verificationCodeService;
@PostMapping(value = "/code/sendEmail")
public ResponseEntity sendEmail(@RequestBody VerificationCode code){
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Autowired
@Qualifier("jwtUserDetailsService")
private UserDetailsService userDetailsService;
@Autowired
private EmailService emailService;
@PostMapping(value = "/code/resetEmail")
public ResponseEntity resetEmail(@RequestBody VerificationCode code) throws Exception {
code.setScenes(ElAdminConstant.RESET_MAIL);
EmailVo emailVo = verificationCodeService.sendEmail(code);
emailService.send(emailVo,emailService.find());
return new ResponseEntity(HttpStatus.OK);
}
@PostMapping(value = "/code/email/resetPass")
public ResponseEntity resetPass() throws Exception {
JwtUser jwtUser = (JwtUser)userDetailsService.loadUserByUsername(jwtTokenUtil.getUserName(RequestHolder.getHttpServletRequest()));
VerificationCode code = new VerificationCode();
code.setType("email");
verificationCodeService.sendEmail(code);
code.setValue(jwtUser.getEmail());
code.setScenes(ElAdminConstant.RESET_MAIL);
EmailVo emailVo = verificationCodeService.sendEmail(code);
emailService.send(emailVo,emailService.find());
return new ResponseEntity(HttpStatus.OK);
}

View File

@ -1,5 +1,6 @@
package me.zhengjie.system.service;
import me.zhengjie.core.security.JwtUser;
import me.zhengjie.system.domain.User;
import me.zhengjie.system.service.dto.UserDTO;
import org.springframework.cache.annotation.CacheConfig;
@ -50,4 +51,25 @@ public interface UserService {
*/
@Cacheable(key = "'findByName'+#p0")
User findByName(String userName);
/**
*
* @param jwtUser
* @param encryptPassword
*/
void updatePass(JwtUser jwtUser, String encryptPassword);
/**
*
* @param jwtUser
* @param url
*/
void updateAvatar(JwtUser jwtUser, String url);
/**
*
* @param jwtUser
* @param email
*/
void updateEmail(JwtUser jwtUser, String email);
}

View File

@ -1,6 +1,7 @@
package me.zhengjie.system.service;
import me.zhengjie.system.domain.VerificationCode;
import me.zhengjie.tools.domain.vo.EmailVo;
/**
* @author jie
@ -12,7 +13,7 @@ public interface VerificationCodeService {
*
* @param code
*/
void sendEmail(VerificationCode code);
EmailVo sendEmail(VerificationCode code);
/**
*

View File

@ -1,6 +1,7 @@
package me.zhengjie.system.service.impl;
import cn.hutool.core.util.StrUtil;
import me.zhengjie.common.exception.BadRequestException;
import me.zhengjie.common.exception.EntityExistException;
import me.zhengjie.common.utils.ValidationUtil;
import me.zhengjie.system.domain.Menu;
@ -51,6 +52,11 @@ public class MenuServiceImpl implements MenuService {
if(menuRepository.findByName(resources.getName()) != null){
throw new EntityExistException(Menu.class,"name",resources.getName());
}
if(resources.getIFrame()){
if (!(resources.getPath().toLowerCase().startsWith("http://")||resources.getPath().toLowerCase().startsWith("https://"))) {
throw new BadRequestException("外链必须以http://或者https://开头");
}
}
return menuMapper.toDto(menuRepository.save(resources));
}
@ -59,13 +65,17 @@ public class MenuServiceImpl implements MenuService {
Optional<Menu> optionalPermission = menuRepository.findById(resources.getId());
ValidationUtil.isNull(optionalPermission,"Permission","id",resources.getId());
if(resources.getIFrame()){
if (!(resources.getPath().toLowerCase().startsWith("http://")||resources.getPath().toLowerCase().startsWith("https://"))) {
throw new BadRequestException("外链必须以http://或者https://开头");
}
}
Menu menu = optionalPermission.get();
Menu menu1 = menuRepository.findByName(resources.getName());
if(menu1 != null && !menu1.getId().equals(menu.getId())){
throw new EntityExistException(Menu.class,"name",resources.getName());
}
menu.setName(resources.getName());
menu.setComponent(resources.getComponent());
menu.setPath(resources.getPath());

View File

@ -4,6 +4,7 @@ import me.zhengjie.common.exception.BadRequestException;
import me.zhengjie.common.exception.EntityExistException;
import me.zhengjie.common.exception.EntityNotFoundException;
import me.zhengjie.common.utils.ValidationUtil;
import me.zhengjie.core.security.JwtUser;
import me.zhengjie.core.utils.EncryptUtils;
import me.zhengjie.core.utils.JwtTokenUtil;
import me.zhengjie.system.domain.User;
@ -130,4 +131,22 @@ public class UserServiceImpl implements UserService {
return user;
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updatePass(JwtUser jwtUser, String pass) {
userRepository.updatePass(jwtUser.getId(),pass);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updateAvatar(JwtUser jwtUser, String url) {
userRepository.updateAvatar(jwtUser.getId(),url);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updateEmail(JwtUser jwtUser, String email) {
userRepository.updateEmail(jwtUser.getId(),email);
}
}

View File

@ -1,23 +1,81 @@
package me.zhengjie.system.service.impl;
import cn.hutool.core.util.RandomUtil;
import me.zhengjie.common.exception.BadRequestException;
import me.zhengjie.common.utils.ElAdminConstant;
import me.zhengjie.system.domain.VerificationCode;
import me.zhengjie.system.repository.VerificationCodeRepository;
import me.zhengjie.system.service.VerificationCodeService;
import me.zhengjie.tools.domain.vo.EmailVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.Arrays;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* @author jie
* @date 2018-12-26
*/
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class VerificationCodeServiceImpl implements VerificationCodeService {
@Override
public void sendEmail(VerificationCode code) {
@Autowired
private VerificationCodeRepository verificationCodeRepository;
@Value("${code.expiration}")
private Integer expiration;
@Override
@Transactional(rollbackFor = Exception.class)
public EmailVo sendEmail(VerificationCode code) {
EmailVo emailVo = null;
String content = "";
VerificationCode verificationCode = verificationCodeRepository.findByScenesAndTypeAndValueAndStatusIsTrue(code.getScenes(),code.getType(),code.getValue());
// 如果不存在有效的验证码,就创建一个新的
if(verificationCode == null){
code.setCode(RandomUtil.randomNumbers (6));
content = ElAdminConstant.EMAIL_CODE + code.getCode() + "</p>";
emailVo = new EmailVo(Arrays.asList(code.getValue()),"eladmin后台管理系统",content);
timedDestruction(verificationCodeRepository.save(code));
// 存在就再次发送原来的验证码
} else {
content = ElAdminConstant.EMAIL_CODE + verificationCode.getCode() + "</p>";
emailVo = new EmailVo(Arrays.asList(verificationCode.getValue()),"eladmin后台管理系统",content);
}
return emailVo;
}
@Override
public void validated(VerificationCode code) {
VerificationCode verificationCode = verificationCodeRepository.findByScenesAndTypeAndValueAndStatusIsTrue(code.getScenes(),code.getType(),code.getValue());
if(verificationCode == null || !verificationCode.getCode().equals(code.getCode())){
throw new BadRequestException("无效验证码");
} else {
verificationCode.setStatus(false);
verificationCodeRepository.save(verificationCode);
}
}
/**
*
* @param verifyCode
*/
private void timedDestruction(VerificationCode verifyCode) {
//以下示例为程序调用结束继续运行
ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
try {
executorService.schedule(() -> {
verifyCode.setStatus(false);
verificationCodeRepository.save(verifyCode);
}, expiration * 60 * 1000L, TimeUnit.MILLISECONDS);
}catch (Exception e){
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,80 @@
package me.zhengjie.tools.domain;
import lombok.Data;
import javax.persistence.*;
import javax.validation.constraints.NotBlank;
import java.io.Serializable;
/**
*
* @author jie
* @date 2018-12-31
*/
@Data
@Entity
@Table(name = "alipay_config")
public class AlipayConfig implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
/**
* ID,APPIDAPPID
*/
@NotBlank
private String appID;
/**
* PKCS8RSA2
*/
@NotBlank
@Column(length = 2000)
private String privateKey;
/**
*
*/
@NotBlank
@Column(length = 2000)
private String publicKey;
/**
*
*/
private String signType="RSA2";
/**
*
*/
private String gatewayUrl = "https://openapi.alipaydev.com/gateway.do";
/**
*
*/
private String charset= "utf-8";
/**
*
*/
@NotBlank
private String notifyUrl;
/**
*
*/
@NotBlank
private String returnUrl;
/**
*
*/
private String format="JSON";
/**
*
*/
@NotBlank
private String sysServiceProviderId;
}

View File

@ -0,0 +1,61 @@
package me.zhengjie.tools.domain;
import lombok.Data;
import javax.persistence.*;
import javax.validation.constraints.NotBlank;
import java.io.Serializable;
/**
*
* @author jie
* @date 2018-12-31
*/
@Data
@Entity
@Table(name = "qiniu_config")
public class QiniuConfig implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
/**
* (Access/Secret Key)
*/
@NotBlank
private String accessKey;
/**
* (Access/Secret Key)
*/
@NotBlank
private String secretKey;
/**
* Bucket
*/
@NotBlank
private String bucket;
/**
* Zone
* Zone.zone0()
* Zone.zone1()
* Zone.zone2()
* Zone.zoneNa0()
* Zone.zoneAs0()
*/
@NotBlank
private String zone;
/**
*
*/
@NotBlank
private String host;
/**
* /
*/
private String type = "公开";
}

View File

@ -0,0 +1,54 @@
package me.zhengjie.tools.domain;
import lombok.Data;
import org.hibernate.annotations.UpdateTimestamp;
import javax.persistence.*;
import java.io.Serializable;
import java.sql.Timestamp;
/**
*
* @author jie
* @date 2018-12-31
*/
@Data
@Entity
@Table(name = "qiniu_content")
public class QiniuContent implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
/**
* qiniu.jpg
*/
@Column(name = "name",unique = false)
private String key;
/**
*
*/
private String bucket;
/**
*
*/
private String size;
/**
*
*/
private String url;
/**
* /
*/
private String type = "公开";
/**
*
*/
@UpdateTimestamp
private Timestamp updateTime;
}

View File

@ -1,6 +1,8 @@
package me.zhengjie.tools.domain.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
@ -13,6 +15,8 @@ import java.util.List;
* @date 2018/09/28 12:02:14
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class EmailVo {
/**

View File

@ -0,0 +1,65 @@
package me.zhengjie.tools.domain.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import java.sql.Date;
import java.sql.Timestamp;
/**
*
* @author jie
* @date 2018-12-31
*/
@Data
public class TradeVo {
/**
*
*/
@NotBlank
private String body;
/**
*
*/
@NotBlank
private String subject;
/**
*
*/
@ApiModelProperty(hidden = true)
private String outTradeNo;
/**
*
*/
@ApiModelProperty(hidden = true)
private String tradeNo;
/**
*
*/
@NotBlank
private String totalAmount;
/**
* ,
*/
@ApiModelProperty(hidden = true)
private String state;
/**
*
*/
@ApiModelProperty(hidden = true)
private Timestamp createTime;
/**
*
*/
@ApiModelProperty(hidden = true)
private Date cancelTime;
}

View File

@ -0,0 +1,11 @@
package me.zhengjie.tools.repository;
import me.zhengjie.tools.domain.AlipayConfig;
import org.springframework.data.jpa.repository.JpaRepository;
/**
* @author jie
* @date 2018-12-31
*/
public interface AlipayRepository extends JpaRepository<AlipayConfig,Long> {
}

View File

@ -0,0 +1,11 @@
package me.zhengjie.tools.repository;
import me.zhengjie.tools.domain.QiniuConfig;
import org.springframework.data.jpa.repository.JpaRepository;
/**
* @author jie
* @date 2018-12-31
*/
public interface QiNiuConfigRepository extends JpaRepository<QiniuConfig,Long> {
}

View File

@ -0,0 +1,19 @@
package me.zhengjie.tools.repository;
import me.zhengjie.tools.domain.QiniuContent;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
/**
* @author jie
* @date 2018-12-31
*/
public interface QiniuContentRepository extends JpaRepository<QiniuContent,Long>, JpaSpecificationExecutor {
/**
* key
* @param key
* @return
*/
QiniuContent findByKey(String key);
}

View File

@ -0,0 +1,125 @@
package me.zhengjie.tools.rest;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.common.aop.log.Log;
import me.zhengjie.tools.domain.AlipayConfig;
import me.zhengjie.tools.domain.vo.TradeVo;
import me.zhengjie.tools.service.AlipayService;
import me.zhengjie.tools.util.AliPayStatusEnum;
import me.zhengjie.tools.util.AlipayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
/**
* @author jie
* @date 2018-12-31
*/
@Slf4j
@RestController
@RequestMapping("/api")
public class AliPayController {
@Autowired
AlipayUtils alipayUtils;
@Autowired
private AlipayService alipayService;
@GetMapping(value = "/aliPay")
public ResponseEntity get(){
return new ResponseEntity(alipayService.find(),HttpStatus.OK);
}
@Log(description = "配置支付宝")
@PutMapping(value = "/aliPay")
public ResponseEntity payConfig(@Validated @RequestBody AlipayConfig alipayConfig){
alipayConfig.setId(1L);
alipayService.update(alipayConfig);
return new ResponseEntity(HttpStatus.OK);
}
@Log(description = "支付宝PC网页支付")
@ApiOperation(value = "PC网页支付")
@PostMapping(value = "/aliPay/toPayAsPC")
public ResponseEntity toPayAsPC(@Validated@RequestBody TradeVo trade) throws Exception{
log.warn("REST request to toPayAsPC Trade : {}" +trade);
AlipayConfig alipay = alipayService.find();
trade.setOutTradeNo(alipayUtils.getOrderCode());
String payUrl = alipayService.toPayAsPC(alipay,trade);
return ResponseEntity.ok(payUrl);
}
@Log(description = "支付宝手机网页支付")
@ApiOperation(value = "手机网页支付")
@PostMapping(value = "/aliPay/toPayAsWeb")
public ResponseEntity toPayAsWeb(@Validated @RequestBody TradeVo trade) throws Exception{
log.warn("REST request to toPayAsWeb Trade : {}" +trade);
AlipayConfig alipay = alipayService.find();
trade.setOutTradeNo(alipayUtils.getOrderCode());
String payUrl = alipayService.toPayAsWeb(alipay,trade);
return ResponseEntity.ok(payUrl);
}
@ApiIgnore
@GetMapping("/aliPay/return")
@ApiOperation(value = "支付之后跳转的链接")
public ResponseEntity returnPage(HttpServletRequest request, HttpServletResponse response) throws Exception {
AlipayConfig alipay = alipayService.find();
response.setContentType("text/html;charset=" + alipay.getCharset());
//内容验签,防止黑客篡改参数
if(alipayUtils.rsaCheck(request,alipay)){
//商户订单号
String outTradeNo = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"),"UTF-8");
//支付宝交易号
String tradeNo = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"),"UTF-8");
System.out.println("商户订单号"+outTradeNo+" "+"第三方交易号"+tradeNo);
/**
* OK
*/
return new ResponseEntity("payment successful",HttpStatus.OK);
}else{
/**
*
*/
return new ResponseEntity(HttpStatus.BAD_REQUEST);
}
}
@ApiIgnore
@RequestMapping("/aliPay/notify")
@ApiOperation(value = "支付异步通知(要公网访问)接收异步通知检查通知内容app_id、out_trade_no、total_amount是否与请求中的一致根据trade_status进行后续业务处理")
public ResponseEntity notify(HttpServletRequest request) throws Exception{
AlipayConfig alipay = alipayService.find();
Map<String, String[]> parameterMap = request.getParameterMap();
StringBuilder notifyBuild = new StringBuilder("/****************************** pay notify ******************************/\n");
parameterMap.forEach((key, value) -> notifyBuild.append(key + "=" + value[0] + "\n") );
//内容验签,防止黑客篡改参数
if (alipayUtils.rsaCheck(request,alipay)) {
//交易状态
String tradeStatus = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"),"UTF-8");
// 商户订单号
String outTradeNo = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"),"UTF-8");
//支付宝交易号
String tradeNo = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"),"UTF-8");
//付款金额
String totalAmount = new String(request.getParameter("total_amount").getBytes("ISO-8859-1"),"UTF-8");
//验证
if(tradeStatus.equals(AliPayStatusEnum.SUCCESS.getValue())||tradeStatus.equals(AliPayStatusEnum.FINISHED.getValue())){
/**
*
*/
}
return new ResponseEntity(HttpStatus.OK);
}
return new ResponseEntity(HttpStatus.BAD_REQUEST);
}
}

View File

@ -25,13 +25,11 @@ public class EmailController {
@Autowired
private EmailService emailService;
@PreAuthorize("hasAnyRole('ADMIN')")
@GetMapping(value = "/email")
public ResponseEntity get(){
return new ResponseEntity(emailService.find(),HttpStatus.OK);
}
@PreAuthorize("hasAnyRole('ADMIN')")
@Log(description = "配置邮件")
@PutMapping(value = "/email")
public ResponseEntity emailConfig(@Validated @RequestBody EmailConfig emailConfig){
@ -39,7 +37,6 @@ public class EmailController {
return new ResponseEntity(HttpStatus.OK);
}
@PreAuthorize("hasAnyRole('ADMIN')")
@Log(description = "发送邮件")
@PostMapping(value = "/email")
public ResponseEntity send(@Validated @RequestBody EmailVo emailVo) throws Exception {

View File

@ -0,0 +1,108 @@
package me.zhengjie.tools.rest;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.common.aop.log.Log;
import me.zhengjie.tools.domain.QiniuConfig;
import me.zhengjie.tools.domain.QiniuContent;
import me.zhengjie.tools.service.QiNiuService;
import me.zhengjie.tools.service.query.QiNiuQueryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;
/**
*
* @author
* @date 2018/09/28 6:55:53
*/
@Slf4j
@RestController
@RequestMapping("api")
public class QiniuController {
@Autowired
private QiNiuService qiNiuService;
@Autowired
private QiNiuQueryService qiNiuQueryService;
@GetMapping(value = "/qiNiuConfig")
public ResponseEntity get(){
return new ResponseEntity(qiNiuService.find(), HttpStatus.OK);
}
@Log(description = "配置七牛云存储")
@PutMapping(value = "/qiNiuConfig")
public ResponseEntity emailConfig(@Validated @RequestBody QiniuConfig qiniuConfig){
qiNiuService.update(qiniuConfig);
return new ResponseEntity(HttpStatus.OK);
}
@Log(description = "查询文件")
@GetMapping(value = "/qiNiuContent")
public ResponseEntity getRoles(QiniuContent resources, Pageable pageable){
return new ResponseEntity(qiNiuQueryService.queryAll(resources,pageable),HttpStatus.OK);
}
/**
*
* @param file
* @return
*/
@Log(description ="上传文件")
@PostMapping(value = "/qiNiuContent")
public ResponseEntity upload(@RequestParam MultipartFile file){
QiniuContent qiniuContent = qiNiuService.upload(file,qiNiuService.find());
Map map = new HashMap();
map.put("errno",0);
map.put("id",qiniuContent.getId());
map.put("data",new String[]{qiniuContent.getUrl()});
return new ResponseEntity(map,HttpStatus.OK);
}
/**
*
* @return
*/
@Log(description ="同步七牛云数据")
@PostMapping(value = "/qiNiuContent/synchronize")
public ResponseEntity synchronize(){
log.warn("REST request to synchronize qiNiu : {}");
qiNiuService.synchronize(qiNiuService.find());
return new ResponseEntity(HttpStatus.OK);
}
/**
*
* @param id
* @return
* @throws Exception
*/
@Log(description ="下载文件")
@GetMapping(value = "/qiNiuContent/download/{id}")
public ResponseEntity download(@PathVariable Long id){
return new ResponseEntity(qiNiuService.download(qiNiuService.findByContentId(id),qiNiuService.find()),HttpStatus.OK);
}
/**
*
* @param id
* @return
* @throws Exception
*/
@Log(description ="删除文件")
@DeleteMapping(value = "/qiNiuContent/{id}")
public ResponseEntity delete(@PathVariable Long id){
qiNiuService.delete(qiNiuService.findByContentId(id),qiNiuService.find());
return new ResponseEntity(HttpStatus.OK);
}
}

View File

@ -0,0 +1,48 @@
package me.zhengjie.tools.service;
import me.zhengjie.tools.domain.AlipayConfig;
import me.zhengjie.tools.domain.vo.TradeVo;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
/**
* @author jie
* @date 2018-12-31
*/
@CacheConfig(cacheNames = "alipay")
public interface AlipayService {
/**
* PC
* @param alipay
* @param trade
* @return
* @throws Exception
*/
String toPayAsPC(AlipayConfig alipay, TradeVo trade) throws Exception;
/**
*
* @param alipay
* @param trade
* @return
* @throws Exception
*/
String toPayAsWeb(AlipayConfig alipay, TradeVo trade) throws Exception;
/**
*
* @return
*/
@Cacheable(key = "'1'")
AlipayConfig find();
/**
*
* @param alipayConfig
* @return
*/
@CachePut(key = "'1'")
AlipayConfig update(AlipayConfig alipayConfig);
}

View File

@ -0,0 +1,73 @@
package me.zhengjie.tools.service;
import me.zhengjie.tools.domain.QiniuConfig;
import me.zhengjie.tools.domain.QiniuContent;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.multipart.MultipartFile;
import java.io.UnsupportedEncodingException;
/**
* @author jie
* @date 2018-12-31
*/
@CacheConfig(cacheNames = "qiNiu")
public interface QiNiuService {
/**
*
* @return
*/
@Cacheable(key = "'1'")
QiniuConfig find();
/**
*
* @param qiniuConfig
* @return
*/
@CachePut(key = "'1'")
QiniuConfig update(QiniuConfig qiniuConfig);
/**
*
* @param file
* @param qiniuConfig
*/
@CacheEvict(allEntries = true)
QiniuContent upload(MultipartFile file, QiniuConfig qiniuConfig);
/**
*
* @param id
* @return
*/
@Cacheable(key = "'content:'+#p0")
QiniuContent findByContentId(Long id);
/**
*
* @param content
* @param config
* @return
*/
String download(QiniuContent content, QiniuConfig config);
/**
*
* @param content
* @param config
* @return
*/
@CacheEvict(allEntries = true)
void delete(QiniuContent content, QiniuConfig config);
/**
*
* @param config
*/
@CacheEvict(allEntries = true)
void synchronize(QiniuConfig config);
}

View File

@ -0,0 +1,135 @@
package me.zhengjie.tools.service.impl;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import me.zhengjie.common.exception.BadRequestException;
import me.zhengjie.tools.domain.AlipayConfig;
import me.zhengjie.tools.domain.vo.TradeVo;
import me.zhengjie.tools.repository.AlipayRepository;
import me.zhengjie.tools.service.AlipayService;
import me.zhengjie.tools.util.AlipayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.Optional;
/**
* @author jie
* @date 2018-12-31
*/
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class AlipayServiceImpl implements AlipayService {
@Autowired
AlipayUtils alipayUtils;
@Autowired
private AlipayRepository alipayRepository;
@Override
public String toPayAsPC(AlipayConfig alipay, TradeVo trade) throws Exception {
if(alipay.getId() == null){
throw new BadRequestException("请先添加相应配置,再操作");
}
AlipayClient alipayClient = new DefaultAlipayClient(alipay.getGatewayUrl(), alipay.getAppID(), alipay.getPrivateKey(), alipay.getFormat(), alipay.getCharset(), alipay.getPublicKey(), alipay.getSignType());
double money = Double.parseDouble(trade.getTotalAmount());
if(money <= 0 || money>=5000){
throw new BadRequestException("测试金额过大");
}
/**
* APIrequest()
*/
AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
/**
*
*/
request.setReturnUrl(alipay.getReturnUrl());
request.setNotifyUrl(alipay.getNotifyUrl());
/**
*
*/
request.setBizContent("{" +
" \"out_trade_no\":\""+trade.getOutTradeNo()+"\"," +
" \"product_code\":\"FAST_INSTANT_TRADE_PAY\"," +
" \"total_amount\":"+trade.getTotalAmount()+"," +
" \"subject\":\""+trade.getSubject()+"\"," +
" \"body\":\""+trade.getBody()+"\"," +
" \"extend_params\":{" +
" \"sys_service_provider_id\":\""+alipay.getSysServiceProviderId()+"\"" +
" }"+
" }");//填充业务参数
/**
* SDK
* GETurl
*/
return alipayClient.pageExecute(request, "GET").getBody();
}
@Override
public String toPayAsWeb(AlipayConfig alipay, TradeVo trade) throws Exception {
if(alipay.getId() == null){
throw new BadRequestException("请先添加相应配置,再操作");
}
AlipayClient alipayClient = new DefaultAlipayClient(alipay.getGatewayUrl(), alipay.getAppID(), alipay.getPrivateKey(), alipay.getFormat(), alipay.getCharset(), alipay.getPublicKey(), alipay.getSignType());
double money = Double.parseDouble(trade.getTotalAmount());
if(money <= 0 || money >= 5000){
throw new BadRequestException("测试金额过大");
}
/**
* APIrequest()
*/
AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
/**
*
*/
request.setReturnUrl(alipay.getReturnUrl());
request.setNotifyUrl(alipay.getNotifyUrl());
/**
*
*/
request.setBizContent("{" +
" \"out_trade_no\":\""+trade.getOutTradeNo()+"\"," +
" \"product_code\":\"FAST_INSTANT_TRADE_PAY\"," +
" \"total_amount\":"+trade.getTotalAmount()+"," +
" \"subject\":\""+trade.getSubject()+"\"," +
" \"body\":\""+trade.getBody()+"\"," +
" \"extend_params\":{" +
" \"sys_service_provider_id\":\""+alipay.getSysServiceProviderId()+"\"" +
" }"+
" }");//填充业务参数
/**
* SDK
* GETurl
*/
return alipayClient.pageExecute(request, "GET").getBody();
}
@Override
public AlipayConfig find() {
Optional<AlipayConfig> alipayConfig = alipayRepository.findById(1L);
if (alipayConfig.isPresent()){
return alipayConfig.get();
} else {
return new AlipayConfig();
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public AlipayConfig update(AlipayConfig alipayConfig) {
return alipayRepository.saveAndFlush(alipayConfig);
}
}

View File

@ -3,6 +3,7 @@ package me.zhengjie.tools.service.impl;
import cn.hutool.extra.mail.MailAccount;
import cn.hutool.extra.mail.MailUtil;
import me.zhengjie.common.exception.BadRequestException;
import me.zhengjie.common.utils.ElAdminConstant;
import me.zhengjie.core.utils.EncryptUtils;
import me.zhengjie.tools.domain.EmailConfig;
import me.zhengjie.tools.domain.vo.EmailVo;
@ -72,7 +73,7 @@ public class EmailServiceImpl implements EmailService {
account.setFrom(emailConfig.getUser()+"<"+emailConfig.getFromUser()+">");
//ssl方式发送
account.setStartttlsEnable(true);
String content = emailVo.getContent()+ "<p style='text-align: right;'>----- 邮件来自<span style='color: rgb(194, 79, 74);'>&nbsp;<a href='http://auauz.net' target='_blank'>eladmin</a></span>&nbsp;后台管理系统</p>";
String content = emailVo.getContent()+ ElAdminConstant.EMAIL_CONTENT;
/**
*
*/

View File

@ -70,7 +70,7 @@ public class PictureServiceImpl implements PictureService {
picture = JSON.parseObject(jsonObject.get("data").toString(), Picture.class);
picture.setSize(FileUtil.getSize(Integer.valueOf(picture.getSize())));
picture.setUsername(username);
picture.setFilename(FileUtil.getFileNameNoEx(multipartFile.getOriginalFilename()));
picture.setFilename(FileUtil.getFileNameNoEx(multipartFile.getOriginalFilename())+FileUtil.getExtensionName(multipartFile.getOriginalFilename()));
pictureRepository.save(picture);
//删除临时文件
FileUtil.deleteFile(file);

View File

@ -0,0 +1,179 @@
package me.zhengjie.tools.service.impl;
import com.google.gson.Gson;
import com.qiniu.common.QiniuException;
import com.qiniu.http.Response;
import com.qiniu.storage.BucketManager;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.DefaultPutRet;
import com.qiniu.storage.model.FileInfo;
import com.qiniu.util.Auth;
import me.zhengjie.common.exception.BadRequestException;
import me.zhengjie.common.utils.FileUtil;
import me.zhengjie.common.utils.ValidationUtil;
import me.zhengjie.tools.domain.QiniuConfig;
import me.zhengjie.tools.domain.QiniuContent;
import me.zhengjie.tools.repository.QiNiuConfigRepository;
import me.zhengjie.tools.repository.QiniuContentRepository;
import me.zhengjie.tools.service.QiNiuService;
import me.zhengjie.tools.util.QiNiuUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import java.io.UnsupportedEncodingException;
import java.util.Optional;
/**
* @author jie
* @date 2018-12-31
*/
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class QiNiuServiceImpl implements QiNiuService {
@Autowired
private QiNiuConfigRepository qiNiuConfigRepository;
@Autowired
private QiniuContentRepository qiniuContentRepository;
@Value("${qiniu.max-size}")
private Long maxSize;
private final String TYPE = "公开";
@Override
public QiniuConfig find() {
Optional<QiniuConfig> qiniuConfig = qiNiuConfigRepository.findById(1L);
if(qiniuConfig.isPresent()){
return qiniuConfig.get();
} else {
return new QiniuConfig();
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public QiniuConfig update(QiniuConfig qiniuConfig) {
if (!(qiniuConfig.getHost().toLowerCase().startsWith("http://")||qiniuConfig.getHost().toLowerCase().startsWith("https://"))) {
throw new BadRequestException("外链域名必须以http://或者https://开头");
}
qiniuConfig.setId(1L);
return qiNiuConfigRepository.save(qiniuConfig);
}
@Override
@Transactional(rollbackFor = Exception.class)
public QiniuContent upload(MultipartFile file, QiniuConfig qiniuConfig) {
Long size = maxSize * 1024 * 1024;
if(file.getSize() > size){
throw new BadRequestException("文件超出规定大小");
}
if(qiniuConfig.getId() == null){
throw new BadRequestException("请先添加相应配置,再操作");
}
/**
* Zone
*/
Configuration cfg = QiNiuUtil.getConfiguration(qiniuConfig.getZone());
UploadManager uploadManager = new UploadManager(cfg);
Auth auth = Auth.create(qiniuConfig.getAccessKey(), qiniuConfig.getSecretKey());
String upToken = auth.uploadToken(qiniuConfig.getBucket());
try {
Response response = uploadManager.put(file.getBytes(), QiNiuUtil.getKey(file.getOriginalFilename()), upToken);
//解析上传成功的结果
DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
//存入数据库
QiniuContent qiniuContent = new QiniuContent();
qiniuContent.setBucket(qiniuConfig.getBucket());
qiniuContent.setType(qiniuConfig.getType());
qiniuContent.setKey(putRet.key);
qiniuContent.setUrl(qiniuConfig.getHost()+"/"+putRet.key);
qiniuContent.setSize(FileUtil.getSize(Integer.parseInt(file.getSize()+"")));
return qiniuContentRepository.save(qiniuContent);
} catch (Exception e) {
throw new BadRequestException(e.getMessage());
}
}
@Override
public QiniuContent findByContentId(Long id) {
Optional<QiniuContent> qiniuContent = qiniuContentRepository.findById(id);
ValidationUtil.isNull(qiniuContent,"QiniuContent", "id",id);
return qiniuContent.get();
}
@Override
public String download(QiniuContent content,QiniuConfig config){
String finalUrl = null;
if(TYPE.equals(content.getType())){
finalUrl = content.getUrl();
} else {
Auth auth = Auth.create(config.getAccessKey(), config.getSecretKey());
/**
* 1
*/
long expireInSeconds = 3600;
finalUrl = auth.privateDownloadUrl(content.getUrl(), expireInSeconds);
}
return finalUrl;
}
@Override
@Transactional(rollbackFor = Exception.class)
public void delete(QiniuContent content, QiniuConfig config) {
//构造一个带指定Zone对象的配置类
Configuration cfg = QiNiuUtil.getConfiguration(config.getZone());
Auth auth = Auth.create(config.getAccessKey(), config.getSecretKey());
BucketManager bucketManager = new BucketManager(auth, cfg);
try {
bucketManager.delete(content.getBucket(), content.getKey());
qiniuContentRepository.delete(content);
} catch (QiniuException ex) {
System.err.println(ex.code());
System.err.println(ex.response.toString());
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public void synchronize(QiniuConfig config) {
if(config.getId() == null){
throw new BadRequestException("请先添加相应配置,再操作");
}
//构造一个带指定Zone对象的配置类
Configuration cfg = QiNiuUtil.getConfiguration(config.getZone());
Auth auth = Auth.create(config.getAccessKey(), config.getSecretKey());
BucketManager bucketManager = new BucketManager(auth, cfg);
//文件名前缀
String prefix = "";
//每次迭代的长度限制最大1000推荐值 1000
int limit = 1000;
//指定目录分隔符,列出所有公共前缀(模拟列出目录效果)。缺省值为空字符串
String delimiter = "";
//列举空间文件列表
BucketManager.FileListIterator fileListIterator = bucketManager.createFileListIterator(config.getBucket(), prefix, limit, delimiter);
while (fileListIterator.hasNext()) {
//处理获取的file list结果
QiniuContent qiniuContent = null;
FileInfo[] items = fileListIterator.next();
for (FileInfo item : items) {
if(qiniuContentRepository.findByKey(item.key) == null){
qiniuContent = new QiniuContent();
qiniuContent.setSize(FileUtil.getSize(Integer.parseInt(item.fsize+"")));
qiniuContent.setKey(item.key);
qiniuContent.setType(config.getType());
qiniuContent.setBucket(config.getBucket());
qiniuContent.setUrl(config.getHost()+"/"+item.key);
qiniuContentRepository.save(qiniuContent);
}
}
}
}
}

View File

@ -0,0 +1,66 @@
package me.zhengjie.tools.service.query;
import me.zhengjie.common.utils.PageUtil;
import me.zhengjie.tools.domain.QiniuContent;
import me.zhengjie.tools.repository.QiniuContentRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;
/**
* @author jie
* @date 2018-12-31
*/
@Service
@CacheConfig(cacheNames = "qiNiu")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class QiNiuQueryService {
@Autowired
private QiniuContentRepository qiniuContentRepository;
/**
*
*/
@Cacheable(keyGenerator = "keyGenerator")
public Object queryAll(QiniuContent qiniuContent, Pageable pageable){
return PageUtil.toPage(qiniuContentRepository.findAll(new Spec(qiniuContent),pageable));
}
class Spec implements Specification<QiniuContent> {
private QiniuContent qiniuContent;
public Spec(QiniuContent qiniuContent){
this.qiniuContent = qiniuContent;
}
@Override
public Predicate toPredicate(Root<QiniuContent> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) {
List<Predicate> list = new ArrayList<Predicate>();
if(!ObjectUtils.isEmpty(qiniuContent.getKey())){
/**
*
*/
list.add(cb.like(root.get("key").as(String.class),"%"+qiniuContent.getKey()+"%"));
}
Predicate[] p = new Predicate[list.size()];
return cb.and(list.toArray(p));
}
}
}

View File

@ -0,0 +1,41 @@
package me.zhengjie.tools.util;
/**
*
* @author zhengjie
* @date 2018/08/01 16:45:43
*/
public enum AliPayStatusEnum {
/**
*
*/
FINISHED("交易成功", "TRADE_FINISHED"),
/**
*
*/
SUCCESS("支付成功", "TRADE_SUCCESS"),
/**
*
*/
BUYER_PAY("交易创建", "WAIT_BUYER_PAY"),
/**
*
*/
CLOSED("交易关闭", "TRADE_CLOSED");
private String name;
private String value;
AliPayStatusEnum(String name, String value) {
this.name = name;
this.value = value;
}
public String getValue() {
return value;
}
}

View File

@ -0,0 +1,79 @@
package me.zhengjie.tools.util;
import cn.hutool.core.util.StrUtil;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import me.zhengjie.tools.domain.AlipayConfig;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
*
* @author zhengjie
* @date 2018/09/30 14:04:35
*/
@Component
public class AlipayUtils {
/**
*
* @return
*/
public String getOrderCode() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
int a = (int)(Math.random() * 9000.0D) + 1000;
System.out.println(a);
Date date = new Date();
String str = sdf.format(date);
String[] split = str.split("-");
String s = split[0] + split[1] + split[2];
String[] split1 = s.split(" ");
String s1 = split1[0] + split1[1];
String[] split2 = s1.split(":");
String s2 = split2[0] + split2[1] + split2[2] + a;
return s2;
}
/**
*
* @param request
* @return
*/
public boolean rsaCheck(HttpServletRequest request, AlipayConfig alipay){
/**
* POST
*/
Map<String,String> params = new HashMap<>(1);
Map requestParams = request.getParameterMap();
for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
String name = (String) iter.next();
String[] values = (String[]) requestParams.get(name);
String valueStr = "";
for (int i = 0; i < values.length; i++) {
valueStr = (i == values.length - 1) ? valueStr + values[i]
: valueStr + values[i] + ",";
}
params.put(name, valueStr);
}
try {
boolean verifyResult = AlipaySignature.rsaCheckV1(params,
alipay.getPublicKey(),
alipay.getCharset(),
alipay.getSignType());
return verifyResult;
} catch (AlipayApiException e) {
return false;
}
}
public boolean isEmpty(String str){
return StrUtil.isEmpty(str);
}
}

View File

@ -0,0 +1,60 @@
package me.zhengjie.tools.util;
import com.qiniu.common.Zone;
import com.qiniu.storage.Configuration;
import me.zhengjie.common.utils.FileUtil;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
*
* @author jie
* @date 2018-12-31
*/
public class QiNiuUtil {
public static final String HUAD = "华东";
public static final String HUAB = "华北";
public static final String HUAN = "华南";
public static final String BEIM = "北美";
/**
*
* @param zone
* @return
*/
public static Configuration getConfiguration(String zone){
if(HUAD.equals(zone)){
return new Configuration(Zone.zone0());
} else if(HUAB.equals(zone)){
return new Configuration(Zone.zone1());
} else if(HUAN.equals(zone)){
return new Configuration(Zone.zone2());
} else if (BEIM.equals(zone)){
return new Configuration(Zone.zoneNa0());
// 否则就是东南亚
} else {
return new Configuration(Zone.zoneAs0());
}
}
/**
* keyhash
* @param file
* @return
*/
public static String getKey(String file){
StringBuffer key = new StringBuffer(FileUtil.getFileNameNoEx(file));
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
Date date = new Date();
key.append(sdf.format(date));
key.append(".");
key.append(FileUtil.getExtensionName(file));
return key.toString();
}
}

View File

@ -80,11 +80,20 @@ spring:
jwt:
header: Authorization
secret: mySecret
# token 过期时间 1个小时
expiration: 3600000
# token 过期时间 2个小时
expiration: 7200000
# expiration: 60000
auth:
# 授权路径
path: /login
# 获取用户信息
account: /info
#七牛云
qiniu:
# 文件大小 /M
max-size: 5
#验证码有效时间/分钟
code:
expiration: 5