From 8b6dba3749b486d030832ef738a63a50d3b588d5 Mon Sep 17 00:00:00 2001 From: Bunny <1319900154@qq.com> Date: Fri, 11 Jul 2025 15:32:11 +0800 Subject: [PATCH] =?UTF-8?q?:sparkles:=20=E8=AE=BE=E7=BD=AE=E8=87=AA?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=E7=94=A8=E6=88=B7=E6=9F=A5=E8=AF=A2Service?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../step2/config/MyBatisPlusFieldConfig.java | 44 ++++++++++++++ .../ControllerStringParamTrimConfig.java | 2 +- .../web/ThreadLocalCleanupInterceptor.java | 21 +++++++ .../spring/step2/config/web/WebConfig.java | 26 +++++++++ .../com/spring/step2/context/BaseContext.java | 29 ++++++++++ .../com/spring/step2/domain/dto/UserDto.java | 20 ------- .../security/service/DbUserDetailService.java | 35 +++++++++++ .../service/InMemoryUserDetailsService.java | 58 ++++++++----------- .../step2/service/impl/UserServiceImpl.java | 9 +++ .../step2/service/impl/UsersServiceImpl.java | 15 ++++- .../src/main/resources/mapper/UserMapper.xml | 3 - 11 files changed, 202 insertions(+), 60 deletions(-) create mode 100644 spring-security/step-2/src/main/java/com/spring/step2/config/MyBatisPlusFieldConfig.java rename spring-security/step-2/src/main/java/com/spring/step2/config/{ => web}/ControllerStringParamTrimConfig.java (98%) create mode 100644 spring-security/step-2/src/main/java/com/spring/step2/config/web/ThreadLocalCleanupInterceptor.java create mode 100644 spring-security/step-2/src/main/java/com/spring/step2/config/web/WebConfig.java create mode 100644 spring-security/step-2/src/main/java/com/spring/step2/context/BaseContext.java create mode 100644 spring-security/step-2/src/main/java/com/spring/step2/security/service/DbUserDetailService.java diff --git a/spring-security/step-2/src/main/java/com/spring/step2/config/MyBatisPlusFieldConfig.java b/spring-security/step-2/src/main/java/com/spring/step2/config/MyBatisPlusFieldConfig.java new file mode 100644 index 0000000..d632420 --- /dev/null +++ b/spring-security/step-2/src/main/java/com/spring/step2/config/MyBatisPlusFieldConfig.java @@ -0,0 +1,44 @@ +package com.spring.step2.config; + +import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; +import com.spring.step2.context.BaseContext; +import org.apache.ibatis.reflection.MetaObject; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; + +/** + * 配置MP在修改和新增时的操作 + */ +@Component +public class MyBatisPlusFieldConfig implements MetaObjectHandler { + + /** + * 使用mp做添加操作时候,这个方法执行 + */ + @Override + public void insertFill(MetaObject metaObject) { + // 设置属性值 + this.strictInsertFill(metaObject, "isDeleted", Integer.class, 0); + this.setFieldValByName("createTime", LocalDateTime.now(), metaObject); + this.setFieldValByName("updateTime", LocalDateTime.now(), metaObject); + if (BaseContext.getUsername() != null) { + this.setFieldValByName("createUser", BaseContext.getUserId(), metaObject); + this.setFieldValByName("updateUser", BaseContext.getUserId(), metaObject); + } else { + this.setFieldValByName("createUser", 0L, metaObject); + this.setFieldValByName("updateUser", BaseContext.getUserId(), metaObject); + } + } + + /** + * 使用mp做修改操作时候,这个方法执行 + */ + @Override + public void updateFill(MetaObject metaObject) { + if (BaseContext.getUserId() != null) { + this.setFieldValByName("updateTime", LocalDateTime.now(), metaObject); + this.setFieldValByName("updateUser", BaseContext.getUserId(), metaObject); + } + } +} diff --git a/spring-security/step-2/src/main/java/com/spring/step2/config/ControllerStringParamTrimConfig.java b/spring-security/step-2/src/main/java/com/spring/step2/config/web/ControllerStringParamTrimConfig.java similarity index 98% rename from spring-security/step-2/src/main/java/com/spring/step2/config/ControllerStringParamTrimConfig.java rename to spring-security/step-2/src/main/java/com/spring/step2/config/web/ControllerStringParamTrimConfig.java index 095b2b3..1317a3a 100644 --- a/spring-security/step-2/src/main/java/com/spring/step2/config/ControllerStringParamTrimConfig.java +++ b/spring-security/step-2/src/main/java/com/spring/step2/config/web/ControllerStringParamTrimConfig.java @@ -1,4 +1,4 @@ -package com.spring.step2.config; +package com.spring.step2.config.web; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; diff --git a/spring-security/step-2/src/main/java/com/spring/step2/config/web/ThreadLocalCleanupInterceptor.java b/spring-security/step-2/src/main/java/com/spring/step2/config/web/ThreadLocalCleanupInterceptor.java new file mode 100644 index 0000000..bd45ffd --- /dev/null +++ b/spring-security/step-2/src/main/java/com/spring/step2/config/web/ThreadLocalCleanupInterceptor.java @@ -0,0 +1,21 @@ +package com.spring.step2.config.web; + +import com.spring.step2.context.BaseContext; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.HandlerInterceptor; + +@Configuration +public class ThreadLocalCleanupInterceptor implements HandlerInterceptor { + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + return true; + } + + @Override + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { + BaseContext.removeUser(); + } +} \ No newline at end of file diff --git a/spring-security/step-2/src/main/java/com/spring/step2/config/web/WebConfig.java b/spring-security/step-2/src/main/java/com/spring/step2/config/web/WebConfig.java new file mode 100644 index 0000000..a24fe0d --- /dev/null +++ b/spring-security/step-2/src/main/java/com/spring/step2/config/web/WebConfig.java @@ -0,0 +1,26 @@ +package com.spring.step2.config.web; + +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +@RequiredArgsConstructor +public class WebConfig implements WebMvcConfigurer { + + private final ThreadLocalCleanupInterceptor threadLocalCleanupInterceptor; + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(threadLocalCleanupInterceptor); + } + + @Bean + public RestTemplate restTemplate() { + return new RestTemplate(); + } + +} \ No newline at end of file diff --git a/spring-security/step-2/src/main/java/com/spring/step2/context/BaseContext.java b/spring-security/step-2/src/main/java/com/spring/step2/context/BaseContext.java new file mode 100644 index 0000000..8b26744 --- /dev/null +++ b/spring-security/step-2/src/main/java/com/spring/step2/context/BaseContext.java @@ -0,0 +1,29 @@ +package com.spring.step2.context; + + +public class BaseContext { + private static final ThreadLocal userId = new ThreadLocal<>(); + private static final ThreadLocal username = new ThreadLocal<>(); + + // 用户id相关 + public static Long getUserId() { + return userId.get(); + } + + public static void setUserId(Long _userId) { + userId.set(_userId); + } + + public static String getUsername() { + return username.get(); + } + + public static void setUsername(String _username) { + username.set(_username); + } + + public static void removeUser() { + username.remove(); + userId.remove(); + } +} \ No newline at end of file diff --git a/spring-security/step-2/src/main/java/com/spring/step2/domain/dto/UserDto.java b/spring-security/step-2/src/main/java/com/spring/step2/domain/dto/UserDto.java index 71686bb..8b844b9 100644 --- a/spring-security/step-2/src/main/java/com/spring/step2/domain/dto/UserDto.java +++ b/spring-security/step-2/src/main/java/com/spring/step2/domain/dto/UserDto.java @@ -6,8 +6,6 @@ import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; -import java.time.LocalDateTime; - @Data @AllArgsConstructor @NoArgsConstructor @@ -15,9 +13,6 @@ import java.time.LocalDateTime; @Schema(name = "UserDTO对象", title = "用户", description = "用户的DTO对象") public class UserDto { - @Schema(name = "id", title = "主键") - private String id; - @Schema(name = "username", title = "用户名") private String username; @@ -27,19 +22,4 @@ public class UserDto { @Schema(name = "email", title = "邮箱") private String email; - @Schema(name = "createTime", title = "创建时间") - private LocalDateTime createTime; - - @Schema(name = "updateTime", title = "更新时间") - private LocalDateTime updateTime; - - @Schema(name = "createUser", title = "创建用户") - private Long createUser; - - @Schema(name = "updateUser", title = "更新用户") - private Long updateUser; - - @Schema(name = "isDeleted", title = "是否被删除") - private Boolean isDeleted; - } \ No newline at end of file diff --git a/spring-security/step-2/src/main/java/com/spring/step2/security/service/DbUserDetailService.java b/spring-security/step-2/src/main/java/com/spring/step2/security/service/DbUserDetailService.java new file mode 100644 index 0000000..969e620 --- /dev/null +++ b/spring-security/step-2/src/main/java/com/spring/step2/security/service/DbUserDetailService.java @@ -0,0 +1,35 @@ +package com.spring.step2.security.service; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.spring.step2.domain.entity.UserEntity; +import com.spring.step2.mapper.UserMapper; +import lombok.RequiredArgsConstructor; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class DbUserDetailService implements UserDetailsService { + + private final UserMapper userMapper; + + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + // 查询当前用户 + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.lambda().eq(UserEntity::getUsername, username); + UserEntity userEntity = userMapper.selectOne(wrapper); + + // 判断当前用户是否存在 + if (userEntity == null) { + throw new UsernameNotFoundException("用户不存在"); + } + + return User.builder().username(userEntity.getUsername()) + .password(userEntity.getPassword()) + .build(); + } +} diff --git a/spring-security/step-2/src/main/java/com/spring/step2/security/service/InMemoryUserDetailsService.java b/spring-security/step-2/src/main/java/com/spring/step2/security/service/InMemoryUserDetailsService.java index aae995a..de01572 100644 --- a/spring-security/step-2/src/main/java/com/spring/step2/security/service/InMemoryUserDetailsService.java +++ b/spring-security/step-2/src/main/java/com/spring/step2/security/service/InMemoryUserDetailsService.java @@ -1,35 +1,27 @@ package com.spring.step2.security.service; -import lombok.RequiredArgsConstructor; -import org.springframework.security.core.userdetails.User; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.security.core.userdetails.UsernameNotFoundException; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.stereotype.Service; - -@Service -@RequiredArgsConstructor -public class InMemoryUserDetailsService implements UserDetailsService { - - private final PasswordEncoder passwordEncoder; - - @Override - public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { - // 1. 这里应该根据username从数据库或其他存储中查询用户信息 - // 以下是模拟数据,实际应用中应从数据库查询 - - // 2. 如果用户不存在,抛出UsernameNotFoundException - if (!"bunny".equalsIgnoreCase(username)) { - throw new UsernameNotFoundException("User not found: " + username); - } - - // 3. 构建UserDetails对象返回 - return User.builder() - .username(username) // 使用传入的用户名 - .password(passwordEncoder.encode("123456")) // 密码应该已经加密存储,这里仅为示例 - .roles("USER") // 角色会自动添加ROLE_前缀 - .authorities("read", "write") // 添加具体权限 - .build(); - } -} \ No newline at end of file +// @Service +// @RequiredArgsConstructor +// public class InMemoryUserDetailsService implements UserDetailsService { +// +// private final PasswordEncoder passwordEncoder; +// +// @Override +// public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { +// // 1. 这里应该根据username从数据库或其他存储中查询用户信息 +// // 以下是模拟数据,实际应用中应从数据库查询 +// +// // 2. 如果用户不存在,抛出UsernameNotFoundException +// if (!"bunny".equalsIgnoreCase(username)) { +// throw new UsernameNotFoundException("User not found: " + username); +// } +// +// // 3. 构建UserDetails对象返回 +// return User.builder() +// .username(username) // 使用传入的用户名 +// .password(passwordEncoder.encode("123456")) // 密码应该已经加密存储,这里仅为示例 +// .roles("USER") // 角色会自动添加ROLE_前缀 +// .authorities("read", "write") // 添加具体权限 +// .build(); +// } +// } \ No newline at end of file diff --git a/spring-security/step-2/src/main/java/com/spring/step2/service/impl/UserServiceImpl.java b/spring-security/step-2/src/main/java/com/spring/step2/service/impl/UserServiceImpl.java index afffad5..56e3558 100644 --- a/spring-security/step-2/src/main/java/com/spring/step2/service/impl/UserServiceImpl.java +++ b/spring-security/step-2/src/main/java/com/spring/step2/service/impl/UserServiceImpl.java @@ -12,6 +12,7 @@ import com.spring.step2.mapper.UserMapper; import com.spring.step2.service.UserService; import lombok.RequiredArgsConstructor; import org.springframework.beans.BeanUtils; +import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -31,6 +32,8 @@ import java.util.List; @RequiredArgsConstructor public class UserServiceImpl extends ServiceImpl implements UserService { + private final PasswordEncoder passwordEncoder; + /** * * 用户 服务实现类 * @@ -59,6 +62,12 @@ public class UserServiceImpl extends ServiceImpl impleme public void addUser(UserDto dto) { UserEntity user = new UserEntity(); BeanUtils.copyProperties(dto, user); + + // 设置用户密码 + String password = user.getPassword(); + String encodePassword = passwordEncoder.encode(password); + user.setPassword(encodePassword); + save(user); } diff --git a/spring-security/step-2/src/main/java/com/spring/step2/service/impl/UsersServiceImpl.java b/spring-security/step-2/src/main/java/com/spring/step2/service/impl/UsersServiceImpl.java index 26cf34b..1224a1b 100644 --- a/spring-security/step-2/src/main/java/com/spring/step2/service/impl/UsersServiceImpl.java +++ b/spring-security/step-2/src/main/java/com/spring/step2/service/impl/UsersServiceImpl.java @@ -12,6 +12,7 @@ import com.spring.step2.mapper.UsersMapper; import com.spring.step2.service.UsersService; import lombok.RequiredArgsConstructor; import org.springframework.beans.BeanUtils; +import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -31,6 +32,8 @@ import java.util.List; @RequiredArgsConstructor public class UsersServiceImpl extends ServiceImpl implements UsersService { + private final PasswordEncoder passwordEncoder; + /** * * 服务实现类 * @@ -57,9 +60,15 @@ public class UsersServiceImpl extends ServiceImpl impl */ @Override public void addUsers(UsersDto dto) { - UsersEntity users = new UsersEntity(); - BeanUtils.copyProperties(dto, users); - save(users); + UsersEntity user = new UsersEntity(); + BeanUtils.copyProperties(dto, user); + + // 设置用户密码 + String password = user.getPassword(); + String encodePassword = passwordEncoder.encode(password); + user.setPassword(encodePassword); + + save(user); } /** diff --git a/spring-security/step-2/src/main/resources/mapper/UserMapper.xml b/spring-security/step-2/src/main/resources/mapper/UserMapper.xml index d65359a..18449e7 100644 --- a/spring-security/step-2/src/main/resources/mapper/UserMapper.xml +++ b/spring-security/step-2/src/main/resources/mapper/UserMapper.xml @@ -27,9 +27,6 @@ from t_user is_deleted = 0 - - and id like CONCAT('%',#{dto.id},'%') - and username like CONCAT('%',#{dto.username},'%')