diff --git a/.idea/.cache/.Apifox_Helper/.toolWindow.db b/.idea/.cache/.Apifox_Helper/.toolWindow.db index 18564a9..096b99b 100644 Binary files a/.idea/.cache/.Apifox_Helper/.toolWindow.db and b/.idea/.cache/.Apifox_Helper/.toolWindow.db differ diff --git a/pom.xml b/pom.xml index 63cf238..50bce6a 100644 --- a/pom.xml +++ b/pom.xml @@ -1,5 +1,5 @@ - 4.0.0 com.vv.pk.assistant @@ -102,6 +102,48 @@ 5.6.227 + + + com.mailgun + mailgun-java + 2.0.0 + + + + + com.github.ben-manes.caffeine + caffeine + 2.9.3 + + + org.springframework.boot + spring-boot-starter-cache + + + + + org.springframework.security + spring-security-crypto + 5.5.1 + + + + + cn.dev33 + sa-token-spring-boot-starter + 1.44.0 + + + + + cn.hutool + hutool-all + 5.8.38 + + + + + diff --git a/src/main/java/vvpkassistant/Tools/BcryptUtils.java b/src/main/java/vvpkassistant/Tools/BcryptUtils.java new file mode 100644 index 0000000..d85f001 --- /dev/null +++ b/src/main/java/vvpkassistant/Tools/BcryptUtils.java @@ -0,0 +1,22 @@ +package vvpkassistant.Tools; + +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; + +/* + * @author: ziin + * @date: 2025/8/4 18:19 + */ +public class BcryptUtils { + + + + public static String encryptPassword(String password) { + BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); + return passwordEncoder.encode(password); + } + + public static Boolean matchPassword(String rawPassWord,String encodePassword){ + BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); + return passwordEncoder.matches(encodePassword, rawPassWord); + } +} diff --git a/src/main/java/vvpkassistant/User/controller/UserController.java b/src/main/java/vvpkassistant/User/controller/UserController.java index 77a12f1..7fd31c9 100644 --- a/src/main/java/vvpkassistant/User/controller/UserController.java +++ b/src/main/java/vvpkassistant/User/controller/UserController.java @@ -1,4 +1,5 @@ package vvpkassistant.User.controller; +import cn.dev33.satoken.stp.StpUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import vvpkassistant.CoinRecords.CoinRecords; @@ -7,16 +8,23 @@ import vvpkassistant.Data.ResponseData; import vvpkassistant.Data.ResponseInfo; import vvpkassistant.Data.WxChatParam; import vvpkassistant.User.mapper.UserDao; +import vvpkassistant.User.model.DTO.UserModelDTO; import vvpkassistant.User.model.UserModel; +import vvpkassistant.User.model.UserModelVO; +import vvpkassistant.User.service.UserService; import vvpkassistant.common.ErrorCode; import vvpkassistant.config.FunctionConfigHolder; import vvpkassistant.Tools.VVRequester; import vvpkassistant.Tools.VVTools; import vvpkassistant.exception.BusinessException; +import vvpkassistant.mail.model.MailModel; +import vvpkassistant.mail.service.MailService; import vvpkassistant.pk.mapper.PkInfoDao; import vvpkassistant.pk.model.PkInfoModel; import vvpkassistant.pk.model.PkRecordDetail; import vvpkassistant.pk.mapper.PkRecordDetailDao; + +import javax.annotation.Resource; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -43,6 +51,10 @@ public class UserController { @Autowired private VVRequester vvRequester; + + @Resource + private UserService userService; + // 配置用户信息 @PostMapping("inputUserInfo") public ResponseData inputUserInfo(@RequestBody Map param) { @@ -165,29 +177,12 @@ public class UserController { } - //todo 修改用户返回结果 // 修改用户信息 @PostMapping("updateUserInfo") - public ResponseData updateUserInfo(@RequestBody Map map) { - UserModel userModel = new UserModel(); - //设置用户id - userModel.setId(Integer.valueOf(map.get("id").toString())); - //设置用户头像 - userModel.setHeaderIcon(map.get("headerIcon").toString()); - //设置用户昵称 - userModel.setNickName(map.get("nickName").toString()); - - int i = userDao.updateById(userModel); - // 返回结果 - Map result = new HashMap<>(); - result.put("info", userDao.selectById(map.get("id").toString())); - result.put("newAccount", false); - if (i == 1){ - return ResponseData.success(result); - }else { - throw new BusinessException(ErrorCode.SYSTEM_ERROR); - } + public ResponseData updateUserInfo(@RequestBody UserModelDTO userModelDTO) { + UserModelVO userModelVO = userService.updateUserInfo( userModelDTO); + return ResponseData.success(userModelVO); } // 获取用户信息 @@ -367,5 +362,13 @@ public class UserController { return ResponseData.success(coinRecords); } + @PostMapping("/loginWithMail") + public ResponseData loginWithMail(@RequestBody UserModelDTO model) { + return ResponseData.success(userService.loginWithMail(model)); + } + @PostMapping("/registerWithMail") + public ResponseData mailRegister(@RequestBody UserModelDTO model){ + return ResponseData.success(userService.addUserWithMail(model)); + } } diff --git a/src/main/java/vvpkassistant/User/model/DTO/UserModelDTO.java b/src/main/java/vvpkassistant/User/model/DTO/UserModelDTO.java new file mode 100644 index 0000000..20a54bb --- /dev/null +++ b/src/main/java/vvpkassistant/User/model/DTO/UserModelDTO.java @@ -0,0 +1,28 @@ +package vvpkassistant.User.model.DTO; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +@Data + +public class UserModelDTO { + @TableId(type = IdType.AUTO) + private Integer id; // 主键 + private String nickName; // 昵称 + private String phoneNumber; // 手机号码 + private String headerIcon; // 头像 + private String openid; // openid + private String sessionKey; // session key + private Integer status; // 用户状态 0 正常 其他业务逻辑待定 + private Long createTime; // 创建时间 + private String userChatId; // 聊天使用的id,使用微信的openid作为标识 + private Integer points; // 用户积分 + private Integer inviterId; // 邀请人id + private String email; + private String newPassword; + private String oldPassword; + private String password; + +} diff --git a/src/main/java/vvpkassistant/User/model/UserModel.java b/src/main/java/vvpkassistant/User/model/UserModel.java index 8a0de0c..6ad2e58 100644 --- a/src/main/java/vvpkassistant/User/model/UserModel.java +++ b/src/main/java/vvpkassistant/User/model/UserModel.java @@ -20,4 +20,7 @@ public class UserModel { private String userChatId; // 聊天使用的id,使用微信的openid作为标识 private Integer points; // 用户积分 private Integer inviterId; // 邀请人id + private String email; + private String password; + } diff --git a/src/main/java/vvpkassistant/User/model/UserModelVO.java b/src/main/java/vvpkassistant/User/model/UserModelVO.java new file mode 100644 index 0000000..927a9e2 --- /dev/null +++ b/src/main/java/vvpkassistant/User/model/UserModelVO.java @@ -0,0 +1,26 @@ +package vvpkassistant.User.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import vvpkassistant.Data.WxChatParam; + +@Data +public class UserModelVO { + private Integer id; // 主键 + private String nickName; // 昵称 + private String phoneNumber; // 手机号码 + private String headerIcon; // 头像 + private String openid; // openid + private String sessionKey; // session key + private Integer status; // 用户状态 0 正常 其他业务逻辑待定 + private Long createTime; // 创建时间 + private String userChatId; // 聊天使用的id,使用微信的openid作为标识 + private Integer points; // 用户积分 + private Integer inviterId; // 邀请人id + private String email; + private String token; + private Boolean newAccount; + private WxChatParam chatInfo; +} diff --git a/src/main/java/vvpkassistant/User/service/UserService.java b/src/main/java/vvpkassistant/User/service/UserService.java new file mode 100644 index 0000000..95a6448 --- /dev/null +++ b/src/main/java/vvpkassistant/User/service/UserService.java @@ -0,0 +1,20 @@ +package vvpkassistant.User.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import vvpkassistant.User.model.DTO.UserModelDTO; +import vvpkassistant.User.model.UserModel; +import vvpkassistant.User.model.UserModelVO; + + + +/* + * @author: ziin + * @date: 2025/8/4 16:19 + */ +public interface UserService extends IService { + UserModelVO loginWithMail(UserModelDTO model); + + UserModelVO updateUserInfo(UserModelDTO userModelDTO); + + UserModelVO addUserWithMail(UserModelDTO model); +} diff --git a/src/main/java/vvpkassistant/User/service/UserServiceImpl.java b/src/main/java/vvpkassistant/User/service/UserServiceImpl.java new file mode 100644 index 0000000..5a44092 --- /dev/null +++ b/src/main/java/vvpkassistant/User/service/UserServiceImpl.java @@ -0,0 +1,128 @@ +package vvpkassistant.User.service; + +import cn.dev33.satoken.stp.StpUtil; +import cn.hutool.core.bean.BeanUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import vvpkassistant.Data.WxChatParam; +import vvpkassistant.Tools.BcryptUtils; +import vvpkassistant.Tools.VVTools; +import vvpkassistant.User.mapper.UserDao; +import vvpkassistant.User.model.DTO.UserModelDTO; +import vvpkassistant.User.model.UserModel; +import vvpkassistant.User.model.UserModelVO; +import vvpkassistant.common.ErrorCode; +import vvpkassistant.exception.BusinessException; +import vvpkassistant.mail.model.MailModel; + +import javax.annotation.Resource; + +/* + * @author: ziin + * @date: 2025/8/4 16:19 + */ +@Service +public class UserServiceImpl extends ServiceImpl implements UserService { + + @Resource + private UserDao userDao; + + @Resource + private WxChatParam wxChatParam; + + @Override + public UserModelVO loginWithMail(UserModelDTO model) { + + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(UserModel::getEmail,model.getEmail()) + .in(UserModel::getStatus, 0,2); + + UserModel userModel = userDao.selectOne(lambdaQueryWrapper); + if (userModel == null) { + throw new BusinessException(ErrorCode.USER_DOES_NOT_EXIST); + } + + String password = userModel.getPassword(); + UserModelVO userModelVO = BeanUtil.copyProperties(userModel, UserModelVO.class); + if (BcryptUtils.matchPassword(password, model.getPassword())) { + StpUtil.login(userModel.getId()); + userModelVO.setToken(StpUtil.getTokenValue()); + userModelVO.setChatInfo(wxChatParam); + return userModelVO; + }else { + throw new BusinessException(ErrorCode.PASSWORD_ERROR); + } + } + + @Override + public UserModelVO updateUserInfo(UserModelDTO userModelDTO) { + + UserModel userInfo = userDao.selectById(userModelDTO.getId()); + if (userInfo == null) { + throw new BusinessException(ErrorCode.USER_DOES_NOT_EXIST); + } +// 用户没有密码的情况下设置密码 + if (userInfo.getPassword() == null) { + if (!userModelDTO.getNewPassword().isEmpty()){ + if (userModelDTO.getNewPassword().length()<6){ + throw new BusinessException(ErrorCode.PARAMS_ERROR,"密码长度不能小于 6 位"); + } + userModelDTO.setPassword(BcryptUtils.encryptPassword(userModelDTO.getNewPassword())); + } + } +// 用户有密码的情况下重新设置密码 + if (userInfo.getPassword() != null && userModelDTO.getOldPassword() != null) { + if (BcryptUtils.matchPassword(userModelDTO.getOldPassword(), userInfo.getPassword())) { + userModelDTO.setPassword(BcryptUtils.encryptPassword(userModelDTO.getNewPassword())); + }else { + throw new BusinessException(ErrorCode.PASSWORD_ERROR,"旧密码不正确"); + } + } + + UserModel userModel = new UserModel(); + BeanUtil.copyProperties(userModelDTO, userModel); + int i = userDao.updateById(userModel); + // 返回结果 + userDao.selectById(userModel.getId()); + UserModelVO userModelVO = BeanUtil.copyProperties(userModel, UserModelVO.class); + userModelVO.setNewAccount(false); + if (i == 1){ + return userModelVO; + }else { + throw new BusinessException(ErrorCode.SYSTEM_ERROR); + } + } + + @Override + public UserModelVO addUserWithMail(UserModelDTO model) { + + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(UserModel::getEmail,model.getEmail()); + UserModel userModel = userDao.selectOne(lambdaQueryWrapper); + if (userModel != null) { + throw new BusinessException(ErrorCode.MAIL_ALREADY_EXIST); + } + if (model.getPassword().length() < 6 ){ + throw new BusinessException(ErrorCode.PARAMS_ERROR,"密码长度不能小于 6 位"); + } + model.setPassword(BcryptUtils.encryptPassword(model.getPassword())); + model.setCreateTime(VVTools.currentTimeStamp()); + //设置状态为正常 + model.setStatus(2); + //设置积分为0 + model.setPoints(0); + userDao.insert(BeanUtil.copyProperties(model, UserModel.class)); + // 判断用户是否为邀请用户 + if (model.getInviterId() != null) { + UserModel oldUser = userDao.selectById(model.getInviterId()); + oldUser.setPoints(oldUser.getPoints() + 10); + userDao.updateById(oldUser); + } + UserModelVO userModelVO = BeanUtil.copyProperties(model, UserModelVO.class); + userModelVO.setNewAccount(true); + userModelVO.setChatInfo(wxChatParam); + return userModelVO; + } +} diff --git a/src/main/java/vvpkassistant/common/ErrorCode.java b/src/main/java/vvpkassistant/common/ErrorCode.java index 7b6c178..f55c51f 100644 --- a/src/main/java/vvpkassistant/common/ErrorCode.java +++ b/src/main/java/vvpkassistant/common/ErrorCode.java @@ -27,7 +27,11 @@ public enum ErrorCode { WX_SYSTEM_BUSY(-1, "系统繁忙"), /* =============== 登录/用户信息 =============== */ - WX_GET_USER_INFO_FAILED(50001, "获取用户信息失败,请稍后再试"); + WX_GET_USER_INFO_FAILED(50001, "获取用户信息失败,请稍后再试"), + USER_DOES_NOT_EXIST(5002,"用户不存在"), + MAIL_ALREADY_EXIST(5003,"邮箱已存在"), + PASSWORD_ERROR(5004, "用户名或密码错误" ), + TOKEN_INVALID(40400, "Token无效,请重新登录"); /** * 状态码 diff --git a/src/main/java/vvpkassistant/config/SaTokenConfigure.java b/src/main/java/vvpkassistant/config/SaTokenConfigure.java new file mode 100644 index 0000000..0ea7902 --- /dev/null +++ b/src/main/java/vvpkassistant/config/SaTokenConfigure.java @@ -0,0 +1,69 @@ +package vvpkassistant.config; + +import cn.dev33.satoken.fun.strategy.SaCorsHandleFunction; +import cn.dev33.satoken.interceptor.SaInterceptor; +import cn.dev33.satoken.router.SaHttpMethod; +import cn.dev33.satoken.router.SaRouter; +import cn.dev33.satoken.stp.StpUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +@Slf4j +public class SaTokenConfigure implements WebMvcConfigurer { + + + + @Override + public void addInterceptors(InterceptorRegistry registry) { + // 注册Sa-Token的拦截器 + registry.addInterceptor(new SaInterceptor(handle -> StpUtil.checkLogin())) + .addPathPatterns("/**") + .excludePathPatterns(getExcludePaths()); + } + + /** + * 获取需要放行的路径 + */ + private String[] getExcludePaths() { + return new String[]{ + // Swagger & Knife4j 相关 + "/doc.html", + "/webjars/**", + "/swagger-resources/**", + "/v2/api-docs", + "/v3/api-docs", + "/v3/api-docs/**", + "/swagger-ui.html", + "/swagger-ui/**", + "/favicon.ico", + // 你的其他放行路径,例如登录接口 + "/user/loginWithPhoneNumber", + "/user/registerWithMail", + "/user/loginWithMail" + }; + } + + @Bean + public SaCorsHandleFunction corsHandle() { + return (req, res, sto) -> { + res. + // 允许指定域访问跨域资源 + setHeader("Access-Control-Allow-Origin", "*") + // 允许所有请求方式 + .setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE") + // 有效时间 + .setHeader("Access-Control-Max-Age", "3600") + // 允许的header参数 + .setHeader("Access-Control-Allow-Headers", "*"); + + // 如果是预检请求,则立即返回到前端 + SaRouter.match(SaHttpMethod.OPTIONS) + .back(); + }; + + } +} \ No newline at end of file diff --git a/src/main/java/vvpkassistant/exception/GlobalExceptionHandler.java b/src/main/java/vvpkassistant/exception/GlobalExceptionHandler.java index 30fa00c..28e3626 100644 --- a/src/main/java/vvpkassistant/exception/GlobalExceptionHandler.java +++ b/src/main/java/vvpkassistant/exception/GlobalExceptionHandler.java @@ -1,5 +1,6 @@ package vvpkassistant.exception; +import cn.dev33.satoken.exception.NotLoginException; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; @@ -28,6 +29,44 @@ public class GlobalExceptionHandler { log.error("RuntimeException", e); return ResponseData.error(ErrorCode.SYSTEM_ERROR); } + // 全局异常拦截(拦截项目中的NotLoginException异常) + @ExceptionHandler(NotLoginException.class) + public ResponseData handlerNotLoginException(NotLoginException nle) + throws Exception { + + // 打印堆栈,以供调试 + nle.printStackTrace(); + + // 判断场景值,定制化异常信息 + String message = ""; + if(nle.getType().equals(NotLoginException.NOT_TOKEN)) { + message = "未能读取到有效用户令牌"; + } + else if(nle.getType().equals(NotLoginException.INVALID_TOKEN)) { + message = "令牌无效"; + } + else if(nle.getType().equals(NotLoginException.TOKEN_TIMEOUT)) { + message = "令牌已过期"; + } + else if(nle.getType().equals(NotLoginException.BE_REPLACED)) { + message = "令牌已被顶下线"; + } + else if(nle.getType().equals(NotLoginException.KICK_OUT)) { + message = "令牌已被踢下线"; + } + else if(nle.getType().equals(NotLoginException.TOKEN_FREEZE)) { + message = "令牌已被冻结"; + } + else if(nle.getType().equals(NotLoginException.NO_PREFIX)) { + message = "未按照指定前缀提交令牌"; + } + else { + message = "当前会话未登录"; + } + + // 返回给前端 + return ResponseData.error(ErrorCode.TOKEN_INVALID.getCode(),message); + } } diff --git a/src/main/java/vvpkassistant/mail/model/MailModel.java b/src/main/java/vvpkassistant/mail/model/MailModel.java new file mode 100644 index 0000000..8d78ec3 --- /dev/null +++ b/src/main/java/vvpkassistant/mail/model/MailModel.java @@ -0,0 +1,13 @@ +package vvpkassistant.mail.model; + +import lombok.Data; + +/* + * @author: ziin + * @date: 2025/8/4 15:48 + */ +@Data +public class MailModel { + private String mailAddress; + private Integer code; +} diff --git a/src/main/java/vvpkassistant/mail/service/MailService.java b/src/main/java/vvpkassistant/mail/service/MailService.java new file mode 100644 index 0000000..5319ee9 --- /dev/null +++ b/src/main/java/vvpkassistant/mail/service/MailService.java @@ -0,0 +1,11 @@ +package vvpkassistant.mail.service; + +import vvpkassistant.mail.model.MailModel; + +/* + * @author: ziin + * @date: 2025/8/4 15:42 + */ +public interface MailService { + Boolean sendMail(MailModel model); +} diff --git a/src/main/java/vvpkassistant/mail/service/MailServiceImpl.java b/src/main/java/vvpkassistant/mail/service/MailServiceImpl.java new file mode 100644 index 0000000..853212a --- /dev/null +++ b/src/main/java/vvpkassistant/mail/service/MailServiceImpl.java @@ -0,0 +1,62 @@ +package vvpkassistant.mail.service; + +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; +import com.mailgun.api.v3.MailgunMessagesApi; +import com.mailgun.client.MailgunClient; +import com.mailgun.model.message.Message; +import com.mailgun.model.message.MessageResponse; +import feign.AsyncClient; +import feign.Client; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; +import vvpkassistant.mail.model.MailModel; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +/* + * @author: ziin + * @date: 2025/8/4 15:42 + */ +@Service +public class MailServiceImpl implements MailService { + + @Value("${mailgun}") + private String mailgunKey; + + public final Cache codeCache = Caffeine.newBuilder() + .expireAfterWrite(10, TimeUnit.MINUTES) // 5 分钟过期 + .maximumSize(10_000) // 防止内存暴涨 + .build(); + + + @Override + public Boolean sendMail(MailModel model) { + ExecutorService executor = Executors.newFixedThreadPool(2); + AsyncClient.Default asyncClient = new AsyncClient.Default<>( + new Client.Default(null, null), executor); + + MailgunMessagesApi mailgunAsyncMessagesApi = MailgunClient.config(mailgunKey) + .client(asyncClient) + .createAsyncApi(MailgunMessagesApi.class); + + Message message = Message.builder() + .from("") + .to(model.getMailAddress()) + .subject("your mail address Verification code is : ") + .html("\n" + + "\n" + + "\t

Sending HTML emails with Mailgun

\n" + + "\t

Hello world

\n" + + "\t

More examples can be found here

\n" + + "\n" + + "") + .build(); + + MessageResponse messageResponse = mailgunAsyncMessagesApi.sendMessage("www.baidu.com", message); + return true; + } +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 016bac5..9eb93ba 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -7,3 +7,22 @@ spring: +mailgun: b4888f65c7fd452213f3a8aea9d88269-812b35f5-006d7fd6 + + +############## Sa-Token 配置 (文档: https://sa-token.cc) ############## +sa-token: + # token 名称(同时也是 cookie 名称) + token-name: token + # token 有效期(单位:秒) 默认30天,-1 代表永久有效 + timeout: 2592000 + # token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结 + active-timeout: -1 + # 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录) + is-concurrent: true + # 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token) + is-share: false + # token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik) + token-style: random-128 + # 是否输出操作日志 + is-log: true diff --git a/target/classes/application.yml b/target/classes/application.yml index 016bac5..9eb93ba 100644 --- a/target/classes/application.yml +++ b/target/classes/application.yml @@ -7,3 +7,22 @@ spring: +mailgun: b4888f65c7fd452213f3a8aea9d88269-812b35f5-006d7fd6 + + +############## Sa-Token 配置 (文档: https://sa-token.cc) ############## +sa-token: + # token 名称(同时也是 cookie 名称) + token-name: token + # token 有效期(单位:秒) 默认30天,-1 代表永久有效 + timeout: 2592000 + # token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结 + active-timeout: -1 + # 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录) + is-concurrent: true + # 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token) + is-share: false + # token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik) + token-style: random-128 + # 是否输出操作日志 + is-log: true