diff --git a/pom.xml b/pom.xml
index e275ee6..a694854 100644
--- a/pom.xml
+++ b/pom.xml
@@ -66,6 +66,14 @@
java-jwt
4.3.0
+
+ org.springframework.boot
+ spring-boot-starter-mail
+
+
+ org.springframework.boot
+ spring-boot-starter-amqp
+
org.springframework.security
spring-security-test
diff --git a/src/main/java/com/example/config/RabbitConfiguration.java b/src/main/java/com/example/config/RabbitConfiguration.java
new file mode 100644
index 0000000..7d5f70a
--- /dev/null
+++ b/src/main/java/com/example/config/RabbitConfiguration.java
@@ -0,0 +1,18 @@
+package com.example.config;
+
+import org.springframework.amqp.core.Queue;
+import org.springframework.amqp.core.QueueBuilder;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+
+
+@Configuration
+public class RabbitConfiguration {
+ @Bean("emailQueue")
+ public Queue emailQueue(){
+ return QueueBuilder
+ .durable("mail")
+ .build();
+ }
+}
diff --git a/src/main/java/com/example/controller/AuthorizeController.java b/src/main/java/com/example/controller/AuthorizeController.java
new file mode 100644
index 0000000..81c29f8
--- /dev/null
+++ b/src/main/java/com/example/controller/AuthorizeController.java
@@ -0,0 +1,26 @@
+package com.example.controller;
+
+import com.example.entity.RestBean;
+import com.example.service.AccountService;
+import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletRequest;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/api/auth")
+public class AuthorizeController {
+
+ @Resource
+ AccountService service;
+ @GetMapping("/ask-code")
+ public RestBean askVerifyCode(@RequestParam String email,
+ @RequestParam String type ,
+ HttpServletRequest request){
+ String message = service.registerEmailVerityCode(type , email , request.getRemoteAddr());
+ return message == null ? RestBean.success() : RestBean.failure(400 , message);
+ }
+
+}
diff --git a/src/main/java/com/example/docker-compose.yaml b/src/main/java/com/example/docker-compose.yaml
deleted file mode 100644
index 24943a9..0000000
--- a/src/main/java/com/example/docker-compose.yaml
+++ /dev/null
@@ -1,29 +0,0 @@
-version: '3'
-services:
- nginx:
- image: nginx
- ports:
- - 8888:80
- deploy:
- mode: replicated
- replicas: 3
- visualizer:
- image: dockersamples/visualizer
- ports:
- - 8080:8080
- volumes:
- - /var/run/docker.sock:/var/run/docker.sock
- deploy:
- replicas: 1
- placement:
- constraints: [node.repo == manager]
- portainer:
- image: portainer/portainer
- ports:
- - 9000:9000
- volumes:
- - /var/run/docker.sock:/var/run/docker.sock
- deploy:
- replicas: 1
- placement:
- constraints: [node.role == manager]
\ No newline at end of file
diff --git a/src/main/java/com/example/listener/MailQueueListener.java b/src/main/java/com/example/listener/MailQueueListener.java
new file mode 100644
index 0000000..166662a
--- /dev/null
+++ b/src/main/java/com/example/listener/MailQueueListener.java
@@ -0,0 +1,46 @@
+package com.example.listener;
+
+import jakarta.annotation.Resource;
+import org.springframework.amqp.rabbit.annotation.RabbitHandler;
+import org.springframework.amqp.rabbit.annotation.RabbitListener;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.mail.SimpleMailMessage;
+import org.springframework.mail.javamail.JavaMailSender;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+@Component
+@RabbitListener(queues = "mail")
+public class MailQueueListener {
+ @Resource
+ JavaMailSender sender;
+
+ @Value("${spring.mail.username}")
+ String username;
+
+ @RabbitHandler
+ public void sendMailMessage(Map data){
+ String email = (String) data.get("email");
+ Integer code = (Integer) data.get("code");
+ String type = (String) data.get("type");
+ SimpleMailMessage message = switch (type) {
+ case "register" -> createMessage("欢迎注册我们的网站" ,
+ "您的邮件注册验证码为:" + code + ",有效时间三分钟,为了保障您的安全 , 请勿向他人泄漏验证码信息.", email);
+ case "reset" -> createMessage("你的密码重置邮件" ,
+ "你好,您正在进行重置密码操作,验证码:" + code + ", 有效时间三分钟,如非本人操作,请无视." ,email);
+ default -> null;
+ };
+ if (message == null) return;
+ sender.send(message);
+ }
+
+ private SimpleMailMessage createMessage(String title , String content , String email){
+ SimpleMailMessage message = new SimpleMailMessage();
+ message.setSubject(title);
+ message.setText(content);
+ message.setTo(email);
+ message.setFrom(username);
+ return message;
+ }
+}
diff --git a/src/main/java/com/example/service/AccountService.java b/src/main/java/com/example/service/AccountService.java
index 5cae6c1..5530672 100644
--- a/src/main/java/com/example/service/AccountService.java
+++ b/src/main/java/com/example/service/AccountService.java
@@ -7,4 +7,5 @@ import org.springframework.security.core.userdetails.UserDetailsService;
public interface AccountService extends IService , UserDetailsService {
public Account findAccountByNameOrEmail(String text);
+ String registerEmailVerityCode(String type , String email , String ip);
}
diff --git a/src/main/java/com/example/service/impl/AccountServiceImpl.java b/src/main/java/com/example/service/impl/AccountServiceImpl.java
index fb6df79..7f96166 100644
--- a/src/main/java/com/example/service/impl/AccountServiceImpl.java
+++ b/src/main/java/com/example/service/impl/AccountServiceImpl.java
@@ -4,14 +4,32 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.entity.dto.Account;
import com.example.mapper.AccountMapper;
import com.example.service.AccountService;
+import com.example.utils.Const;
+import com.example.utils.FlowUtils;
+import jakarta.annotation.Resource;
+import org.springframework.amqp.core.AmqpTemplate;
+import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Random;
+import java.util.concurrent.TimeUnit;
+
@Service
public class AccountServiceImpl extends ServiceImpl implements AccountService {
+ @Resource
+ FlowUtils utils;
+ @Resource
+ AmqpTemplate amqpTemplate;
+
+ @Resource
+ StringRedisTemplate stringRedisTemplate;
+
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Account account = this.findAccountByNameOrEmail(username);
@@ -24,10 +42,34 @@ public class AccountServiceImpl extends ServiceImpl imp
.build();
}
+
+ @Override
+ public String registerEmailVerityCode(String type, String email, String ip) {
+ synchronized (ip.intern()){
+ if (this.verifyLimit(ip)){
+ return "请求频繁,请稍后再试";
+ }
+ Random random = new Random();
+ int code = random.nextInt(899999) + 100000;
+ Map data = Map.of("type" , type , "email", email , "code" , code);
+ amqpTemplate.convertAndSend("mail" , data);
+ stringRedisTemplate.opsForValue()
+ .set(Const.VERIFY_EMAIL_DATA + email ,String.valueOf(code), 3 , TimeUnit.MINUTES );
+ return null;
+ }
+
+
+ }
+
public Account findAccountByNameOrEmail(String text){
return this.query()
.eq("username",text).or()
.eq("email",text)
.one();
}
+
+ private boolean verifyLimit(String ip){
+ String key = Const.VERIFY_EMAIL_LIMIT + ip;
+ return utils.limitOnceCheck(key , 60);
+ }
}
diff --git a/src/main/java/com/example/utils/Const.java b/src/main/java/com/example/utils/Const.java
index 1d743e2..e60413f 100644
--- a/src/main/java/com/example/utils/Const.java
+++ b/src/main/java/com/example/utils/Const.java
@@ -3,6 +3,9 @@ package com.example.utils;
public class Const {
public static final String JWT_BLACK_LIST = "jwt:blacklist:";
+ public static final String VERIFY_EMAIL_LIMIT = "verify:email:limit:";
+ public static final String VERIFY_EMAIL_DATA = "verify:email:data:";
+
public static final int ORDER_CORS = -102;
}
diff --git a/src/main/java/com/example/utils/FlowUtils.java b/src/main/java/com/example/utils/FlowUtils.java
new file mode 100644
index 0000000..4714127
--- /dev/null
+++ b/src/main/java/com/example/utils/FlowUtils.java
@@ -0,0 +1,22 @@
+package com.example.utils;
+
+import jakarta.annotation.Resource;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.stereotype.Component;
+
+import java.util.concurrent.TimeUnit;
+
+@Component
+public class FlowUtils {
+ @Resource
+ StringRedisTemplate template;
+
+ public boolean limitOnceCheck(String key , int blockTime){
+ if (Boolean.TRUE.equals(template.hasKey(key))){
+ return false;
+ }else {
+ template.opsForValue().set(key , "" , blockTime , TimeUnit.SECONDS);
+ return true;
+ }
+ }
+}
diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml
index b2617ed..c67296d 100644
--- a/src/main/resources/application.yaml
+++ b/src/main/resources/application.yaml
@@ -1,5 +1,15 @@
spring:
+ mail:
+ host: smtp.163.com
+ username: realmeamadeus@163.com
+ password: SFTIRQAPGTZJFEPY
+ rabbitmq:
+ addresses: 8.138.140.94
+ username: rabbitmq
+ password: rabbitmq_Ek=hv-W0
+ virtual-host: /
+ port: 5672
security:
filter:
order: -100 #默认值为-100