diff --git a/pom.xml b/pom.xml
index 6e51a6e..5f88f41 100644
--- a/pom.xml
+++ b/pom.xml
@@ -133,6 +133,19 @@
dysmsapi20170525
3.0.0
+
+
+ org.springframework.boot
+ spring-boot-starter-json
+
+
+
+
+ com.alibaba
+ fastjson
+ 2.0.53
+
+
diff --git a/src/main/java/com/guwan/backend/Handler/MyMetaObjectHandler.java b/src/main/java/com/guwan/backend/Handler/MyMetaObjectHandler.java
index 92b428f..16c5957 100644
--- a/src/main/java/com/guwan/backend/Handler/MyMetaObjectHandler.java
+++ b/src/main/java/com/guwan/backend/Handler/MyMetaObjectHandler.java
@@ -4,16 +4,17 @@ import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
+import java.util.Date;
+
-@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
- this.strictInsertFill(metaObject, "createdTime", LocalDateTime.class, LocalDateTime.now());
+ this.strictInsertFill(metaObject, "createdTime", Date.class, new Date());
}
@Override
public void updateFill(MetaObject metaObject) {
- this.strictUpdateFill(metaObject, "lastLoginTime", LocalDateTime.class, LocalDateTime.now());
+ this.strictUpdateFill(metaObject, "lastLoginTime", Date.class, new Date());
}
}
\ No newline at end of file
diff --git a/src/main/java/com/guwan/backend/JwtExample.java b/src/main/java/com/guwan/backend/JwtExample.java
new file mode 100644
index 0000000..64b05a6
--- /dev/null
+++ b/src/main/java/com/guwan/backend/JwtExample.java
@@ -0,0 +1,24 @@
+package com.guwan.backend;
+
+import io.jsonwebtoken.security.Keys;
+import io.jsonwebtoken.SignatureAlgorithm;
+
+import javax.crypto.SecretKey;
+
+public class JwtExample {
+ public static void main(String[] args) {
+ // 选择您的 HMAC-SHA 算法
+ SignatureAlgorithm algorithm = SignatureAlgorithm.HS256;
+
+ // 使用推荐的密钥生成方法生成密钥
+ SecretKey key = Keys.secretKeyFor(algorithm);
+
+ System.out.println("key = " + key);
+
+ SecretKey key2 = Keys.secretKeyFor(SignatureAlgorithm.HS512);
+ System.out.println("key2 = " + key2);
+
+ // 现在 key 是一个足够安全的密钥,可以用于 JWT 签名
+ // 您可以使用这个密钥来创建和验证 JWT
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/guwan/backend/config/JacksonConfiguration.java b/src/main/java/com/guwan/backend/config/JacksonConfiguration.java
new file mode 100644
index 0000000..fc3fb66
--- /dev/null
+++ b/src/main/java/com/guwan/backend/config/JacksonConfiguration.java
@@ -0,0 +1,44 @@
+package com.guwan.backend.config;
+
+
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
+import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
+import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
+import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
+import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
+import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
+import com.fasterxml.jackson.module.paramnames.ParameterNamesModule;
+import com.guwan.backend.constant.Constants;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.format.DateTimeFormatter;
+
+@Configuration
+public class JacksonConfiguration {
+
+ @Bean
+ public ObjectMapper objectMapper(){
+ ObjectMapper objectMapper = new ObjectMapper();
+ objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
+ objectMapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);
+ JavaTimeModule javaTimeModule = new JavaTimeModule();
+
+ javaTimeModule.addSerializer(LocalDateTime.class,new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(Constants.DateTime.DEFAULT_DATE_TIME_FORMAT)));
+ javaTimeModule.addSerializer(LocalDate.class,new LocalDateSerializer(DateTimeFormatter.ofPattern(Constants.DateTime.DEFAULT_DATE_FORMAT)));
+ javaTimeModule.addSerializer(LocalTime.class,new LocalTimeSerializer(DateTimeFormatter.ofPattern(Constants.DateTime.DEFAULT_TIME_FORMAT)));
+
+ javaTimeModule.addDeserializer(LocalDateTime.class,new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(Constants.DateTime.DEFAULT_DATE_TIME_FORMAT)));
+ javaTimeModule.addDeserializer(LocalDate.class,new LocalDateDeserializer(DateTimeFormatter.ofPattern(Constants.DateTime.DEFAULT_DATE_FORMAT)));
+ javaTimeModule.addDeserializer(LocalTime.class,new LocalTimeDeserializer(DateTimeFormatter.ofPattern(Constants.DateTime.DEFAULT_TIME_FORMAT)));
+ objectMapper.registerModule(javaTimeModule).registerModule(new ParameterNamesModule());
+ return objectMapper;
+ }
+}
diff --git a/src/main/java/com/guwan/backend/config/MvcConfiguration.java b/src/main/java/com/guwan/backend/config/MvcConfiguration.java
new file mode 100644
index 0000000..782bc05
--- /dev/null
+++ b/src/main/java/com/guwan/backend/config/MvcConfiguration.java
@@ -0,0 +1,27 @@
+package com.guwan.backend.config;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.converter.HttpMessageConverter;
+import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+import java.util.List;
+
+@Configuration
+public class MvcConfiguration implements WebMvcConfigurer {
+ @Override
+ public void extendMessageConverters(List> converters) {
+ MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
+ ObjectMapper objectMapper = new ObjectMapper();
+ objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
+ objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
+ objectMapper.registerModule(new JavaTimeModule());
+ messageConverter.setObjectMapper(objectMapper);
+ converters.add(0, messageConverter);
+ }
+}
diff --git a/src/main/java/com/guwan/backend/config/MybatisPlusConfig.java b/src/main/java/com/guwan/backend/config/MybatisPlusConfig.java
index 74270be..4eb163b 100644
--- a/src/main/java/com/guwan/backend/config/MybatisPlusConfig.java
+++ b/src/main/java/com/guwan/backend/config/MybatisPlusConfig.java
@@ -1,5 +1,8 @@
package com.guwan.backend.config;
+import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
+import com.guwan.backend.Handler.MyMetaObjectHandler;
+import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@@ -11,4 +14,10 @@ public class MybatisPlusConfig {
// interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
// return interceptor;
// }
+
+ @Bean
+ public MetaObjectHandler myCustomMetaObjectHandler() {
+ return new MyMetaObjectHandler();
+ }
+
}
\ No newline at end of file
diff --git a/src/main/java/com/guwan/backend/constant/Constants.java b/src/main/java/com/guwan/backend/constant/Constants.java
new file mode 100644
index 0000000..e119659
--- /dev/null
+++ b/src/main/java/com/guwan/backend/constant/Constants.java
@@ -0,0 +1,12 @@
+package com.guwan.backend.constant;
+
+public class Constants {
+ public static class DateTime {
+ /** 默认日期时间格式 */
+ public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
+ /** 默认日期格式 */
+ public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
+ /** 默认时间格式 */
+ public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";
+ }
+}
diff --git a/src/main/java/com/guwan/backend/controller/UserController.java b/src/main/java/com/guwan/backend/controller/UserController.java
index ab74633..15f1fe6 100644
--- a/src/main/java/com/guwan/backend/controller/UserController.java
+++ b/src/main/java/com/guwan/backend/controller/UserController.java
@@ -3,10 +3,7 @@ package com.guwan.backend.controller;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import com.guwan.backend.common.Result;
-import com.guwan.backend.dto.user.EmailDto;
-import com.guwan.backend.dto.user.PhoneDto;
-import com.guwan.backend.dto.user.RegisterDTO;
-import com.guwan.backend.dto.user.UserDTO;
+import com.guwan.backend.dto.user.*;
import com.guwan.backend.service.EmailService;
import com.guwan.backend.service.UserService;
import com.guwan.backend.util.RedisUtils;
@@ -53,7 +50,7 @@ public class UserController {
}
@PostMapping("/login")
- public Result login(@RequestBody @Valid LoginRequest request) {
+ public Result login(@RequestBody @Valid LoginDto request) {
try {
log.info("用户登录: {}", request.getUsername());
return Result.success("登录成功", userService.login(request));
@@ -101,7 +98,9 @@ public class UserController {
@PostMapping("/getEmailCode")
- public Result getEmailCode(@RequestParam @Email(message = "邮箱格式不正确") String email) {
+ public Result getEmailCode(@RequestBody @Valid EmailDto emailDto) {
+
+ String email = emailDto.getEmail();
log.info("邮箱注册: {}", email);
@@ -130,7 +129,17 @@ public class UserController {
return Result.success("手机验证码发送成功");
}
-
+ @PostMapping("/email/code")
+ public Result sendEmailCode(
+ @RequestParam @Email(message = "邮箱格式不正确") String email) {
+ try {
+ userService.sendEmailCode(email);
+ return Result.success();
+ } catch (Exception e) {
+ log.error("发送邮箱验证码失败", e);
+ return Result.error(e.getMessage());
+ }
+ }
diff --git a/src/main/java/com/guwan/backend/dto/user/LoginDto.java b/src/main/java/com/guwan/backend/dto/user/LoginDto.java
index 3a230f1..2c6dfab 100644
--- a/src/main/java/com/guwan/backend/dto/user/LoginDto.java
+++ b/src/main/java/com/guwan/backend/dto/user/LoginDto.java
@@ -1,4 +1,34 @@
package com.guwan.backend.dto.user;
+
+import lombok.Data;
+
+@Data
public class LoginDto {
+ /**
+ * 登录类型 对应前端
+ */
+ private String activeTab;
+
+ /**
+ * 用户名
+ */
+ private String username;
+ /**
+ * 密码
+ */
+ private String password;
+ /**
+ * 手机号
+ */
+ private String phone;
+ /**
+ * 邮箱
+ */
+ private String email;
+ /**
+ * 验证码
+ */
+ private String code;
+
}
diff --git a/src/main/java/com/guwan/backend/dto/user/UserDTO.java b/src/main/java/com/guwan/backend/dto/user/UserDTO.java
index 8cf22dc..99f0528 100644
--- a/src/main/java/com/guwan/backend/dto/user/UserDTO.java
+++ b/src/main/java/com/guwan/backend/dto/user/UserDTO.java
@@ -1,8 +1,15 @@
package com.guwan.backend.dto.user;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
+import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
+import java.util.Date;
@Data
public class UserDTO {
@@ -14,8 +21,9 @@ public class UserDTO {
private String phone;
private Integer gender;
private String bio;
- private LocalDateTime createdTime;
- private LocalDateTime lastLoginTime;
+
+ private Date createdTime;
+ private Date lastLoginTime;
private Integer status;
private String token;
}
\ No newline at end of file
diff --git a/src/main/java/com/guwan/backend/entity/User.java b/src/main/java/com/guwan/backend/entity/User.java
index 235d4f5..c5fe143 100644
--- a/src/main/java/com/guwan/backend/entity/User.java
+++ b/src/main/java/com/guwan/backend/entity/User.java
@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.time.LocalDateTime;
+import java.util.Date;
@Data
@TableName("user")
@@ -29,10 +30,10 @@ public class User {
@TableField(fill = FieldFill.INSERT)
- private LocalDateTime createdTime;
+ private Date createdTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
- private LocalDateTime lastLoginTime;
+ private Date lastLoginTime;
private Integer status;
}
\ No newline at end of file
diff --git a/src/main/java/com/guwan/backend/service/UserService.java b/src/main/java/com/guwan/backend/service/UserService.java
index 24a9931..417238d 100644
--- a/src/main/java/com/guwan/backend/service/UserService.java
+++ b/src/main/java/com/guwan/backend/service/UserService.java
@@ -1,5 +1,6 @@
package com.guwan.backend.service;
+import com.guwan.backend.dto.user.LoginDto;
import com.guwan.backend.dto.user.RegisterDTO;
import com.guwan.backend.dto.user.UserDTO;
import com.guwan.backend.vo.user.EmailRegisterRequest;
@@ -14,7 +15,13 @@ public interface UserService {
* @return
*/
UserDTO register(RegisterDTO registerDTO);
- UserDTO login(LoginRequest request);
+
+ /**
+ * 登录
+ * @param request
+ * @return
+ */
+ UserDTO login(LoginDto request);
UserDTO getCurrentUser();
Long getCurrentUserId();
UserDTO getUserById(Long id);
diff --git a/src/main/java/com/guwan/backend/service/impl/UserServiceImpl.java b/src/main/java/com/guwan/backend/service/impl/UserServiceImpl.java
index 4a380bf..3c59955 100644
--- a/src/main/java/com/guwan/backend/service/impl/UserServiceImpl.java
+++ b/src/main/java/com/guwan/backend/service/impl/UserServiceImpl.java
@@ -1,6 +1,7 @@
package com.guwan.backend.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.guwan.backend.dto.user.LoginDto;
import com.guwan.backend.dto.user.RegisterDTO;
import com.guwan.backend.dto.user.UserDTO;
import com.guwan.backend.entity.User;
@@ -10,6 +11,7 @@ import com.guwan.backend.service.UserService;
import com.guwan.backend.service.VerificationService;
import com.guwan.backend.util.JwtUtil;
import com.guwan.backend.util.RedisUtil;
+import com.guwan.backend.util.RedisUtils;
import com.guwan.backend.vo.user.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -19,6 +21,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
+import java.util.Date;
import java.util.concurrent.TimeUnit;
@Slf4j
@@ -30,6 +33,7 @@ public class UserServiceImpl implements UserService {
private final PasswordEncoder passwordEncoder;
private final JwtUtil jwtUtil;
private final RedisUtil redisUtil;
+ private final RedisUtils redisUtils;
private final VerificationService verificationService;
private final EmailService emailService;
@@ -74,28 +78,62 @@ public class UserServiceImpl implements UserService {
user.setPassword(passwordEncoder.encode(request.getPassword()));
user.setPhone(request.getPhone());
user.setEmail(request.getEmail());
- user.setCreatedTime(LocalDateTime.now());
user.setStatus(1);
userMapper.insert(user);
+
+ redisUtil.delete(request.getEmail());
+ redisUtil.delete(request.getPhone());
return convertToDTO(user);
}
@Override
- public UserDTO login(LoginRequest request) {
- User user = findByUsername(request.getUsername());
-
- if (user == null || !passwordEncoder.matches(request.getPassword(), user.getPassword())) {
- throw new IllegalArgumentException("用户名或密码错误");
+ public UserDTO login(LoginDto request) {
+ User user = null;
+ System.out.println("request = " + request);
+
+ if (request.getActiveTab().equals("account")) {
+ user = userMapper.selectOne(new LambdaQueryWrapper().eq(User::getUsername, request.getUsername()));
+ if (user == null || !passwordEncoder.matches(request.getPassword(), user.getPassword())) {
+ throw new IllegalArgumentException("用户名或密码错误");
+ }
}
-
+
+ if (request.getActiveTab().equals("phone")) {
+ user = userMapper.selectOne(new LambdaQueryWrapper().eq(User::getPhone, request.getPhone()));
+ String redisPhoneCode = (String) redisUtil.get(request.getPhone());
+ if (user == null) {
+ throw new IllegalArgumentException("用户未注册");
+ }
+ if (!request.getCode().equals(redisPhoneCode)){
+ throw new IllegalArgumentException("验证码错误");
+ }else {
+ redisUtil.delete(request.getPhone());
+ }
+ }
+
+ if (request.getActiveTab().equals("email")) {
+ user = userMapper.selectOne(new LambdaQueryWrapper().eq(User::getEmail, request.getEmail()));
+ String redisEmailCode = (String) redisUtil.get(request.getEmail());
+ if (user == null) {
+ throw new IllegalArgumentException("用户未注册");
+ }
+ if (!request.getCode().equals(redisEmailCode)){
+ throw new IllegalArgumentException("验证码错误");
+ }else {
+ redisUtil.delete(request.getEmail());
+ }
+ }
+
+
if (user.getStatus() != 1) {
throw new IllegalArgumentException("账号已被禁用");
}
+
// 更新最后登录时间
- user.setLastLoginTime(LocalDateTime.now());
+ user.setLastLoginTime(new Date());
userMapper.updateById(user);
UserDTO userDTO = convertToDTO(user);
@@ -103,7 +141,7 @@ public class UserServiceImpl implements UserService {
userDTO.setToken(token);
// 缓存用户信息
- redisUtil.set(USER_CACHE_KEY + user.getId(), userDTO, USER_CACHE_DURATION, TimeUnit.SECONDS);
+ redisUtils.set(USER_CACHE_KEY + user.getId(), userDTO, USER_CACHE_DURATION);
return userDTO;
}
diff --git a/src/main/java/com/guwan/backend/util/JwtUtil.java b/src/main/java/com/guwan/backend/util/JwtUtil.java
index c287cf7..ba63ae2 100644
--- a/src/main/java/com/guwan/backend/util/JwtUtil.java
+++ b/src/main/java/com/guwan/backend/util/JwtUtil.java
@@ -11,6 +11,7 @@ import org.springframework.stereotype.Component;
import java.security.Key;
import java.util.Date;
+
@Slf4j
@Component
public class JwtUtil {
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index dd6a893..20c1ac5 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -67,7 +67,7 @@ mybatis-plus:
# JWT配置
jwt:
- secret: your-secret-key-must-be-at-least-32-bytes-long
+ secret: javax.crypto.spec.SecretKeySpec@5884561.Guwan.javax.crypto.spec.SecretKeySpec@5884561
expiration: 86400000 # 24小时
# 阿里云配置