⚡ feat(修改): 删除不用的引用
This commit is contained in:
parent
116d1e6e18
commit
88a2a78ef6
|
@ -10,13 +10,11 @@ import java.util.Collections;
|
|||
|
||||
public class NewCodeGet {
|
||||
// 数据连接
|
||||
// public static final String sqlHost = "jdbc:mysql://106.15.251.123:3305/bunny_docs?serverTimezone=GMT%2B8&useSSL=false&characterEncoding=utf-8&allowPublicKeyRetrieval=true";
|
||||
public static final String sqlHost = "jdbc:mysql://106.15.251.123:3305/myDS?serverTimezone=GMT%2B8&useSSL=false&characterEncoding=utf-8&allowPublicKeyRetrieval=true";
|
||||
public static final String sqlHost = "jdbc:mysql://192.168.3.98:3305/myDS?serverTimezone=GMT%2B8&useSSL=false&characterEncoding=utf-8&allowPublicKeyRetrieval=true";
|
||||
// 作者名称
|
||||
public static final String author = "Bunny";
|
||||
// 公共路径
|
||||
public static final String outputDir = "D:\\MyFolder\\Quartz-Demo\\service";
|
||||
// public static final String outputDir = "D:\\Project\\web\\PC\\demo\\Quartz-Demo\\service";
|
||||
// 实体类名称
|
||||
public static final String entity = "Bunny";
|
||||
|
||||
|
|
|
@ -1,149 +0,0 @@
|
|||
package cn.bunny.common.service.utils;
|
||||
|
||||
|
||||
import cn.bunny.common.service.properties.SnowflakeProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class SnowflakeIdGenerator {
|
||||
// 数据中心id
|
||||
private final long datacenterId;
|
||||
// 数据中心id位数
|
||||
private final long datacenterBits;
|
||||
// 机器id
|
||||
private final long workerId;
|
||||
// 机器id位数
|
||||
private final long workerBits;
|
||||
// 序列id所占位数
|
||||
private final long sequenceBits;
|
||||
// 时间戳起始点(毫秒)
|
||||
private final long twepoch;
|
||||
|
||||
// 数据中心最大id
|
||||
private final long maxDatacenterId;
|
||||
// 机器最大id
|
||||
private final long maxWorkerId;
|
||||
// 最大序列号
|
||||
private final long maxSequence;
|
||||
|
||||
// 机器id左移位数
|
||||
private final long workerIdShift;
|
||||
// 数据中心id左移位数
|
||||
private final long datacenterIdShift;
|
||||
// 毫秒数左移位数
|
||||
private final long timestampLeftShift;
|
||||
|
||||
// 单次批量生成id的最大数量
|
||||
private final int maxBatchCount;
|
||||
|
||||
// 序列号
|
||||
private long sequence = 0L;
|
||||
// 上一次时间戳
|
||||
private long lastTimestamp = -1L;
|
||||
|
||||
public SnowflakeIdGenerator(SnowflakeProperties properties) {
|
||||
// 数据中心id
|
||||
this.datacenterId = properties.getDatacenterId();
|
||||
// 数据中心id位数
|
||||
this.datacenterBits = properties.getDatacenterBits();
|
||||
// 机器id
|
||||
this.workerId = properties.getWorkerId();
|
||||
// 机器id位数
|
||||
this.workerBits = properties.getWorkerBits();
|
||||
// 序列id所占位数
|
||||
this.sequenceBits = properties.getSequenceBits();
|
||||
// 时间戳起始点(毫秒)
|
||||
this.twepoch = properties.getTwepoch();
|
||||
// 数据中心最大id
|
||||
this.maxDatacenterId = -1L ^ (-1L << properties.getDatacenterBits());
|
||||
// 机器最大id
|
||||
this.maxWorkerId = -1L ^ (-1L << properties.getWorkerBits());
|
||||
// 最大序列号
|
||||
this.maxSequence = -1L ^ (-1L << properties.getSequenceBits());
|
||||
|
||||
this.workerIdShift = properties.getSequenceBits();
|
||||
// 数据中心id左移位数
|
||||
this.datacenterIdShift = properties.getSequenceBits() + properties.getWorkerBits();
|
||||
// 毫秒数左移位数
|
||||
this.timestampLeftShift = properties.getSequenceBits() + properties.getWorkerBits() + properties.getSequenceBits();
|
||||
// 单次批量生成id的最大数量
|
||||
this.maxBatchCount = properties.getMaxBatchCount();
|
||||
|
||||
// 校验datacenterId和workerId是否超出最大值
|
||||
if (datacenterId > maxDatacenterId || datacenterId < 0) {
|
||||
throw new IllegalArgumentException(String.format("数据中心Id不能大于%d或小于0", maxDatacenterId));
|
||||
}
|
||||
if (workerId > maxWorkerId || workerId < 0) {
|
||||
throw new IllegalArgumentException(String.format("机器Id不能大于%d或小于0", maxWorkerId));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* id生成方法(单个)
|
||||
*/
|
||||
public synchronized long nextId() {
|
||||
// 获取当前时间的毫秒数
|
||||
long timestamp = currentTime();
|
||||
|
||||
// 判断时钟是否回拨
|
||||
if (timestamp < lastTimestamp) {
|
||||
throw new RuntimeException(String.format("时钟回拨,回拨毫秒数:%d", lastTimestamp - timestamp));
|
||||
}
|
||||
|
||||
// 设置序列号
|
||||
if (lastTimestamp == timestamp) {
|
||||
// 设置序列号递增,如果当前毫秒内序列号已经达到最大值,则直到下一毫秒在重新从0开始计算序列号
|
||||
sequence = (sequence + 1) & maxSequence;
|
||||
if (sequence == 0) {
|
||||
timestamp = tilNextMillis(lastTimestamp);
|
||||
}
|
||||
} else {
|
||||
sequence = 0L;
|
||||
}
|
||||
lastTimestamp = timestamp;
|
||||
|
||||
// 计算id
|
||||
return ((timestamp - twepoch) << timestampLeftShift) |
|
||||
(datacenterId << datacenterIdShift) |
|
||||
(workerId << workerIdShift) |
|
||||
sequence;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* id生成方法(批量)
|
||||
*/
|
||||
public synchronized List<Long> nextIds(int count) {
|
||||
if (count > maxBatchCount || count < 0) {
|
||||
throw new IllegalArgumentException(String.format("批量生成id的数量不能大于%d或小于0", maxBatchCount));
|
||||
}
|
||||
List<Long> ids = new ArrayList<>(count);
|
||||
for (int i = 0; i < count; i++) {
|
||||
ids.add(nextId());
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* 循环等待直至获取到新的毫秒时间戳
|
||||
* 确保生成的时间戳总是向前移动的,即使在相同的毫秒内请求多个ID时也能保持唯一性。
|
||||
*/
|
||||
private long tilNextMillis(long lastTimestamp) {
|
||||
long timestamp = currentTime();
|
||||
// 循环等待直至获取到新的毫秒时间戳
|
||||
while (timestamp <= lastTimestamp) {
|
||||
timestamp = currentTime();
|
||||
}
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前时间的毫秒数
|
||||
*/
|
||||
private long currentTime() {
|
||||
return System.currentTimeMillis();
|
||||
}
|
||||
}
|
10
dao/pom.xml
10
dao/pom.xml
|
@ -55,16 +55,6 @@
|
|||
<groupId>com.github.xiaoymin</groupId>
|
||||
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<!-- spring-security -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
<!-- spring-security-test -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-test</artifactId>
|
||||
</dependency>
|
||||
<!-- spring-web -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
|
|
|
@ -5,6 +5,9 @@ import lombok.Builder;
|
|||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 添加任务
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
|
|
|
@ -5,6 +5,9 @@ import lombok.Builder;
|
|||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* * 移出、暂停、恢复任务
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>cn.bunny</groupId>
|
||||
<artifactId>module</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>module-mail</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>module-mail</name>
|
||||
<url>https://maven.apache.org</url>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-mail</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -1,23 +0,0 @@
|
|||
Configuration example
|
||||
|
||||
mail:
|
||||
host: smtp.qq.com # 邮箱地址
|
||||
port: 465 # 邮箱端口号
|
||||
username: xxx@qq.com # 设置发送邮箱
|
||||
password: xx # 如果是纯数字要加引号
|
||||
default-encoding: UTF-8 # 设置编码格式
|
||||
protocol: smtps
|
||||
properties:
|
||||
mail:
|
||||
debug: true # 是否开启debug模式发送邮件
|
||||
smtp:
|
||||
auth: true
|
||||
connectionTimeout: 5000 # 设置连接延迟
|
||||
timeout: 5000 # 延迟时间
|
||||
writeTimeout: 5000 # 写入邮箱延迟
|
||||
allow8BitMime: true
|
||||
sendPartial: true
|
||||
ssl:
|
||||
enabled: true # 是否开启SSL连接
|
||||
socketFactory:
|
||||
class: javax.net.ssl.SSLSocketFactory # 必要设置!!!
|
|
@ -1,23 +0,0 @@
|
|||
package cn.bunny.module.mail.utils;
|
||||
|
||||
import cn.bunny.common.service.utils.EmptyUtil;
|
||||
import cn.bunny.pojo.email.EmailSend;
|
||||
import cn.bunny.pojo.result.constant.MailMessageConstant;
|
||||
|
||||
public class MailSendCheckUtil {
|
||||
/**
|
||||
* 检测发送对象是否为空的对象
|
||||
*
|
||||
* @param emailSend 邮件发送对象
|
||||
*/
|
||||
public static void check(EmailSend emailSend) {
|
||||
// 空发送对象
|
||||
EmptyUtil.isEmpty(emailSend, MailMessageConstant.EMPTY_SEND_OBJECT);
|
||||
// 收件人不能为空
|
||||
EmptyUtil.isEmpty(emailSend.getSendTo(), MailMessageConstant.ADDRESS_NOT_NULL);
|
||||
// 标题不能为空
|
||||
EmptyUtil.isEmpty(emailSend.getSubject(), MailMessageConstant.TITLE_NOT_NULL);
|
||||
// 发送消息不能为空
|
||||
EmptyUtil.isEmpty(emailSend.getMessage(), MailMessageConstant.SEND_MESSAGE_NOT_NULL);
|
||||
}
|
||||
}
|
|
@ -1,167 +0,0 @@
|
|||
package cn.bunny.module.mail.utils;
|
||||
|
||||
import cn.bunny.pojo.email.EmailSend;
|
||||
import cn.bunny.pojo.email.EmailSendInit;
|
||||
import jakarta.mail.MessagingException;
|
||||
import jakarta.mail.internet.MimeMessage;
|
||||
import org.springframework.mail.SimpleMailMessage;
|
||||
import org.springframework.mail.javamail.JavaMailSenderImpl;
|
||||
import org.springframework.mail.javamail.MimeMessageHelper;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class MailSenderUtil {
|
||||
private final String username;
|
||||
private final JavaMailSenderImpl javaMailSender;
|
||||
|
||||
/**
|
||||
* 初始化构造函数进行当前类赋值
|
||||
*/
|
||||
public MailSenderUtil(EmailSendInit emailSendInit) {
|
||||
JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl();
|
||||
javaMailSender.setHost(emailSendInit.getHost());
|
||||
javaMailSender.setPort(emailSendInit.getPort());
|
||||
javaMailSender.setUsername(emailSendInit.getUsername());
|
||||
javaMailSender.setPassword(emailSendInit.getPassword());
|
||||
javaMailSender.setProtocol("smtps");
|
||||
javaMailSender.setDefaultEncoding("UTF-8");
|
||||
|
||||
this.username = emailSendInit.getUsername();
|
||||
this.javaMailSender = javaMailSender;
|
||||
}
|
||||
|
||||
/**
|
||||
* 综合邮箱发送
|
||||
*
|
||||
* @param emailSend 邮件消息
|
||||
*/
|
||||
public void sendEmail(EmailSend emailSend) throws MessagingException {
|
||||
MailSendCheckUtil.check(emailSend);
|
||||
|
||||
// 创建 MimeMessage 对象用于发送邮件富文本或者附件
|
||||
MimeMessage message = javaMailSender.createMimeMessage();
|
||||
// 创建 MimeMessageHelper
|
||||
MimeMessageHelper helper = new MimeMessageHelper(message, true);
|
||||
|
||||
// 设置发送人
|
||||
helper.setFrom(username);
|
||||
// 设置邮件接受者
|
||||
helper.setTo(emailSend.getSendTo());
|
||||
// 设置邮件主题
|
||||
helper.setSubject(emailSend.getSubject());
|
||||
// 设置发送消息 为富文本
|
||||
helper.setText(emailSend.getMessage(), emailSend.getIsRichText());
|
||||
// 设置抄送人
|
||||
helper.setCc(emailSend.getCcParam().split(","));
|
||||
// 邮件添加附件
|
||||
MultipartFile[] files = emailSend.getFile();
|
||||
for (MultipartFile file : files) {
|
||||
helper.addAttachment(Objects.requireNonNull(file.getOriginalFilename()), file);
|
||||
}
|
||||
|
||||
// 发送邮件
|
||||
javaMailSender.send(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送邮件-简单
|
||||
*
|
||||
* @param emailSend 邮件消息
|
||||
*/
|
||||
public void sendSimpleEmail(EmailSend emailSend) {
|
||||
MailSendCheckUtil.check(emailSend);
|
||||
// 创建邮件消息体 SimpleMailMessage 发送简单邮件
|
||||
SimpleMailMessage mailMessage = new SimpleMailMessage();
|
||||
|
||||
// 设置邮件发送人
|
||||
mailMessage.setFrom(username);
|
||||
// 设置邮件接受者
|
||||
mailMessage.setTo(emailSend.getSendTo());
|
||||
// 设置邮件主题
|
||||
mailMessage.setSubject(emailSend.getSubject());
|
||||
// 设置邮件消息
|
||||
mailMessage.setText(emailSend.getMessage());
|
||||
|
||||
javaMailSender.send(mailMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送带附件邮件
|
||||
*
|
||||
* @param emailSend 邮件消息
|
||||
*/
|
||||
public void sendAttachmentEmail(EmailSend emailSend, MultipartFile file, boolean isRich) throws MessagingException {
|
||||
MailSendCheckUtil.check(emailSend);
|
||||
// 创建 MimeMessage 对象用户发送附件或者是富文本内容
|
||||
MimeMessage mailMessage = javaMailSender.createMimeMessage();
|
||||
// 创建 MimeMessageHelper
|
||||
MimeMessageHelper helper = new MimeMessageHelper(mailMessage, true);
|
||||
|
||||
// 奢姿邮件发送人
|
||||
helper.setFrom(username);
|
||||
// 设置邮件接受者
|
||||
helper.setTo(emailSend.getSendTo());
|
||||
// 设置邮件消息
|
||||
helper.setText(emailSend.getMessage(), isRich);
|
||||
// 设置邮件主题
|
||||
helper.setSubject(emailSend.getSubject());
|
||||
// 邮件添加附件
|
||||
helper.addAttachment(Objects.requireNonNull(file.getOriginalFilename()), file);
|
||||
|
||||
// 发送邮件
|
||||
javaMailSender.send(mailMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送富文本邮件
|
||||
*
|
||||
* @param emailSend 邮件消息
|
||||
*/
|
||||
public void sendRichText(EmailSend emailSend, boolean isRich) throws MessagingException {
|
||||
MailSendCheckUtil.check(emailSend);
|
||||
// 创建 MimeMessage 对象用户发送附件或者是富文本内容
|
||||
MimeMessage mailMessage = javaMailSender.createMimeMessage();
|
||||
// 创建 MimeMessageHelper
|
||||
MimeMessageHelper helper = new MimeMessageHelper(mailMessage, true);
|
||||
|
||||
// 设置邮件发送者
|
||||
helper.setFrom(username);
|
||||
// 设置邮件接受者
|
||||
helper.setTo(emailSend.getSendTo());
|
||||
// 设置邮件主题
|
||||
helper.setSubject(emailSend.getSubject());
|
||||
// 设置邮件富文本,后面跟true 表示HTML格式发送
|
||||
helper.setText(emailSend.getMessage(), isRich);
|
||||
|
||||
// 发送邮件
|
||||
javaMailSender.send(mailMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送带抄送的邮件
|
||||
*
|
||||
* @param emailSend 邮件消息
|
||||
*/
|
||||
public void sendCC(EmailSend emailSend, boolean isRich) throws MessagingException {
|
||||
MailSendCheckUtil.check(emailSend);
|
||||
// 创建 MimeMessage 对象用于发送邮件富文本或者附件
|
||||
MimeMessage message = javaMailSender.createMimeMessage();
|
||||
// 创建 MimeMessageHelper
|
||||
MimeMessageHelper helper = new MimeMessageHelper(message, true);
|
||||
|
||||
// 设置发送人
|
||||
helper.setFrom(username);
|
||||
// 设置邮件接受者
|
||||
helper.setTo(emailSend.getSendTo());
|
||||
// 设置邮件主题
|
||||
helper.setSubject(emailSend.getSubject());
|
||||
// 设置发送消息 为富文本
|
||||
helper.setText(emailSend.getMessage(), isRich);
|
||||
// 设置抄送人
|
||||
helper.setCc(emailSend.getCcParam().split(","));
|
||||
|
||||
// 发送邮件
|
||||
javaMailSender.send(message);
|
||||
}
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>cn.bunny</groupId>
|
||||
<artifactId>module</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>module-minio</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>module-minio</name>
|
||||
<url>https://maven.apache.org</url>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<!-- minio -->
|
||||
<dependency>
|
||||
<groupId>io.minio</groupId>
|
||||
<artifactId>minio</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -1,27 +0,0 @@
|
|||
package cn.bunny.module.minio.properties;
|
||||
|
||||
import io.minio.MinioClient;
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "bunny.minio")
|
||||
@ConditionalOnProperty(name = "bunny.minio.bucket-name")// 当属性有值时这个配置才生效
|
||||
@Data
|
||||
@Slf4j
|
||||
public class MinioProperties {
|
||||
private String endpointUrl;
|
||||
private String accessKey;
|
||||
private String secretKey;
|
||||
private String bucketName;
|
||||
|
||||
@Bean
|
||||
public MinioClient minioClient() {
|
||||
log.info("注册MinioClient...");
|
||||
return MinioClient.builder().endpoint(endpointUrl).credentials(accessKey, secretKey).build();
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,35 +0,0 @@
|
|||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>cn.bunny</groupId>
|
||||
<artifactId>module</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>module-rabbitMQ</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>module-rabbitMQ</name>
|
||||
<url>https://maven.apache.org</url>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-amqp</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.amqp</groupId>
|
||||
<artifactId>spring-rabbit-test</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.dataformat</groupId>
|
||||
<artifactId>jackson-dataformat-xml</artifactId>
|
||||
<version>2.16.0-rc1</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -1,38 +0,0 @@
|
|||
package cn.bunny.module.rabbitMQ.config;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
|
||||
import org.springframework.amqp.support.converter.MessageConverter;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class RabbitMqConfig {
|
||||
@Autowired
|
||||
private RabbitTemplate rabbitTemplate;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
rabbitTemplate.setReturnsCallback(returned -> {
|
||||
log.error("触发return callback,");
|
||||
log.debug("exchange: {}", returned.getExchange());
|
||||
log.debug("routingKey: {}", returned.getRoutingKey());
|
||||
log.debug("message: {}", returned.getMessage());
|
||||
log.debug("replyCode: {}", returned.getReplyCode());
|
||||
log.debug("replyText: {}", returned.getReplyText());
|
||||
});
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MessageConverter messageConverter() {
|
||||
// 1.定义消息转换器
|
||||
Jackson2JsonMessageConverter converter = new Jackson2JsonMessageConverter();
|
||||
// 2.配置自动创建消息id,用于识别不同消息,也可以在业务中基于ID判断是否是重复消息
|
||||
converter.setCreateMessageIds(true);
|
||||
return converter;
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
package cn.bunny.module.rabbitMQ.consumer;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class DelayConsumer {
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
package cn.bunny.module.rabbitMQ.consumer;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class DirectConsumer {
|
||||
@Autowired
|
||||
RabbitTemplate rabbitTemplate;
|
||||
|
||||
/**
|
||||
* 发送红色消息
|
||||
*/
|
||||
@Test
|
||||
void testSendDirectRed() throws Exception {
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
rabbitTemplate.convertAndSend("bunny.direct", "red", "发送消息:" + i);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
package cn.bunny.module.rabbitMQ.consumer;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class ErrorConsumer {
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
package cn.bunny.module.rabbitMQ.consumer;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class FanoutConsumer {
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
package cn.bunny.module.rabbitMQ.consumer;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class LazyConsumer {
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
package cn.bunny.module.rabbitMQ.consumer;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class TopicConsumer {
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
package cn.bunny.module.rabbitMQ.listener;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class DelayListener {
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
package cn.bunny.module.rabbitMQ.listener;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.amqp.core.ExchangeTypes;
|
||||
import org.springframework.amqp.rabbit.annotation.Exchange;
|
||||
import org.springframework.amqp.rabbit.annotation.Queue;
|
||||
import org.springframework.amqp.rabbit.annotation.QueueBinding;
|
||||
import org.springframework.amqp.rabbit.annotation.RabbitListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class DirectListener {
|
||||
/**
|
||||
* * 监听者2
|
||||
* 创建队列 持久化的、不自动删除
|
||||
* 创建交换机 持久化的、不自动删除
|
||||
* key包含 red 和 yellow
|
||||
*
|
||||
* @param message 接受消息
|
||||
*/
|
||||
@RabbitListener(bindings = @QueueBinding(
|
||||
value = @Queue(name = "direct.queue2", durable = "true", autoDelete = "false"),
|
||||
exchange = @Exchange(name = "bunny.direct", type = ExchangeTypes.DIRECT, durable = "true", autoDelete = "false"),
|
||||
key = {"red", "yellow"}
|
||||
))
|
||||
public void listenDirectQueue2(String message) {
|
||||
System.out.println("消费者2接收到 Direct key 为 {\"red\", \"yellow\"} 消息:【" + message + "】");
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
package cn.bunny.module.rabbitMQ.listener;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class ErrorListener {
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
package cn.bunny.module.rabbitMQ.listener;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class FanoutListener {
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
package cn.bunny.module.rabbitMQ.listener;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class LazyListener {
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
package cn.bunny.module.rabbitMQ.listener;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class TopicListener {
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>cn.bunny</groupId>
|
||||
<artifactId>module</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>module-task</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>module-task</name>
|
||||
<url>https://maven.apache.org</url>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
</dependencies>
|
||||
</project>
|
|
@ -1,14 +0,0 @@
|
|||
package cn.bunny.module.task;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class TemplateTask {
|
||||
@Scheduled(cron = "0/1 5 * * * ?")
|
||||
public void templateTask() {
|
||||
log.info("定时任务执行...");
|
||||
}
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>cn.bunny</groupId>
|
||||
<artifactId>module</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>module-websocket</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>module-websocket</name>
|
||||
<url>https://maven.apache.org</url>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<!-- websocket -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-websocket</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -1,71 +0,0 @@
|
|||
package cn.bunny.module.websocket;
|
||||
|
||||
import jakarta.websocket.OnClose;
|
||||
import jakarta.websocket.OnMessage;
|
||||
import jakarta.websocket.OnOpen;
|
||||
import jakarta.websocket.Session;
|
||||
import jakarta.websocket.server.PathParam;
|
||||
import jakarta.websocket.server.ServerEndpoint;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* WebSocket服务
|
||||
*/
|
||||
@Component
|
||||
@ServerEndpoint("/ws/{sid}")
|
||||
public class WebSocketServer {
|
||||
|
||||
// 存放会话对象
|
||||
private static final Map<String, Session> sessionMap = new HashMap();
|
||||
|
||||
/**
|
||||
* 连接建立成功调用的方法
|
||||
*/
|
||||
@OnOpen
|
||||
public void onOpen(Session session, @PathParam("sid") String sid) {
|
||||
System.out.println("客户端:" + sid + "建立连接");
|
||||
sessionMap.put(sid, session);
|
||||
}
|
||||
|
||||
/**
|
||||
* 收到客户端消息后调用的方法
|
||||
*
|
||||
* @param message 客户端发送过来的消息
|
||||
*/
|
||||
@OnMessage
|
||||
public void onMessage(String message, @PathParam("sid") String sid) {
|
||||
System.out.println("收到来自客户端:" + sid + "的信息:" + message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 连接关闭调用的方法
|
||||
*
|
||||
* @param sid 请求id
|
||||
*/
|
||||
@OnClose
|
||||
public void onClose(@PathParam("sid") String sid) {
|
||||
System.out.println("连接断开:" + sid);
|
||||
sessionMap.remove(sid);
|
||||
}
|
||||
|
||||
/**
|
||||
* 群发
|
||||
*
|
||||
* @param message 消息
|
||||
*/
|
||||
public void sendToAllClient(String message) {
|
||||
Collection<Session> sessions = sessionMap.values();
|
||||
for (Session session : sessions) {
|
||||
try {
|
||||
// 服务器向客户端发送消息
|
||||
session.getBasicRemote().sendText(message);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
package cn.bunny.module.websocket.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
|
||||
|
||||
@Configuration
|
||||
public class WebSocketConfiguration {
|
||||
@Bean
|
||||
public ServerEndpointExporter endpointExporter() {
|
||||
return new ServerEndpointExporter();
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>cn.bunny</groupId>
|
||||
<artifactId>Quartz-Demo</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>module</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>module</name>
|
||||
<url>https://maven.apache.org</url>
|
||||
<modules>
|
||||
<module>module-minio</module>
|
||||
<module>module-mail</module>
|
||||
<module>module-rabbitMQ</module>
|
||||
<module>module-websocket</module>
|
||||
<module>spring-security</module>
|
||||
<module>module-task</module>
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>cn.bunny</groupId>
|
||||
<artifactId>service-utils</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -1,32 +0,0 @@
|
|||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>cn.bunny</groupId>
|
||||
<artifactId>module</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>spring-security</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>spring-security</name>
|
||||
<url>https://maven.apache.org</url>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<!-- spring-security -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
<!-- spring-security-test -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-test</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -1,96 +0,0 @@
|
|||
package cn.bunny.security.config;
|
||||
|
||||
import cn.bunny.security.custom.CustomPasswordEncoder;
|
||||
import cn.bunny.security.filter.TokenAuthenticationFilter;
|
||||
import cn.bunny.security.filter.TokenLoginFilterService;
|
||||
import cn.bunny.security.handelr.SecurityAccessDeniedHandler;
|
||||
import cn.bunny.security.handelr.SecurityAuthenticationEntryPoint;
|
||||
import cn.bunny.security.service.CustomAuthorizationManagerService;
|
||||
import cn.bunny.security.service.CustomUserDetailsService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
|
||||
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
||||
import org.springframework.security.core.session.SessionRegistry;
|
||||
import org.springframework.security.core.session.SessionRegistryImpl;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
import org.springframework.security.web.util.matcher.RegexRequestMatcher;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@EnableMethodSecurity
|
||||
public class WebSecurityConfig {
|
||||
@Autowired
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
// 自定义用户接口
|
||||
@Autowired
|
||||
private CustomUserDetailsService customUserDetailsService;
|
||||
// 自定义密码加密器
|
||||
@Autowired
|
||||
private CustomPasswordEncoder customPasswordEncoder;
|
||||
// 自定义验证码
|
||||
@Autowired
|
||||
private CustomAuthorizationManagerService customAuthorizationManager;
|
||||
@Autowired
|
||||
private AuthenticationConfiguration authenticationConfiguration;
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
|
||||
httpSecurity
|
||||
// 前端段分离不需要---禁用明文验证
|
||||
.httpBasic(AbstractHttpConfigurer::disable)
|
||||
// 前端段分离不需要---禁用默认登录页
|
||||
.formLogin(AbstractHttpConfigurer::disable)
|
||||
// 前端段分离不需要---禁用退出页
|
||||
.logout(AbstractHttpConfigurer::disable)
|
||||
// 前端段分离不需要---csrf攻击
|
||||
.csrf(AbstractHttpConfigurer::disable)
|
||||
// 跨域访问权限,如果需要可以关闭后自己配置跨域访问
|
||||
.cors(AbstractHttpConfigurer::disable)
|
||||
// 前后端分离不需要---因为是无状态的
|
||||
.sessionManagement(AbstractHttpConfigurer::disable)
|
||||
// 前后端分离不需要---记住我,e -> e.rememberMeParameter("rememberBunny").rememberMeCookieName("rememberBunny").key("BunnyKey")
|
||||
.rememberMe(AbstractHttpConfigurer::disable)
|
||||
.authorizeHttpRequests(authorize -> {
|
||||
// 有样式文件,不需要访问权限
|
||||
authorize.requestMatchers(RegexRequestMatcher.regexMatcher("^\\S*[css|js]$")).permitAll();
|
||||
// 上面都不是需要鉴权访问
|
||||
authorize.anyRequest().access(customAuthorizationManager);
|
||||
})
|
||||
.exceptionHandling(exception -> {
|
||||
// 请求未授权接口
|
||||
exception.authenticationEntryPoint(new SecurityAuthenticationEntryPoint());
|
||||
// 没有权限访问
|
||||
exception.accessDeniedHandler(new SecurityAccessDeniedHandler());
|
||||
})
|
||||
// 登录验证过滤器
|
||||
.addFilterBefore(new TokenLoginFilterService(authenticationConfiguration, redisTemplate, customUserDetailsService), UsernamePasswordAuthenticationFilter.class)
|
||||
// 其它权限鉴权过滤器
|
||||
.addFilterAt(new TokenAuthenticationFilter(redisTemplate), UsernamePasswordAuthenticationFilter.class)
|
||||
// 自定义密码加密器和用户登录
|
||||
.passwordManagement(customPasswordEncoder).userDetailsService(customUserDetailsService);
|
||||
|
||||
return httpSecurity.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SessionRegistry sessionRegistry() {
|
||||
return new SessionRegistryImpl();
|
||||
}
|
||||
|
||||
// 排出鉴定路径
|
||||
@Bean
|
||||
public WebSecurityCustomizer webSecurityCustomizer() {
|
||||
String[] annotations = {"/", "/test/**", "/diagram-viewer/**", "/editor-app/**", "/*.html",
|
||||
"/api/**",
|
||||
"/*/*/noAuth/**", "/*/noAuth/**", "/favicon.ico", "/swagger-resources/**", "/webjars/**", "/v3/**", "/swagger-ui.html/**", "/doc.html"};
|
||||
return web -> web.ignoring().requestMatchers(annotations);
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
package cn.bunny.security.custom;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.Customizer;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configurers.PasswordManagementConfigurer;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.util.DigestUtils;
|
||||
|
||||
/**
|
||||
* 自定义密码加密比对
|
||||
*/
|
||||
@Configuration
|
||||
public class CustomPasswordEncoder implements PasswordEncoder, Customizer<PasswordManagementConfigurer<HttpSecurity>> {
|
||||
@Override
|
||||
public String encode(CharSequence rawPassword) {
|
||||
return DigestUtils.md5DigestAsHex(rawPassword.toString().getBytes());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(CharSequence rawPassword, String encodedPassword) {
|
||||
return encodedPassword.matches(DigestUtils.md5DigestAsHex(rawPassword.toString().getBytes()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void customize(PasswordManagementConfigurer<HttpSecurity> httpSecurityPasswordManagementConfigurer) {
|
||||
}
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
package cn.bunny.security.custom;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* 重写自带的User
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class CustomUser extends User {
|
||||
private cn.bunny.entity.system.user.User user;
|
||||
|
||||
public CustomUser(cn.bunny.entity.system.user.User user, Collection<? extends GrantedAuthority> authorities) {
|
||||
super(user.getEmail(), user.getPassword(), authorities);
|
||||
this.user = user;
|
||||
}
|
||||
}
|
|
@ -1,91 +0,0 @@
|
|||
package cn.bunny.security.filter;
|
||||
|
||||
import cn.bunny.common.service.context.BaseContext;
|
||||
import cn.bunny.common.service.exception.BunnyException;
|
||||
import cn.bunny.common.service.utils.JwtHelper;
|
||||
import cn.bunny.common.service.utils.ResponseUtil;
|
||||
import cn.bunny.pojo.result.Result;
|
||||
import cn.bunny.pojo.result.ResultCodeEnum;
|
||||
import cn.bunny.pojo.result.constant.RedisUserConstant;
|
||||
import cn.bunny.vo.system.login.LoginVo;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class TokenAuthenticationFilter extends OncePerRequestFilter {
|
||||
private final RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
public TokenAuthenticationFilter(RedisTemplate<String, Object> redisTemplate) {
|
||||
this.redisTemplate = redisTemplate;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException, BunnyException {
|
||||
String token = request.getHeader("token");
|
||||
|
||||
// login请求就没token,直接放行,因为后边有其他的过滤器
|
||||
if (token == null) {
|
||||
doFilter(request, response, chain);
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果想让这个用户下线,清空Redis这个用户值,返回未登录,判断Redis是否有这个用户
|
||||
// 如果想让这个用户锁定,清空Redis值并在数据库中设置status值为1
|
||||
String userName = JwtHelper.getUsername(token);
|
||||
Object usernameObject = redisTemplate.opsForValue().get(RedisUserConstant.getUserLoginInfoPrefix(userName));
|
||||
if (usernameObject == null) {
|
||||
Result<Object> error = Result.error(ResultCodeEnum.LOGIN_AUTH);
|
||||
ResponseUtil.out(response, error);
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取Redis中登录信息
|
||||
LoginVo loginVo = JSON.parseObject(JSON.toJSONString(usernameObject), LoginVo.class);
|
||||
// 如果是登录接口,直接放行
|
||||
UsernamePasswordAuthenticationToken authentication = getAuthentication(request);
|
||||
if (authentication != null) {
|
||||
// 设置用户详细信息
|
||||
authentication.setDetails(loginVo.getPersonDescription());
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
}
|
||||
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
|
||||
private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
|
||||
// 请求头是否有token
|
||||
String token = request.getHeader("token");
|
||||
String username = RedisUserConstant.getAdminLoginInfoPrefix(JwtHelper.getUsername(token));
|
||||
List<SimpleGrantedAuthority> authList = new ArrayList<>();
|
||||
if (!StringUtils.hasText(username)) return null;
|
||||
|
||||
// 当前用户信息放到ThreadLocal里面
|
||||
BaseContext.setAdminId(JwtHelper.getUserId(token));
|
||||
BaseContext.setAdminName(username);
|
||||
|
||||
// 通过username从redis获取权限数据
|
||||
Object UserObject = redisTemplate.opsForValue().get(username);
|
||||
// 把redis获取字符串权限数据转换要求集合类型 List<SimpleGrantedAuthority>
|
||||
if (UserObject != null) {
|
||||
LoginVo loginVo = JSON.parseObject(JSON.toJSONString(UserObject), LoginVo.class);
|
||||
List<String> roleList = loginVo.getRoleList();
|
||||
roleList.forEach(role -> authList.add(new SimpleGrantedAuthority(role)));
|
||||
|
||||
return new UsernamePasswordAuthenticationToken(username, null, authList);
|
||||
} else {
|
||||
return new UsernamePasswordAuthenticationToken(username, null, new ArrayList<>());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,139 +0,0 @@
|
|||
package cn.bunny.security.filter;
|
||||
|
||||
|
||||
import cn.bunny.common.service.utils.ResponseUtil;
|
||||
import cn.bunny.dto.user.LoginDto;
|
||||
import cn.bunny.pojo.result.Result;
|
||||
import cn.bunny.pojo.result.ResultCodeEnum;
|
||||
import cn.bunny.pojo.result.constant.RedisUserConstant;
|
||||
import cn.bunny.security.handelr.SecurityAuthenticationFailureHandler;
|
||||
import cn.bunny.security.handelr.SecurityAuthenticationSuccessHandler;
|
||||
import cn.bunny.security.service.CustomUserDetailsService;
|
||||
import cn.bunny.vo.system.login.LoginVo;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* * UsernamePasswordAuthenticationFilter
|
||||
* * 也可以在这里添加验证码、短信等的验证
|
||||
* 由于SpringSecurity的登录只能是表单形式 并且用户名密码需要时username、password,可以通过继承 UsernamePasswordAuthenticationFilter 获取登录请求的参数
|
||||
* 再去设置到 UsernamePasswordAuthenticationToken 中 来改变请求传参方式、参数名等 或者也可以在登录的时候加入其他参数等等
|
||||
*/
|
||||
public class TokenLoginFilterService extends UsernamePasswordAuthenticationFilter {
|
||||
private final RedisTemplate<String, Object> redisTemplate;
|
||||
private final CustomUserDetailsService customUserDetailsService;
|
||||
private LoginDto loginDto;
|
||||
|
||||
// 依赖注入
|
||||
public TokenLoginFilterService(AuthenticationConfiguration authenticationConfiguration, RedisTemplate<String, Object> redisTemplate, CustomUserDetailsService customUserDetailsService) throws Exception {
|
||||
this.setAuthenticationSuccessHandler(new SecurityAuthenticationSuccessHandler());
|
||||
this.setAuthenticationFailureHandler(new SecurityAuthenticationFailureHandler());
|
||||
this.setPostOnly(false);
|
||||
// ? 指定登录接口及提交方式,可以指定任意路径
|
||||
this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/*/login", HttpMethod.POST.name()));
|
||||
this.setAuthenticationManager(authenticationConfiguration.getAuthenticationManager());
|
||||
// 依赖注入
|
||||
this.redisTemplate = redisTemplate;
|
||||
this.customUserDetailsService = customUserDetailsService;
|
||||
}
|
||||
|
||||
/**
|
||||
* * 登录认证,获取输入的用户名和密码,调用方法认证
|
||||
* 接受前端login登录参数
|
||||
* 在这里可以设置短信验证登录
|
||||
*/
|
||||
@Override
|
||||
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
|
||||
try {
|
||||
// 获取用户信息
|
||||
loginDto = new ObjectMapper().readValue(request.getInputStream(), LoginDto.class);
|
||||
|
||||
// 登录验证码判断
|
||||
String username = loginDto.getUsername();
|
||||
String emailCode = loginDto.getEmailCode().toLowerCase();
|
||||
String redisEmailCode = (String) redisTemplate.opsForValue().get(RedisUserConstant.getAdminUserEmailCodePrefix(username));
|
||||
|
||||
// 如果不存在验证码
|
||||
if (!StringUtils.hasText(emailCode)) {
|
||||
ResponseUtil.out(response, Result.error(ResultCodeEnum.EMAIL_CODE_NOT_EMPTY));
|
||||
return null;
|
||||
}
|
||||
if (!StringUtils.hasText(redisEmailCode)) {
|
||||
ResponseUtil.out(response, Result.error(ResultCodeEnum.SEND_EMAIL_CODE_NOT_EMPTY));
|
||||
return null;
|
||||
}
|
||||
// 验证码不匹配
|
||||
if (!Objects.equals(redisEmailCode.toLowerCase(), emailCode)) {
|
||||
ResponseUtil.out(response, Result.error(ResultCodeEnum.EMAIL_CODE_NOT_MATCHING));
|
||||
return null;
|
||||
}
|
||||
|
||||
// 封装对象,将用户名密码传入
|
||||
Authentication authenticationToken = new UsernamePasswordAuthenticationToken(loginDto.getUsername(), loginDto.getPassword());
|
||||
return this.getAuthenticationManager().authenticate(authenticationToken);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e.getLocalizedMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* * 认证成功调用方法
|
||||
* 返回登录成功后的信息
|
||||
*/
|
||||
@Override
|
||||
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication auth) {
|
||||
// 封装返回对象
|
||||
LoginVo loginVo = customUserDetailsService.login(loginDto);
|
||||
|
||||
// 判断用户是否被锁定
|
||||
if (loginVo.getStatus() == 1) {
|
||||
ResponseUtil.out(response, Result.error(ResultCodeEnum.FAIL_NO_ACCESS_DENIED_USER_LOCKED));
|
||||
return;
|
||||
}
|
||||
|
||||
// 将值存入Redis中
|
||||
redisTemplate.opsForValue().set(RedisUserConstant.getAdminLoginInfoPrefix(loginVo.getEmail()), loginVo, 15, TimeUnit.DAYS);
|
||||
// 将Redis中验证码删除
|
||||
redisTemplate.delete(RedisUserConstant.getAdminUserEmailCodePrefix(loginVo.getEmail()));
|
||||
// 返回登录信息
|
||||
ResponseUtil.out(response, Result.success(loginVo));
|
||||
}
|
||||
|
||||
/**
|
||||
* * 认证失败调用方法,失败判断
|
||||
* 1. 是否包含用户名
|
||||
* 2. 是否包含密码
|
||||
*/
|
||||
@Override
|
||||
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) {
|
||||
// 账号和密码不能为空
|
||||
if (loginDto == null) {
|
||||
ResponseUtil.out(response, Result.error(ResultCodeEnum.LOGIN_ERROR_USERNAME_PASSWORD_NOT_EMPTY));
|
||||
}
|
||||
// 用户名为空
|
||||
if (!StringUtils.hasText(loginDto.getUsername())) {
|
||||
ResponseUtil.out(response, Result.error(ResultCodeEnum.USERNAME_NOT_EMPTY));
|
||||
}
|
||||
// 密码为空
|
||||
if (!StringUtils.hasText(loginDto.getPassword())) {
|
||||
ResponseUtil.out(response, Result.error(ResultCodeEnum.PASSWORD_NOT_EMPTY));
|
||||
}
|
||||
// 抛出异常,账号或密码错误
|
||||
ResponseUtil.out(response, Result.error(null, ResultCodeEnum.LOGIN_ERROR));
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
package cn.bunny.security.handelr;
|
||||
|
||||
import cn.bunny.pojo.result.Result;
|
||||
import cn.bunny.pojo.result.ResultCodeEnum;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.SneakyThrows;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
|
||||
/**
|
||||
* 没有权限访问
|
||||
*/
|
||||
public class SecurityAccessDeniedHandler implements org.springframework.security.web.access.AccessDeniedHandler {
|
||||
@SneakyThrows
|
||||
@Override
|
||||
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) {
|
||||
Result<Object> result = Result.error(ResultCodeEnum.FAIL_NO_ACCESS_DENIED);
|
||||
|
||||
Object json = JSON.toJSON(result);
|
||||
|
||||
// 返回响应
|
||||
response.setContentType("application/json;charset=UTF-8");
|
||||
response.getWriter().println(json);
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
package cn.bunny.security.handelr;
|
||||
|
||||
import cn.bunny.common.service.utils.ResponseUtil;
|
||||
import cn.bunny.pojo.result.Result;
|
||||
import cn.bunny.pojo.result.ResultCodeEnum;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* 请求未认证接口
|
||||
*/
|
||||
@Slf4j
|
||||
public class SecurityAuthenticationEntryPoint implements AuthenticationEntryPoint {
|
||||
@Override
|
||||
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException {
|
||||
String token = response.getHeader("token");
|
||||
String message = authException.getMessage();
|
||||
// 创建结果对象
|
||||
Result<Object> result;
|
||||
|
||||
if (token == null) {
|
||||
result = Result.error(ResultCodeEnum.LOGIN_AUTH);
|
||||
log.info("请求未登录接口:{},用户id:{}", message, null);
|
||||
} else {
|
||||
result = Result.error(ResultCodeEnum.LOGGED_IN_FROM_ANOTHER_DEVICE);
|
||||
log.info("请求未授权接口:{},用户id:{}", message, token);
|
||||
}
|
||||
|
||||
// 返回响应
|
||||
ResponseUtil.out(response, result);
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
package cn.bunny.security.handelr;
|
||||
|
||||
import cn.bunny.pojo.result.Result;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class SecurityAuthenticationFailureHandler implements org.springframework.security.web.authentication.AuthenticationFailureHandler {
|
||||
@Override
|
||||
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
|
||||
// 错误消息
|
||||
String localizedMessage = exception.getLocalizedMessage();
|
||||
Result<String> result = Result.error(localizedMessage);
|
||||
|
||||
// 转成JSON
|
||||
Object json = JSON.toJSON(result);
|
||||
|
||||
// 返回响应
|
||||
response.setContentType("application/json;charset=UTF-8");
|
||||
response.getWriter().println(json);
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
package cn.bunny.security.handelr;
|
||||
|
||||
import cn.bunny.pojo.result.Result;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* 登录成功
|
||||
*/
|
||||
public class SecurityAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
|
||||
@Override
|
||||
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException {
|
||||
// 获取用户身份信息
|
||||
Object principal = authentication.getPrincipal();
|
||||
Result<Object> result = Result.success(principal);
|
||||
|
||||
// 返回
|
||||
response.setContentType("application/json;charset=UTF-8");
|
||||
response.getWriter().println(JSON.toJSON(result));
|
||||
}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
package cn.bunny.security.service;
|
||||
|
||||
import org.springframework.security.authorization.AuthorizationManager;
|
||||
import org.springframework.security.web.access.intercept.RequestAuthorizationContext;
|
||||
|
||||
public interface CustomAuthorizationManagerService extends AuthorizationManager<RequestAuthorizationContext> {
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
package cn.bunny.security.service;
|
||||
|
||||
import cn.bunny.dto.user.LoginDto;
|
||||
import cn.bunny.vo.system.login.LoginVo;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
|
||||
public interface CustomUserDetailsService extends UserDetailsService {
|
||||
/**
|
||||
* 根据用户名获取用户对象(获取不到直接抛异常)
|
||||
*/
|
||||
@Override
|
||||
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
|
||||
|
||||
/**
|
||||
* 前台用户登录接口
|
||||
*
|
||||
* @param loginDto 登录参数
|
||||
* @return 登录后结果返回
|
||||
*/
|
||||
LoginVo login(LoginDto loginDto);
|
||||
}
|
1
pom.xml
1
pom.xml
|
@ -19,7 +19,6 @@
|
|||
<module>common</module>
|
||||
<module>dao</module>
|
||||
<module>service</module>
|
||||
<module>module</module>
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
|
|
|
@ -22,17 +22,7 @@
|
|||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>cn.bunny</groupId>
|
||||
<artifactId>spring-security</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.bunny</groupId>
|
||||
<artifactId>module-mail</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.bunny</groupId>
|
||||
<artifactId>module-minio</artifactId>
|
||||
<artifactId>service-utils</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<!-- 单元测试 -->
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
package cn.bunny.service.aop.annotation;
|
||||
|
||||
import cn.bunny.pojo.enums.OperationType;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface AutoFill {
|
||||
// 数据库操作类型
|
||||
OperationType value();
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
package cn.bunny.service.aop.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface SkipLog {
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
package cn.bunny.service.aop.aspect;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Before;
|
||||
import org.aspectj.lang.annotation.Pointcut;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Aspect
|
||||
@Component
|
||||
@Slf4j
|
||||
public class AutoFillAspect {
|
||||
@Pointcut("execution(* cn.bunny.service.web.service.impl..*(..))")
|
||||
public void autoFillPointcut() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 之前操作
|
||||
*
|
||||
* @param joinPoint 参数
|
||||
*/
|
||||
@Before("autoFillPointcut()")
|
||||
public void autoFill(JoinPoint joinPoint) {
|
||||
log.info("开始进行自动填充");
|
||||
}
|
||||
}
|
|
@ -1,83 +0,0 @@
|
|||
package cn.bunny.service.aop.aspect;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Aspect
|
||||
@Component
|
||||
@Slf4j
|
||||
public class AutoLogAspect {
|
||||
// @Autowired
|
||||
// private SystemLogMapper systemLogMapper;
|
||||
//
|
||||
// @Pointcut("execution(* cn.bunny.service.controller..*(..))")
|
||||
// public void point() {
|
||||
// }
|
||||
//
|
||||
// @Around(value = "point()")
|
||||
// public Object aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable {
|
||||
// Object result;
|
||||
// MethodSignature signature = (MethodSignature) joinPoint.getSignature();
|
||||
// // 是否有跳过注解,如果有跳过注解就不执行当前操作!!!
|
||||
// SkipLog annotation = signature.getMethod().getAnnotation(SkipLog.class);
|
||||
// // 目标方法所在类名路径
|
||||
// String classPath = joinPoint.getSignature().getDeclaringTypeName();
|
||||
// // 当前执行的方法名
|
||||
// String methodName = signature.getName();
|
||||
// // 入参内容
|
||||
// String args = Arrays.toString(joinPoint.getArgs());
|
||||
// // 获取用户token
|
||||
// ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||
// HttpServletRequest request = requestAttributes.getRequest();
|
||||
// String token = request.getHeader("token");
|
||||
// // 初始化系统日志对象
|
||||
// SystemLog systemLog = new SystemLog();
|
||||
// // token转为实体对象
|
||||
// Map<String, Object> mapByToken = JwtHelper.getMapByToken(token);
|
||||
// LoginVo loginVo = JSONObject.parseObject(JSONObject.toJSONString(mapByToken), LoginVo.class);
|
||||
//
|
||||
// // 插入Ip地址
|
||||
// systemLog.setIpAddress(request.getRemoteHost());
|
||||
//
|
||||
// try {
|
||||
// // 当为null时跳过执行
|
||||
// if (annotation != null) return joinPoint.proceed();
|
||||
// if (args.equals("[null]")) {
|
||||
// systemLog.setArgs(null);
|
||||
// } else {
|
||||
// systemLog.setArgs(args);
|
||||
// }
|
||||
// // 登录返回Vo不为空即插入
|
||||
// if (loginVo != null) {
|
||||
// systemLog.setNickname(loginVo.getNickName());
|
||||
// systemLog.setEmail(loginVo.getEmail());
|
||||
// systemLog.setUpdateUser(loginVo.getId());
|
||||
// }
|
||||
//
|
||||
// systemLog.setClassPath(classPath);
|
||||
// systemLog.setMethodName(methodName);
|
||||
// systemLog.setToken(token);
|
||||
//
|
||||
// // 目标对象(连接点)方法的执行
|
||||
// result = joinPoint.proceed();
|
||||
// systemLog.setResult(JSONObject.toJSONString(result));
|
||||
// } catch (Exception exception) {
|
||||
// String message = exception.getMessage();
|
||||
// StackTraceElement[] stackTrace = exception.getStackTrace();
|
||||
//
|
||||
// // 如果报错,设置报错的堆栈和消息,放到数据库中
|
||||
// systemLog.setErrorStack(Arrays.toString(stackTrace));
|
||||
// systemLog.setErrorMessage(message);
|
||||
//
|
||||
// // 插入日志数据到数据库
|
||||
// systemLogMapper.insert(systemLog);
|
||||
//
|
||||
// throw exception;
|
||||
// }
|
||||
//
|
||||
// // 插入日志数据到数据库
|
||||
// systemLogMapper.insert(systemLog);
|
||||
// return result;
|
||||
// }
|
||||
}
|
|
@ -26,11 +26,4 @@ public class LoginController {
|
|||
LoginVo vo = userService.login(loginDto);
|
||||
return Result.success(vo);
|
||||
}
|
||||
|
||||
@Operation(summary = "发送邮箱验证码", description = "发送邮箱验证码")
|
||||
@PostMapping("noAuth/sendEmail")
|
||||
public Result<String> sendEmail(String email) {
|
||||
userService.sendEmail(email);
|
||||
return Result.success();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package cn.bunny.service.quartz;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.quartz.spi.TriggerFiredBundle;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
||||
|
@ -17,9 +17,8 @@ public class QuartzJobFactory extends AdaptableJobFactory {
|
|||
private AutowireCapableBeanFactory capableBeanFactory;
|
||||
|
||||
// 重写创建Job任务的实例方法
|
||||
@NotNull
|
||||
@Override
|
||||
protected Object createJobInstance(@NotNull TriggerFiredBundle bundle) throws Exception {
|
||||
protected Object createJobInstance( TriggerFiredBundle bundle) throws Exception {
|
||||
Object jobInstance = super.createJobInstance(bundle);
|
||||
// 通过以下方式,解决Job任务无法使用Spring中的Bean问题
|
||||
capableBeanFactory.autowireBean(jobInstance);
|
||||
|
|
|
@ -1,72 +0,0 @@
|
|||
package cn.bunny.service.security;
|
||||
|
||||
import cn.bunny.common.service.utils.JwtHelper;
|
||||
import cn.bunny.entity.system.admin.AdminPower;
|
||||
import cn.bunny.security.service.CustomAuthorizationManagerService;
|
||||
import cn.bunny.service.mapper.AdminPowerMapper;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.authorization.AuthorizationDecision;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.web.access.intercept.RequestAuthorizationContext;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
|
||||
/**
|
||||
* 自定义权限判断
|
||||
* 判断用户有哪些权限
|
||||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
public class CustomAuthorizationManagerServiceImpl implements CustomAuthorizationManagerService {
|
||||
@Autowired
|
||||
private AdminPowerMapper adminPowerMapper;
|
||||
|
||||
@Override
|
||||
public void verify(Supplier<Authentication> authentication, RequestAuthorizationContext requestAuthorizationContext) {
|
||||
CustomAuthorizationManagerService.super.verify(authentication, requestAuthorizationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthorizationDecision check(Supplier<Authentication> authentication, RequestAuthorizationContext context) {
|
||||
// 用户的token和用户id、请求Url
|
||||
HttpServletRequest request = context.getRequest();
|
||||
String token = request.getHeader("token");
|
||||
Long userId = JwtHelper.getUserId(token);// 用户id
|
||||
String requestURI = request.getRequestURI();// 请求地址
|
||||
String method = request.getMethod();// 请求方式
|
||||
List<String> roleCodeList = authentication.get().getAuthorities().stream().map(GrantedAuthority::getAuthority).toList();// 角色代码列表
|
||||
if (token == null) {
|
||||
throw new AccessDeniedException("");
|
||||
}
|
||||
|
||||
return new AuthorizationDecision(hasRoleList(requestURI, method, userId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询用户所属的角色信息
|
||||
*
|
||||
* @param requestURI 请求url地址
|
||||
* @param method 请求方式
|
||||
* @param userId 用户id
|
||||
*/
|
||||
private Boolean hasRoleList(String requestURI, String method, Long userId) {
|
||||
// 查询用户权限
|
||||
List<AdminPower> powerList = adminPowerMapper.queryByUserIdWithPower(userId);
|
||||
// 如果查询到当前地址符合这个地址
|
||||
for (AdminPower adminPower : powerList) {
|
||||
String description = adminPower.getDescription();
|
||||
if (description.equals(requestURI) || requestURI.matches(description)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
package cn.bunny.service.security;
|
||||
|
||||
import cn.bunny.dto.user.LoginDto;
|
||||
import cn.bunny.entity.system.admin.AdminRole;
|
||||
import cn.bunny.entity.system.user.User;
|
||||
import cn.bunny.security.custom.CustomUser;
|
||||
import cn.bunny.service.mapper.AdminRoleMapper;
|
||||
import cn.bunny.service.mapper.UserMapper;
|
||||
import cn.bunny.service.service.UserService;
|
||||
import cn.bunny.vo.system.login.LoginVo;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class CustomUserDetailsService implements cn.bunny.security.service.CustomUserDetailsService {
|
||||
@Autowired
|
||||
private UserMapper userMapper;
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
@Autowired
|
||||
private AdminRoleMapper adminRoleMapper;
|
||||
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
||||
// 根据邮箱查询用户名
|
||||
User user = userMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getEmail, username));
|
||||
List<AdminRole> sysRoleList = adminRoleMapper.selectList(null);
|
||||
// 都为空抛出异常,用户不存在
|
||||
if (user == null) {
|
||||
throw new UsernameNotFoundException("");
|
||||
}
|
||||
|
||||
// 查询所有的角色
|
||||
List<String> roleAuthoritieList = sysRoleList.stream().map(AdminRole::getRoleCode).toList();
|
||||
return new CustomUser(user, AuthorityUtils.createAuthorityList(roleAuthoritieList));
|
||||
}
|
||||
|
||||
/**
|
||||
* 前台用户登录接口
|
||||
*
|
||||
* @param loginDto 登录参数
|
||||
* @return 登录后结果返回
|
||||
*/
|
||||
@Override
|
||||
public LoginVo login(LoginDto loginDto) {
|
||||
return userService.login(loginDto);
|
||||
}
|
||||
}
|
|
@ -21,11 +21,4 @@ public interface UserService extends IService<User> {
|
|||
* @return 登录后结果返回
|
||||
*/
|
||||
LoginVo login(LoginDto loginDto);
|
||||
|
||||
/**
|
||||
* 发送邮箱验证码
|
||||
*
|
||||
* @param email 邮箱
|
||||
*/
|
||||
void sendEmail(String email);
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ import cn.bunny.entity.system.admin.AdminPower;
|
|||
import cn.bunny.entity.system.admin.auth.AuthUserRole;
|
||||
import cn.bunny.entity.system.email.EmailUsers;
|
||||
import cn.bunny.entity.system.user.User;
|
||||
import cn.bunny.module.mail.utils.MailSenderUtil;
|
||||
import cn.bunny.pojo.email.EmailSend;
|
||||
import cn.bunny.pojo.email.EmailSendInit;
|
||||
import cn.bunny.pojo.result.constant.ExceptionConstant;
|
||||
|
@ -90,35 +89,4 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
|
|||
|
||||
return loginVo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送邮箱验证码
|
||||
*
|
||||
* @param email 邮箱
|
||||
*/
|
||||
@Override
|
||||
public void sendEmail(String email) {
|
||||
// 从数据库中获取发送邮箱参数
|
||||
EmailUsers emailUsers = emailUsersMapper.selectOne(Wrappers.<EmailUsers>lambdaQuery().eq(EmailUsers::getIsDefault, 1));
|
||||
EmailSendInit emailSendInit = new EmailSendInit();
|
||||
// 判断发送邮箱邮件是否为空
|
||||
EmptyUtil.isEmpty(emailUsers, MailMessageConstant.EMAIL_CONFIG_NOT_FOUND);
|
||||
BeanUtils.copyProperties(emailUsers, emailSendInit);
|
||||
emailSendInit.setUsername(emailUsers.getEmail());
|
||||
// 生成验证码
|
||||
MailSenderUtil mailSenderUtil = new MailSenderUtil(emailSendInit);
|
||||
CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(150, 48, 4, 2);
|
||||
// 生成验证码和可以
|
||||
String code = captcha.getCode();
|
||||
// 发送验证码
|
||||
EmailSend emailSend = new EmailSend();
|
||||
emailSend.setSubject("邮箱验证码");
|
||||
emailSend.setMessage(code);
|
||||
emailSend.setSendTo(email);
|
||||
emailSend.setIsRichText(false);
|
||||
mailSenderUtil.sendSimpleEmail(emailSend);
|
||||
|
||||
// 将验证码保存到Redis中,并设置15分钟过期
|
||||
redisTemplate.opsForValue().set(RedisUserConstant.ADMIN_EMAIL_CODE_PREFIX + email, code, 15, TimeUnit.MINUTES);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,25 +1,14 @@
|
|||
bunny:
|
||||
datasource:
|
||||
host: 106.15.251.123
|
||||
host: 192.168.3.98
|
||||
port: 3305
|
||||
sqlData: bunny_docs
|
||||
username: root
|
||||
password: "02120212"
|
||||
datasource2:
|
||||
host: 106.15.251.123
|
||||
host: 192.168.3.98
|
||||
port: 3305
|
||||
sqlData: myDS
|
||||
username: root
|
||||
password: "02120212"
|
||||
|
||||
redis:
|
||||
host: 47.120.65.66
|
||||
port: 6379
|
||||
database: 0
|
||||
password: "02120212"
|
||||
|
||||
minio:
|
||||
endpointUrl: "http://116.196.101.14:9000"
|
||||
accessKey: bunny
|
||||
secretKey: "02120212"
|
||||
bucket-name: bunny-bbs
|
|
@ -1,25 +1,13 @@
|
|||
bunny:
|
||||
datasource:
|
||||
host: 106.15.251.123
|
||||
host: 192.168.3.98
|
||||
port: 3306
|
||||
sqlData: bunny_docs
|
||||
username: root
|
||||
password: "02120212"
|
||||
datasource2:
|
||||
host: 106.15.251.123
|
||||
host: 192.168.3.98
|
||||
port: 3305
|
||||
sqlData: myDS
|
||||
username: root
|
||||
password: "02120212"
|
||||
|
||||
redis:
|
||||
host: 47.120.65.66
|
||||
port: 6379
|
||||
database: 0
|
||||
password: "02120212"
|
||||
|
||||
minio:
|
||||
endpointUrl: "http://116.196.101.14:9000"
|
||||
accessKey: bunny
|
||||
secretKey: "02120212"
|
||||
bucket-name: bunny-bbs
|
|
@ -25,19 +25,6 @@ spring:
|
|||
aop:
|
||||
enabled: true
|
||||
|
||||
data:
|
||||
redis:
|
||||
host: ${bunny.redis.host}
|
||||
port: ${bunny.redis.port}
|
||||
database: ${bunny.redis.database}
|
||||
password: ${bunny.redis.password}
|
||||
lettuce:
|
||||
pool:
|
||||
max-active: 20 #最大连接数
|
||||
max-wait: -1 #最大阻塞等待时间(负数表示没限制)
|
||||
max-idle: 5 #最大空闲
|
||||
min-idle: 0 #最小空闲
|
||||
|
||||
jackson:
|
||||
date-format: yyyy-MM-dd HH:mm:ss
|
||||
time-zone: GMT+8
|
||||
|
@ -59,6 +46,7 @@ mybatis-plus:
|
|||
logic-delete-field: isDelete
|
||||
configuration:
|
||||
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 查看日志
|
||||
|
||||
logging:
|
||||
level:
|
||||
cn.bunny.service.mapper: error
|
||||
|
@ -70,20 +58,3 @@ logging:
|
|||
dateformat: HH:mm:ss:SSS
|
||||
file:
|
||||
path: "logs/${spring.application.name}"
|
||||
|
||||
|
||||
bunny:
|
||||
minio:
|
||||
endpointUrl: ${bunny.minio.endpointUrl}
|
||||
accessKey: ${bunny.minio.accessKey}
|
||||
secretKey: ${bunny.minio.secretKey}
|
||||
bucket-name: ${bunny.minio.bucket-name}
|
||||
|
||||
snowflake:
|
||||
datacenterBits: 5 # 数据中心id位数
|
||||
workerBits: 5 # 机器id位数
|
||||
sequenceBits: 12 # 序列id所占位数
|
||||
datacenterId: 1 # 数据中心id,范围0-2^5-1
|
||||
workerId: 1 # 机器id,范围0-2^5-1
|
||||
twepoch: 1704038400000 # 时间戳起始点(2024-01-01 00::00:00 的毫秒数)
|
||||
maxBatchCount: 100000 #单次批量生成id的最大数量 默认10万
|
|
@ -5,7 +5,7 @@ org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDele
|
|||
org.quartz.jobStore.tablePrefix=QRTZ_
|
||||
org.quartz.jobStore.dataSource=myDS
|
||||
org.quartz.dataSource.myDS.driver=com.mysql.cj.jdbc.Driver
|
||||
org.quartz.dataSource.myDS.URL=jdbc:mysql://106.15.251.123:3305/myDS?serverTimezone=GMT%2B8&useSSL=false&characterEncoding=utf-8&allowPublicKeyRetrieval=true
|
||||
org.quartz.dataSource.myDS.URL=jdbc:mysql://192.168.3.98:3305/myDS?serverTimezone=GMT%2B8&useSSL=false&characterEncoding=utf-8&allowPublicKeyRetrieval=true
|
||||
org.quartz.dataSource.myDS.user=root
|
||||
org.quartz.dataSource.myDS.password=02120212
|
||||
org.quartz.dataSource.myDS.maxConnections=5
|
Loading…
Reference in New Issue