diff --git a/.idea/CoolRequestCommonStatePersistent.xml b/.idea/CoolRequestCommonStatePersistent.xml index e2e9036..9b96684 100644 --- a/.idea/CoolRequestCommonStatePersistent.xml +++ b/.idea/CoolRequestCommonStatePersistent.xml @@ -1,6 +1,6 @@ - \ No newline at end of file diff --git a/aioj-backend-auth/src/main/java/cn/meowrain/aioj/backend/auth/config/SecurityConfiguration.java b/aioj-backend-auth/src/main/java/cn/meowrain/aioj/backend/auth/config/SecurityConfiguration.java index 21fffc1..a8c787d 100644 --- a/aioj-backend-auth/src/main/java/cn/meowrain/aioj/backend/auth/config/SecurityConfiguration.java +++ b/aioj-backend-auth/src/main/java/cn/meowrain/aioj/backend/auth/config/SecurityConfiguration.java @@ -27,7 +27,7 @@ public class SecurityConfiguration { .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .authorizeHttpRequests(auth -> auth .requestMatchers("/v1/auth/**", "/oauth2/**", "/.well-known/**", "/doc.html", "/swagger-ui/**", - "/swagger-resources/**", "/webjars/**", "/v3/api-docs/**", "/v3/api-docs", "/favicon.ico") + "/swagger-resources/**", "/webjars/**", "/v3/api-docs/**", "/v3/api-docs", "/favicon.ico","/v1/user/email/send-code") .permitAll() .anyRequest() .authenticated()) diff --git a/aioj-backend-common/aioj-backend-common-core/pom.xml b/aioj-backend-common/aioj-backend-common-core/pom.xml index b9055e7..23cbba8 100644 --- a/aioj-backend-common/aioj-backend-common-core/pom.xml +++ b/aioj-backend-common/aioj-backend-common-core/pom.xml @@ -67,5 +67,11 @@ org.springframework.boot spring-boot-autoconfigure + + + org.springframework.boot + spring-boot-starter-security + true + \ No newline at end of file diff --git a/aioj-backend-common/aioj-backend-common-core/src/main/java/cn/meowrain/aioj/backend/framework/core/utils/ContextHolderUtils.java b/aioj-backend-common/aioj-backend-common-core/src/main/java/cn/meowrain/aioj/backend/framework/core/utils/ContextHolderUtils.java new file mode 100644 index 0000000..6c5ec09 --- /dev/null +++ b/aioj-backend-common/aioj-backend-common-core/src/main/java/cn/meowrain/aioj/backend/framework/core/utils/ContextHolderUtils.java @@ -0,0 +1,87 @@ +package cn.meowrain.aioj.backend.framework.core.utils; + +import lombok.experimental.UtilityClass; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; + +/** + * Security Context 工具类 + * 用于获取当前登录用户信息 + */ +@Slf4j +@UtilityClass +public class ContextHolderUtils { + + /** + * 获取当前登录用户ID + * @return 用户ID + * @throws IllegalStateException 如果用户未登录 + */ + public static Long getCurrentUserId() { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + + if (authentication == null || !authentication.isAuthenticated()) { + throw new IllegalStateException("用户未登录"); + } + + String userId = authentication.getName(); + try { + return Long.valueOf(userId); + } + catch (NumberFormatException e) { + log.error("解析用户ID失败: {}", userId, e); + throw new IllegalStateException("无效的用户ID"); + } + } + + /** + * 获取当前登录用户ID(可选返回) + * @return 用户ID,未登录返回 null + */ + public static Long getCurrentUserIdOrNull() { + try { + return getCurrentUserId(); + } + catch (Exception e) { + return null; + } + } + + /** + * 获取当前登录用户角色 + * @return 用户角色,如 "USER", "ADMIN", "BAN" + */ + public static String getCurrentUserRole() { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + + if (authentication == null || !authentication.isAuthenticated()) { + throw new IllegalStateException("用户未登录"); + } + + return authentication.getAuthorities() + .stream() + .findFirst() + .map(authority -> authority.getAuthority().replace("ROLE_", "")) + .orElse("USER"); + } + + /** + * 判断当前用户是否已登录 + * @return true-已登录, false-未登录 + */ + public static boolean isAuthenticated() { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + return authentication != null && authentication.isAuthenticated() + && !"anonymousUser".equals(authentication.getName()); + } + + /** + * 判断当前用户是否为管理员 + * @return true-是管理员, false-不是管理员 + */ + public static boolean isAdmin() { + return "ADMIN".equals(getCurrentUserRole()); + } + +} diff --git a/aioj-backend-user-service/pom.xml b/aioj-backend-user-service/pom.xml index 3a2924d..7b0d2fe 100644 --- a/aioj-backend-user-service/pom.xml +++ b/aioj-backend-user-service/pom.xml @@ -18,6 +18,11 @@ + + + org.springframework.boot + spring-boot-starter-mail + org.springdoc diff --git a/aioj-backend-user-service/src/main/java/cn/meowrain/aioj/backend/userservice/config/FrameworkConfiguration.java b/aioj-backend-user-service/src/main/java/cn/meowrain/aioj/backend/userservice/config/FrameworkConfiguration.java index e6c4689..c1ad9f3 100644 --- a/aioj-backend-user-service/src/main/java/cn/meowrain/aioj/backend/userservice/config/FrameworkConfiguration.java +++ b/aioj-backend-user-service/src/main/java/cn/meowrain/aioj/backend/userservice/config/FrameworkConfiguration.java @@ -1,8 +1,44 @@ package cn.meowrain.aioj.backend.userservice.config; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mail.javamail.JavaMailSenderImpl; + +import java.util.Properties; @Configuration public class FrameworkConfiguration { + @Value("${spring.mail.host}") + private String mailHost; + + @Value("${spring.mail.port}") + private Integer mailPort; + + @Value("${spring.mail.username}") + private String mailUsername; + + @Value("${spring.mail.password}") + private String mailPassword; + + @Bean + public JavaMailSender javaMailSender() { + JavaMailSenderImpl mailSender = new JavaMailSenderImpl(); + mailSender.setHost(mailHost); + mailSender.setPort(mailPort); + mailSender.setUsername(mailUsername); + mailSender.setPassword(mailPassword); + + Properties props = mailSender.getJavaMailProperties(); + props.put("mail.transport.protocol", "smtp"); + props.put("mail.smtp.auth", "true"); + props.put("mail.smtp.ssl.enable", "true"); + props.put("mail.smtp.starttls.enable", "true"); + props.put("mail.debug", "false"); + + return mailSender; + } + } diff --git a/aioj-backend-user-service/src/main/java/cn/meowrain/aioj/backend/userservice/controller/UserController.java b/aioj-backend-user-service/src/main/java/cn/meowrain/aioj/backend/userservice/controller/UserController.java index 6a8c178..104ab4e 100644 --- a/aioj-backend-user-service/src/main/java/cn/meowrain/aioj/backend/userservice/controller/UserController.java +++ b/aioj-backend-user-service/src/main/java/cn/meowrain/aioj/backend/userservice/controller/UserController.java @@ -2,35 +2,76 @@ package cn.meowrain.aioj.backend.userservice.controller; import cn.meowrain.aioj.backend.framework.core.web.Result; import cn.meowrain.aioj.backend.framework.core.web.Results; +import cn.meowrain.aioj.backend.userservice.dto.req.EmailSendCodeRequestDTO; import cn.meowrain.aioj.backend.userservice.dto.req.UserRegisterRequestDTO; import cn.meowrain.aioj.backend.userservice.dto.resp.UserAuthRespDTO; import cn.meowrain.aioj.backend.userservice.service.UserService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; @RequiredArgsConstructor @RestController() @RequestMapping("/v1/user") +@Tag(name = "用户管理", description = "用户注册、查询等接口") public class UserController { - private final UserService userService; + private final UserService userService; - @PostMapping("/register") - public Result register(@RequestBody UserRegisterRequestDTO userRegisterRequest) { - Long l = userService.userRegister(userRegisterRequest); - return Results.success(l); - } - @GetMapping("/inner/get-by-username") - public Result getUserByUserName(@RequestParam("userAccount") String userAccount) { - UserAuthRespDTO userAuthDTO = userService.findAuthInfoByUserAccount(userAccount); - return Results.success(userAuthDTO); - } + @PostMapping("/register") + @Operation(summary = "用户注册", description = "根据用户注册信息创建新用户") + public Result register( + @Parameter(description = "用户注册信息", required = true) + @RequestBody UserRegisterRequestDTO userRegisterRequest) { + Long l = userService.userRegister(userRegisterRequest); + return Results.success(l); + } - @GetMapping("/inner/get-by-userid") - public Result getUserById(@RequestParam("userId") String userid) { - UserAuthRespDTO userAuthRespDTO = userService.findAuthInfoByUserId(userid); - return Results.success(userAuthRespDTO); - } + @GetMapping("/inner/get-by-username") + @Operation(summary = "根据用户名查询用户", description = "通过用户账号获取用户认证信息(内部接口)") + public Result getUserByUserName( + @Parameter(description = "用户账号", required = true, example = "admin") + @RequestParam("userAccount") String userAccount) { + UserAuthRespDTO userAuthDTO = userService.findAuthInfoByUserAccount(userAccount); + return Results.success(userAuthDTO); + } + @GetMapping("/inner/get-by-userid") + @Operation(summary = "根据用户ID查询用户", description = "通过用户ID获取用户认证信息(内部接口)") + public Result getUserById( + @Parameter(description = "用户ID", required = true, example = "1") + @RequestParam("userId") String userid) { + UserAuthRespDTO userAuthRespDTO = userService.findAuthInfoByUserId(userid); + return Results.success(userAuthRespDTO); + } + /* ================================邮箱相关接口 ======================*/ + + /** + * 发送验证码 + */ + @GetMapping("/email/send-code") + public Result getVerifyCode(@Parameter(description = "邮箱信息", required = true) + @Valid @RequestParam EmailSendCodeRequestDTO request) { + userService.sendEmailCode(request.getEmail()); + return Results.success(null); + } + + /** + * 绑定邮箱 + */ + @PostMapping("/email/bind") + public Result bindEmail(@RequestBody String email) { +// TODO: 待实现 + return null; + } + + @PostMapping("/email/unbind") + public Result unbindEmail() { +// TODO: 待实现 + return null; + } } diff --git a/aioj-backend-user-service/src/main/java/cn/meowrain/aioj/backend/userservice/dao/entity/User.java b/aioj-backend-user-service/src/main/java/cn/meowrain/aioj/backend/userservice/dao/entity/User.java index 96ee516..f8783e1 100644 --- a/aioj-backend-user-service/src/main/java/cn/meowrain/aioj/backend/userservice/dao/entity/User.java +++ b/aioj-backend-user-service/src/main/java/cn/meowrain/aioj/backend/userservice/dao/entity/User.java @@ -12,70 +12,80 @@ import java.util.Date; @Accessors(chain = true) public class User implements Serializable { - /** - * id - */ - @TableId(type = IdType.ASSIGN_ID) - private Long id; + /** + * id + */ + @TableId(type = IdType.ASSIGN_ID) + private Long id; - /** - * 用户账号 - */ - private String userAccount; + /** + * 用户账号 + */ + private String userAccount; - /** - * 用户密码 - */ - private String userPassword; + /** + * 用户密码 + */ + private String userPassword; - /** - * 开放平台id - */ - private String unionId; + /** + * 开放平台id + */ + private String unionId; - /** - * 公众号openId - */ - private String mpOpenId; + /** + * 公众号openId + */ + private String mpOpenId; - /** - * 用户昵称 - */ - private String userName; + /** + * 用户昵称 + */ + private String userName; - /** - * 用户头像 - */ - private String userAvatar; + /** + * 用户头像 + */ + private String userAvatar; - /** - * 用户简介 - */ - private String userProfile; + /** + * 用户简介 + */ + private String userProfile; - /** - * 用户角色:user/admin/ban - */ - private String userRole; + /** + * 用户角色:user/admin/ban + */ + private String userRole; - /** - * 创建时间 - */ - @TableField(fill = FieldFill.INSERT) - private Date createTime; + /** + * 用户邮箱 + */ + private String userEmail; - /** - * 更新时间 - */ - private Date updateTime; + /** + * 用户邮箱是否验证 0 未验证 1已验证 + */ + private Integer userEmailVerified; - /** - * 是否删除 - */ - @TableLogic - private Integer isDelete; + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private Date createTime; - @TableField(exist = false) - private static final long serialVersionUID = 1L; + /** + * 更新时间 + */ + private Date updateTime; + + /** + * 是否删除 + */ + @TableLogic + private Integer isDelete; + + @TableField(exist = false) + private static final long serialVersionUID = 1L; } diff --git a/aioj-backend-user-service/src/main/java/cn/meowrain/aioj/backend/userservice/dto/req/EmailSendCodeRequestDTO.java b/aioj-backend-user-service/src/main/java/cn/meowrain/aioj/backend/userservice/dto/req/EmailSendCodeRequestDTO.java new file mode 100644 index 0000000..a1698ed --- /dev/null +++ b/aioj-backend-user-service/src/main/java/cn/meowrain/aioj/backend/userservice/dto/req/EmailSendCodeRequestDTO.java @@ -0,0 +1,15 @@ +package cn.meowrain.aioj.backend.userservice.dto.req; + +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +/** + * 用户注册的邮箱 请求对象 + */ +@Data +public class EmailSendCodeRequestDTO { + @NotNull + @Email + String email; +} diff --git a/aioj-backend-user-service/src/main/java/cn/meowrain/aioj/backend/userservice/dto/resp/UserAuthRespDTO.java b/aioj-backend-user-service/src/main/java/cn/meowrain/aioj/backend/userservice/dto/resp/UserAuthRespDTO.java index b9de0b5..b855727 100644 --- a/aioj-backend-user-service/src/main/java/cn/meowrain/aioj/backend/userservice/dto/resp/UserAuthRespDTO.java +++ b/aioj-backend-user-service/src/main/java/cn/meowrain/aioj/backend/userservice/dto/resp/UserAuthRespDTO.java @@ -1,5 +1,6 @@ package cn.meowrain.aioj.backend.userservice.dto.resp; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.util.Date; @@ -8,61 +9,85 @@ import java.util.Date; * 用户认证响应体 */ @Data +@Schema(description = "用户认证响应体") public class UserAuthRespDTO { /** * id */ + @Schema(description = "用户ID", example = "1") private Long id; /** * 用户账号 */ + @Schema(description = "用户账号", example = "admin") private String userAccount; /** * 用户密码 */ + @Schema(description = "用户密码", example = "123456") private String userPassword; /** * 开放平台id */ + @Schema(description = "开放平台ID", example = "wx_union_id_123") private String unionId; /** * 公众号openId */ + @Schema(description = "公众号OpenID", example = "wx_openid_123") private String mpOpenId; /** * 用户昵称 */ + @Schema(description = "用户昵称", example = "张三") private String userName; /** * 用户头像 */ + @Schema(description = "用户头像URL", example = "https://example.com/avatar.jpg") private String userAvatar; /** * 用户简介 */ + @Schema(description = "用户简介", example = "这是我的个人简介") private String userProfile; /** * 用户角色:user/admin/ban */ + @Schema(description = "用户角色", example = "user", allowableValues = {"user", "admin", "ban"}) private String userRole; + /** + * 用户邮箱 + */ + @Schema(description = "用户邮箱", example = "user@example.com") + private String userEmail; + + /** + * 用户邮箱是否验证 0 未验证 1已验证 + */ + @Schema(description = "用户邮箱是否验证", example = "1", allowableValues = {"0", "1"}) + private Integer userEmailVerified; + /** * 创建时间 */ + @Schema(description = "创建时间", example = "2025-01-01T00:00:00") private Date createTime; /** * 更新时间 */ + @Schema(description = "更新时间", example = "2025-01-01T12:00:00") private Date updateTime; } diff --git a/aioj-backend-user-service/src/main/java/cn/meowrain/aioj/backend/userservice/service/EmailService.java b/aioj-backend-user-service/src/main/java/cn/meowrain/aioj/backend/userservice/service/EmailService.java new file mode 100644 index 0000000..f1e74c7 --- /dev/null +++ b/aioj-backend-user-service/src/main/java/cn/meowrain/aioj/backend/userservice/service/EmailService.java @@ -0,0 +1,13 @@ +package cn.meowrain.aioj.backend.userservice.service; + +/** + * 邮件服务接口 + */ +public interface EmailService { + + /** + * 发送邮箱验证码 + * @param email 收件人邮箱 + */ + void sendVerifyCode(String email); +} diff --git a/aioj-backend-user-service/src/main/java/cn/meowrain/aioj/backend/userservice/service/UserService.java b/aioj-backend-user-service/src/main/java/cn/meowrain/aioj/backend/userservice/service/UserService.java index 0cf1468..6920063 100644 --- a/aioj-backend-user-service/src/main/java/cn/meowrain/aioj/backend/userservice/service/UserService.java +++ b/aioj-backend-user-service/src/main/java/cn/meowrain/aioj/backend/userservice/service/UserService.java @@ -28,4 +28,19 @@ public interface UserService extends IService { */ UserAuthRespDTO findAuthInfoByUserId(String userId); + + /** + * 发送邮箱验证码 + */ + void sendEmailCode(String email); + + /** + * 绑定邮箱 + */ + void bindEmail(String email, String code); + + /** + * 解绑邮箱 + */ + void unbindEmail(Long userId); } diff --git a/aioj-backend-user-service/src/main/java/cn/meowrain/aioj/backend/userservice/service/impl/EmailServiceImpl.java b/aioj-backend-user-service/src/main/java/cn/meowrain/aioj/backend/userservice/service/impl/EmailServiceImpl.java new file mode 100644 index 0000000..80d90c5 --- /dev/null +++ b/aioj-backend-user-service/src/main/java/cn/meowrain/aioj/backend/userservice/service/impl/EmailServiceImpl.java @@ -0,0 +1,124 @@ +package cn.meowrain.aioj.backend.userservice.service.impl; + +import cn.meowrain.aioj.backend.framework.core.exception.ServiceException; +import cn.meowrain.aioj.backend.userservice.common.constants.RedisKeyConstants; +import cn.meowrain.aioj.backend.userservice.service.EmailService; +import jakarta.mail.MessagingException; +import jakarta.mail.internet.MimeMessage; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mail.javamail.MimeMessageHelper; +import org.springframework.stereotype.Service; + +import java.security.SecureRandom; +import java.util.concurrent.TimeUnit; + +/** + * 邮件服务实现 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class EmailServiceImpl implements EmailService { + + private final JavaMailSender mailSender; + + private final StringRedisTemplate redisTemplate; + + @Value("${spring.mail.username}") + private String FROM_EMAIL; + + private static final String SUBJECT = "【AIOJ】邮箱验证码"; + + + private static final int CODE_LENGTH = 6; + + /** + * 生成6位随机验证码 + */ + private String generateCode() { + SecureRandom random = new SecureRandom(); + StringBuilder stringBuilder = new StringBuilder(); + for (int i = 0; i < CODE_LENGTH; i++) { + stringBuilder.append(random.nextInt(10)); + } + return stringBuilder.toString(); + } + /** + * 构建邮件内容 + */ + private String buildEmailContent(String code) { + return String.format(""" + + + + + + +
+ + + + + + + + + + + + +
+

AIOJ 邮箱验证

+
+

您好,

+

您正在进行邮箱安全校验,为保障账户安全,请使用以下验证码:

+ +
+ %s +
+ +

验证码有效期为 1 分钟,请尽快完成操作。

+

若非本人操作,请忽略本邮件。

+
+

此邮件由系统自动发送,请勿回复

+

AIOJ © %s All Rights Reserved.

+
+
+ + + """, code, java.time.Year.now()); + } + + + @Override + public void sendVerifyCode(String email) { + // 生成验证码 + String code = generateCode(); + // 验证码存redis里面,1分钟过期时间 + String redisKey = String.format(RedisKeyConstants.EMAIL_CODE_PREFIX,email); + redisTemplate.opsForValue().set(redisKey,code,RedisKeyConstants.EMAIL_CODE_TTL,TimeUnit.SECONDS); + + // 发送邮件 + try { + MimeMessage message = mailSender.createMimeMessage(); + // ⭐ 显式指定 UTF-8 编码,解决中文乱码问题 + MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8"); + helper.setFrom(FROM_EMAIL); + helper.setTo(email); + helper.setSubject(SUBJECT); + helper.setText(buildEmailContent(code), true); + + // ⭐ 发送邮件 + mailSender.send(message); + log.info("验证码邮件发送成功: 邮箱={}, 验证码={}", email, code); + }catch (MessagingException e) { + log.error("验证码邮件发送失败: 邮箱={}", email, e); + throw new ServiceException("邮件发送失败,请稍后重试"); + } + } + +} diff --git a/aioj-backend-user-service/src/main/java/cn/meowrain/aioj/backend/userservice/service/impl/UserServiceImpl.java b/aioj-backend-user-service/src/main/java/cn/meowrain/aioj/backend/userservice/service/impl/UserServiceImpl.java index c5aabe2..9b96c92 100644 --- a/aioj-backend-user-service/src/main/java/cn/meowrain/aioj/backend/userservice/service/impl/UserServiceImpl.java +++ b/aioj-backend-user-service/src/main/java/cn/meowrain/aioj/backend/userservice/service/impl/UserServiceImpl.java @@ -4,6 +4,7 @@ import cn.hutool.crypto.digest.BCrypt; import cn.meowrain.aioj.backend.framework.core.errorcode.ErrorCode; import cn.meowrain.aioj.backend.framework.core.exception.ClientException; import cn.meowrain.aioj.backend.framework.core.exception.ServiceException; +import cn.meowrain.aioj.backend.framework.core.utils.ContextHolderUtils; import cn.meowrain.aioj.backend.userservice.common.enums.ChainMarkEnums; import cn.meowrain.aioj.backend.userservice.dao.entity.User; import cn.meowrain.aioj.backend.userservice.dao.mapper.UserMapper; @@ -11,6 +12,7 @@ import cn.meowrain.aioj.backend.userservice.dto.chains.context.UserRegisterReque import cn.meowrain.aioj.backend.userservice.dto.req.UserRegisterRequestDTO; import cn.meowrain.aioj.backend.userservice.dto.resp.UserAuthRespDTO; +import cn.meowrain.aioj.backend.userservice.service.EmailService; import cn.meowrain.aioj.backend.userservice.service.UserService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import lombok.RequiredArgsConstructor; @@ -28,6 +30,8 @@ public class UserServiceImpl extends ServiceImpl implements Us private final UserRegisterRequestParamVerifyContext userRegisterRequestParamVerifyContext; + private final EmailService emailService; + @Override public Long userRegister(UserRegisterRequestDTO request) { UserAuthRespDTO authInfoByUserAccount = findAuthInfoByUserAccount(request.getUserAccount()); @@ -82,4 +86,21 @@ public class UserServiceImpl extends ServiceImpl implements Us } + @Override + public void sendEmailCode(String email) { + emailService.sendVerifyCode(email); + } + + @Override + public void bindEmail(String email, String code) { + Long currentUserId = ContextHolderUtils.getCurrentUserId(); + + + } + + @Override + public void unbindEmail(Long userId) { + + } + } diff --git a/aioj-backend-user-service/src/main/resources/application-dev.yml b/aioj-backend-user-service/src/main/resources/application-dev.yml index 019d5c9..9448ab5 100644 --- a/aioj-backend-user-service/src/main/resources/application-dev.yml +++ b/aioj-backend-user-service/src/main/resources/application-dev.yml @@ -1,4 +1,20 @@ spring: + mail: + host: smtp.qq.com + port: 465 + username: 2705356115@qq.com + # 这里使用授权码 + password: yohcndfrlxwcdfed + default-encoding: UTF-8 + protocol: smtp + properties: + mail: + smtp: + ssl: + enable: true # 在 properties 中明确指定 + auth: true + starttls: + enable: true # QQ邮箱也支持STARTTLS,但使用465端口时,ssl.enable=true是必须的 data: redis: host: 10.0.0.10