diff --git a/src/main/java/asia/yulinling/workflow/config/SecurityConfig.java b/src/main/java/asia/yulinling/workflow/config/SecurityConfig.java
index 21411fe..3520cb5 100644
--- a/src/main/java/asia/yulinling/workflow/config/SecurityConfig.java
+++ b/src/main/java/asia/yulinling/workflow/config/SecurityConfig.java
@@ -5,7 +5,6 @@ import asia.yulinling.workflow.security.JwtAuthenticationEntryPoint;
import asia.yulinling.workflow.security.JwtAuthenticationFilter;
import asia.yulinling.workflow.security.JwtUserDetailsService;
import asia.yulinling.workflow.utils.JwtUtil;
-import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
@@ -48,7 +47,7 @@ public class SecurityConfig {
// 认证请求
.authorizeHttpRequests(auth -> auth
.requestMatchers("/login").permitAll()
- .requestMatchers("/users", "/users/**").hasRole("ADMIN")
+// .requestMatchers("/users", "/users/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
// JWT过滤器
diff --git a/src/main/java/asia/yulinling/workflow/mapper/PermissionMapper.java b/src/main/java/asia/yulinling/workflow/mapper/PermissionMapper.java
index 249b112..d5ac382 100644
--- a/src/main/java/asia/yulinling/workflow/mapper/PermissionMapper.java
+++ b/src/main/java/asia/yulinling/workflow/mapper/PermissionMapper.java
@@ -3,8 +3,11 @@ package asia.yulinling.workflow.mapper;
import asia.yulinling.workflow.model.entity.Permission;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Component;
+import java.util.List;
+
/**
*
*
@@ -16,4 +19,5 @@ import org.springframework.stereotype.Component;
@Mapper
@Component
public interface PermissionMapper extends BaseMapper {
+ List selectPermissionsByRoleId(@Param("roleIds") List roleIds);
}
diff --git a/src/main/java/asia/yulinling/workflow/mapper/RoleMapper.java b/src/main/java/asia/yulinling/workflow/mapper/RoleMapper.java
index 62b0688..3030309 100644
--- a/src/main/java/asia/yulinling/workflow/mapper/RoleMapper.java
+++ b/src/main/java/asia/yulinling/workflow/mapper/RoleMapper.java
@@ -5,6 +5,8 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Component;
+import java.util.List;
+
/**
*
* 角色Mapper
@@ -16,4 +18,5 @@ import org.springframework.stereotype.Component;
@Mapper
@Component
public interface RoleMapper extends BaseMapper {
+ List selectRoleByUserId(Long userId);
}
diff --git a/src/main/java/asia/yulinling/workflow/mapper/RolePermissionMapper.java b/src/main/java/asia/yulinling/workflow/mapper/RolePermissionMapper.java
new file mode 100644
index 0000000..2dd3d29
--- /dev/null
+++ b/src/main/java/asia/yulinling/workflow/mapper/RolePermissionMapper.java
@@ -0,0 +1,19 @@
+package asia.yulinling.workflow.mapper;
+
+import asia.yulinling.workflow.model.entity.RolePermission;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import org.springframework.stereotype.Component;
+
+/**
+ *
+ * 角色权限类
+ *
+ *
+ * @author YLL
+ * @since 2025/6/15
+ */
+@Mapper
+@Component
+public interface RolePermissionMapper extends BaseMapper {
+}
diff --git a/src/main/java/asia/yulinling/workflow/mapper/RoleUserMapper.java b/src/main/java/asia/yulinling/workflow/mapper/RoleUserMapper.java
new file mode 100644
index 0000000..62cd248
--- /dev/null
+++ b/src/main/java/asia/yulinling/workflow/mapper/RoleUserMapper.java
@@ -0,0 +1,19 @@
+package asia.yulinling.workflow.mapper;
+
+import asia.yulinling.workflow.model.entity.RoleUser;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import org.springframework.stereotype.Component;
+
+/**
+ *
+ * 角色用户类
+ *
+ *
+ * @author YLL
+ * @since 2025/6/15
+ */
+@Mapper
+@Component
+public interface RoleUserMapper extends BaseMapper {
+}
diff --git a/src/main/java/asia/yulinling/workflow/model/vo/user/UserPrincipal.java b/src/main/java/asia/yulinling/workflow/model/vo/user/UserPrincipal.java
index 8c92d2f..b534816 100644
--- a/src/main/java/asia/yulinling/workflow/model/vo/user/UserPrincipal.java
+++ b/src/main/java/asia/yulinling/workflow/model/vo/user/UserPrincipal.java
@@ -10,6 +10,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
@@ -30,6 +31,7 @@ import java.util.stream.Collectors;
@Data
@NoArgsConstructor
@AllArgsConstructor
+@Slf4j
public class UserPrincipal implements UserDetails {
/**
@@ -104,7 +106,19 @@ public class UserPrincipal implements UserDetails {
*/
private Collection extends GrantedAuthority> authorities;
- public UserPrincipal(Long id, String username, String password, String nickname, String phone, String email, String birthday, Integer sex, Integer status, Date createTime, Date updateTime, List roleNames, List authorities) {
+ public UserPrincipal(Long id,
+ String username,
+ String password,
+ String nickname,
+ String phone,
+ String email,
+ String birthday,
+ Integer sex,
+ Integer status,
+ Date createTime,
+ Date updateTime,
+ List roleNames,
+ List authorities) {
this.id = id;
this.username = username;
this.password = password;
@@ -125,22 +139,52 @@ public class UserPrincipal implements UserDetails {
return List.of();
}
- public UserPrincipal(Long id, String username, String password,
- List roles, Collection extends GrantedAuthority> authorities) {
+ public UserPrincipal(Long id,
+ String username,
+ String password,
+ List roles,
+ Collection extends GrantedAuthority> authorities) {
this.id = id;
this.username = username;
this.password = password;
this.roles = roles;
this.authorities = authorities;
- this.status = 1; // 启用
+ this.status = 1;
}
- public static UserPrincipal create(User user, List roles, List permissions) {
- List roleNames = roles.stream().map(Role::getName).collect(Collectors.toList());
+ public static UserPrincipal create(User user,
+ List roles,
+ List permissions) {
- List authorities = permissions.stream().filter(permission -> StrUtil.isNotBlank(permission.getPermission())).map(permission -> new SimpleGrantedAuthority(permission.getPermission())).collect(Collectors.toList());
+ log.info("roleNames{}\n{}authorities", roles, permissions);
- return new UserPrincipal(user.getId(), user.getUsername(), user.getPassword(), user.getNickname(), user.getPhone(), user.getEmail(), user.getBirthday(), user.getSex(), user.getStatus(), user.getCreateTime(), user.getUpdateTime(), roleNames, authorities);
+ List roleNames = roles
+ .stream()
+ .map(Role::getName)
+ .collect(Collectors.toList());
+
+ List authorities = permissions
+ .stream()
+ .filter(permission ->
+ StrUtil.isNotBlank(permission.getPermission()))
+ .map(permission ->
+ new SimpleGrantedAuthority(permission.getPermission()))
+ .collect(Collectors.toList());
+
+ return new UserPrincipal(
+ user.getId(),
+ user.getUsername(),
+ user.getPassword(),
+ user.getNickname(),
+ user.getPhone(),
+ user.getEmail(),
+ user.getBirthday(),
+ user.getSex(),
+ user.getStatus(),
+ user.getCreateTime(),
+ user.getUpdateTime(),
+ roleNames,
+ authorities);
}
@@ -161,12 +205,12 @@ public class UserPrincipal implements UserDetails {
@Override
public boolean isAccountNonLocked() {
- return true;
+ return UserDetails.super.isAccountNonLocked();
}
@Override
public boolean isCredentialsNonExpired() {
- return true;
+ return UserDetails.super.isCredentialsNonExpired();
}
@Override
diff --git a/src/main/java/asia/yulinling/workflow/security/JwtAccessDeniedHandler.java b/src/main/java/asia/yulinling/workflow/security/JwtAccessDeniedHandler.java
index 02a1d3d..97b892d 100644
--- a/src/main/java/asia/yulinling/workflow/security/JwtAccessDeniedHandler.java
+++ b/src/main/java/asia/yulinling/workflow/security/JwtAccessDeniedHandler.java
@@ -3,7 +3,6 @@ package asia.yulinling.workflow.security;
import asia.yulinling.workflow.exception.BaseException;
import asia.yulinling.workflow.model.ApiResponse;
import com.fasterxml.jackson.databind.ObjectMapper;
-import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.access.AccessDeniedException;
diff --git a/src/main/java/asia/yulinling/workflow/security/JwtAuthenticationFilter.java b/src/main/java/asia/yulinling/workflow/security/JwtAuthenticationFilter.java
index e528a0f..e396e60 100644
--- a/src/main/java/asia/yulinling/workflow/security/JwtAuthenticationFilter.java
+++ b/src/main/java/asia/yulinling/workflow/security/JwtAuthenticationFilter.java
@@ -1,5 +1,6 @@
package asia.yulinling.workflow.security;
+import asia.yulinling.workflow.model.vo.user.UserPrincipal;
import asia.yulinling.workflow.utils.JwtUtil;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
@@ -8,11 +9,8 @@ import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.security.core.userdetails.UserDetails;
-import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;
@@ -31,7 +29,7 @@ import java.io.IOException;
@Slf4j
public class JwtAuthenticationFilter extends OncePerRequestFilter {
private final JwtUtil jwtUtil;
- private final UserDetailsService userDetailsService;
+ private final JwtUserDetailsService jwtUserDetailsService;
@Override
protected void doFilterInternal(@NotNull HttpServletRequest request,
@@ -46,11 +44,11 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
String username = jwtUtil.parseToken(token).getSubject();
// 3. 根据username验证password
- UserDetails userDetails = userDetailsService.loadUserByUsername(username);
- log.info("userDetails: {}", userDetails);
+ UserPrincipal userPrincipal = jwtUserDetailsService.loadUserByUsername(username);
+ log.info("userPrincipal: {}", userPrincipal);
UsernamePasswordAuthenticationToken authenticationToken
- = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
+ = new UsernamePasswordAuthenticationToken(userPrincipal, null, userPrincipal.getAuthorities());
log.info("authenticationToken: {}", authenticationToken);
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
diff --git a/src/main/java/asia/yulinling/workflow/security/JwtUserDetailsService.java b/src/main/java/asia/yulinling/workflow/security/JwtUserDetailsService.java
index c32006a..3f86786 100644
--- a/src/main/java/asia/yulinling/workflow/security/JwtUserDetailsService.java
+++ b/src/main/java/asia/yulinling/workflow/security/JwtUserDetailsService.java
@@ -1,23 +1,22 @@
package asia.yulinling.workflow.security;
+import asia.yulinling.workflow.mapper.PermissionMapper;
import asia.yulinling.workflow.mapper.RoleMapper;
+import asia.yulinling.workflow.mapper.RoleUserMapper;
import asia.yulinling.workflow.mapper.UserMapper;
+import asia.yulinling.workflow.model.entity.Permission;
import asia.yulinling.workflow.model.entity.Role;
import asia.yulinling.workflow.model.entity.User;
+import asia.yulinling.workflow.model.vo.user.UserPrincipal;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
-import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.authority.SimpleGrantedAuthority;
-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;
-import java.util.Collections;
import java.util.List;
-import java.util.Set;
import java.util.stream.Collectors;
/**
@@ -34,41 +33,45 @@ import java.util.stream.Collectors;
public class JwtUserDetailsService implements UserDetailsService {
private final UserMapper userMapper;
private final RoleMapper roleMapper;
+ private final RoleUserMapper roleUserMapper;
+ private final PermissionMapper permissionMapper;
@Override
- public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
+ public UserPrincipal loadUserByUsername(String username) throws UsernameNotFoundException {
// 1. 构建查找sql
LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery(User.class)
- .eq(User::getUsername, username)
- .or()
- .eq(User::getEmail, username)
- .or()
- .eq(User::getPhone, username);
+ .eq(User::getUsername, username)
+ .or()
+ .eq(User::getEmail, username)
+ .or()
+ .eq(User::getPhone, username);
// 2. 查找用户
User user = userMapper.selectOne(queryWrapper);
if (user == null) {
+ log.error("未找到用户信息{}", username);
throw new UsernameNotFoundException("未找到用户信息:" + username);
}
+ log.info("username:{}", username);
// 3. 查找用户对应的角色
- List roles = roleMapper.selectByIds(Collections.singleton(user.getId()));
+ List roles = roleMapper.selectRoleByUserId(user.getId());
if (roles.isEmpty()) {
+ log.error("未找到角色信息{}", roles);
throw new UsernameNotFoundException("未找到角色信息" + roles);
}
- Set authorities = roles.stream()
- .map((role) -> new SimpleGrantedAuthority(role.getName()))
- .collect(Collectors.toSet());
+ List permissions = permissionMapper.selectPermissionsByRoleId(roles.stream().map(Role::getId).collect(Collectors.toList()));
+
+ if (permissions.isEmpty()) {
+ log.error("未找到权限信息{}", permissions);
+ throw new UsernameNotFoundException("未找到权限信息" + permissions);
+ }
// 4. 返回User
- return new org.springframework.security.core.userdetails.User(
- username,
- user.getPassword(),
- authorities
- );
+ return UserPrincipal.create(user, roles, permissions);
}
}
diff --git a/src/main/resources/mapper/PermissionMapper.xml b/src/main/resources/mapper/PermissionMapper.xml
new file mode 100644
index 0000000..c06be18
--- /dev/null
+++ b/src/main/resources/mapper/PermissionMapper.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/resources/mapper/RoleMapper.xml b/src/main/resources/mapper/RoleMapper.xml
new file mode 100644
index 0000000..f12b551
--- /dev/null
+++ b/src/main/resources/mapper/RoleMapper.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
\ No newline at end of file