From cb884cc4cdd4fa153ecf9f5993bada5473dead4a Mon Sep 17 00:00:00 2001 From: FatttSnake Date: Thu, 18 May 2023 17:05:49 +0800 Subject: [PATCH] Added back-end permission verification --- .../cfive/pinnacle/config/SecurityConfig.java | 10 +-- .../pinnacle/controller/UserController.java | 2 + .../java/com/cfive/pinnacle/entity/User.java | 12 ++++ .../pinnacle/entity/permission/LoginUser.java | 20 +++++- .../filter/JwtAuthenticationTokenFilter.java | 3 +- .../handler/CustomAccessDeniedHandler.java | 19 ------ .../handler/CustomExceptionHandler.java | 4 ++ .../com/cfive/pinnacle/mapper/UserMapper.java | 2 + .../cfive/pinnacle/service/IUserService.java | 2 + .../service/impl/UserServiceImpl.java | 39 ++++++++++- .../permission/impl/LoginServiceImpl.java | 10 ++- .../impl/UserDetailsServiceImpl.java | 7 +- .../src/main/resources/mapper/UserMapper.xml | 68 +++++++++++++++++++ sql/Insert.sql | 34 ++++++++++ 14 files changed, 194 insertions(+), 38 deletions(-) delete mode 100644 Pinnacle/src/main/java/com/cfive/pinnacle/handler/CustomAccessDeniedHandler.java diff --git a/Pinnacle/src/main/java/com/cfive/pinnacle/config/SecurityConfig.java b/Pinnacle/src/main/java/com/cfive/pinnacle/config/SecurityConfig.java index c5a608a..1aaa7d1 100644 --- a/Pinnacle/src/main/java/com/cfive/pinnacle/config/SecurityConfig.java +++ b/Pinnacle/src/main/java/com/cfive/pinnacle/config/SecurityConfig.java @@ -1,7 +1,6 @@ package com.cfive.pinnacle.config; import com.cfive.pinnacle.filter.JwtAuthenticationTokenFilter; -import com.cfive.pinnacle.handler.CustomAccessDeniedHandler; import com.cfive.pinnacle.handler.CustomAuthenticationEntryPointHandler; import com.cfive.pinnacle.service.permission.impl.UserDetailsServiceImpl; import org.springframework.beans.factory.annotation.Autowired; @@ -9,6 +8,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; @@ -22,11 +22,11 @@ import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import java.util.List; @Configuration +@EnableMethodSecurity() public class SecurityConfig { private UserDetailsServiceImpl userDetailsService; private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter; private CustomAuthenticationEntryPointHandler authenticationEntryPointHandler; - private CustomAccessDeniedHandler accessDeniedHandler; @Autowired public void setUserDetailsService(UserDetailsServiceImpl userDetailsService) { @@ -43,11 +43,6 @@ public class SecurityConfig { this.authenticationEntryPointHandler = authenticationEntryPointHandler; } - @Autowired - public void setAccessDeniedHandler(CustomAccessDeniedHandler accessDeniedHandler) { - this.accessDeniedHandler = accessDeniedHandler; - } - @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); @@ -101,7 +96,6 @@ public class SecurityConfig { .exceptionHandling() .authenticationEntryPoint(authenticationEntryPointHandler) - .accessDeniedHandler(accessDeniedHandler) .and() .cors() diff --git a/Pinnacle/src/main/java/com/cfive/pinnacle/controller/UserController.java b/Pinnacle/src/main/java/com/cfive/pinnacle/controller/UserController.java index 4ec1da3..164ccaa 100644 --- a/Pinnacle/src/main/java/com/cfive/pinnacle/controller/UserController.java +++ b/Pinnacle/src/main/java/com/cfive/pinnacle/controller/UserController.java @@ -6,6 +6,7 @@ import com.cfive.pinnacle.entity.common.ResponseCode; import com.cfive.pinnacle.entity.common.ResponseResult; import com.cfive.pinnacle.service.IUserService; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.*; @@ -30,6 +31,7 @@ public class UserController { } @GetMapping + @PreAuthorize("hasAuthority('system:user:all')") public ResponseResult getAllUser() { List users = userService.getAllUser(); return ResponseResult.databaseSelectSuccess(users); diff --git a/Pinnacle/src/main/java/com/cfive/pinnacle/entity/User.java b/Pinnacle/src/main/java/com/cfive/pinnacle/entity/User.java index 0963bef..727879c 100644 --- a/Pinnacle/src/main/java/com/cfive/pinnacle/entity/User.java +++ b/Pinnacle/src/main/java/com/cfive/pinnacle/entity/User.java @@ -9,6 +9,9 @@ import java.io.Serial; import java.io.Serializable; import java.util.List; +import com.cfive.pinnacle.entity.permission.Element; +import com.cfive.pinnacle.entity.permission.Menu; +import com.cfive.pinnacle.entity.permission.Operation; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import lombok.Data; @@ -65,6 +68,15 @@ public class User implements Serializable { @TableField(exist = false) private List groups; + @TableField(exist = false) + private List menus; + + @TableField(exist = false) + private List elements; + + @TableField(exist = false) + private List operations; + @TableField("deleted") private Long deleted; diff --git a/Pinnacle/src/main/java/com/cfive/pinnacle/entity/permission/LoginUser.java b/Pinnacle/src/main/java/com/cfive/pinnacle/entity/permission/LoginUser.java index faa9d28..cb8176f 100644 --- a/Pinnacle/src/main/java/com/cfive/pinnacle/entity/permission/LoginUser.java +++ b/Pinnacle/src/main/java/com/cfive/pinnacle/entity/permission/LoginUser.java @@ -6,20 +6,38 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; @Data @NoArgsConstructor @AllArgsConstructor public class LoginUser implements UserDetails { private User user; + @JsonIgnore + private List authorities; + + public LoginUser(User user) { + this.user = user; + } + + public void setUser(User user) { + this.user = user; + } @JsonIgnore @Override public Collection getAuthorities() { - return null; + if (authorities != null) { + return authorities; + } + + authorities = user.getOperations().stream().map(operation -> new SimpleGrantedAuthority(operation.getCode())).collect(Collectors.toList()); + return authorities; } @JsonIgnore diff --git a/Pinnacle/src/main/java/com/cfive/pinnacle/filter/JwtAuthenticationTokenFilter.java b/Pinnacle/src/main/java/com/cfive/pinnacle/filter/JwtAuthenticationTokenFilter.java index 8b53e53..96489bb 100644 --- a/Pinnacle/src/main/java/com/cfive/pinnacle/filter/JwtAuthenticationTokenFilter.java +++ b/Pinnacle/src/main/java/com/cfive/pinnacle/filter/JwtAuthenticationTokenFilter.java @@ -54,8 +54,7 @@ public class JwtAuthenticationTokenFilter extends OncePerRequestFilter { return; } - // Todo 权限 - UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, null); + UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities()); SecurityContextHolder.getContext().setAuthentication(authenticationToken); filterChain.doFilter(request, response); diff --git a/Pinnacle/src/main/java/com/cfive/pinnacle/handler/CustomAccessDeniedHandler.java b/Pinnacle/src/main/java/com/cfive/pinnacle/handler/CustomAccessDeniedHandler.java deleted file mode 100644 index 905e1c2..0000000 --- a/Pinnacle/src/main/java/com/cfive/pinnacle/handler/CustomAccessDeniedHandler.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.cfive.pinnacle.handler; - -import com.cfive.pinnacle.entity.common.ResponseCode; -import com.cfive.pinnacle.utils.WebUtil; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import org.springframework.security.access.AccessDeniedException; -import org.springframework.stereotype.Component; - -import java.io.IOException; - -@Component -public class CustomAccessDeniedHandler implements org.springframework.security.web.access.AccessDeniedHandler { - @Override - public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException { - String objectResponse = WebUtil.objectResponse(ResponseCode.ACCESS_DENIED, "Access denied", null); - WebUtil.renderString(response, objectResponse); - } -} diff --git a/Pinnacle/src/main/java/com/cfive/pinnacle/handler/CustomExceptionHandler.java b/Pinnacle/src/main/java/com/cfive/pinnacle/handler/CustomExceptionHandler.java index 536ba97..df3ff5d 100644 --- a/Pinnacle/src/main/java/com/cfive/pinnacle/handler/CustomExceptionHandler.java +++ b/Pinnacle/src/main/java/com/cfive/pinnacle/handler/CustomExceptionHandler.java @@ -4,6 +4,7 @@ import com.cfive.pinnacle.entity.common.ResponseCode; import com.cfive.pinnacle.entity.common.ResponseResult; import lombok.extern.slf4j.Slf4j; import org.springframework.dao.DuplicateKeyException; +import org.springframework.security.access.AccessDeniedException; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; @@ -20,6 +21,9 @@ public class CustomExceptionHandler { if (e instanceof BadCredentialsException) { return ResponseResult.build(ResponseCode.LOGOUT_FAILED, e.getMessage(), null); } + if (e instanceof AccessDeniedException) { + return ResponseResult.build(ResponseCode.ACCESS_DENIED, e.getMessage(), null); + } log.debug(e.getMessage(), e); diff --git a/Pinnacle/src/main/java/com/cfive/pinnacle/mapper/UserMapper.java b/Pinnacle/src/main/java/com/cfive/pinnacle/mapper/UserMapper.java index 7e49980..408aa1c 100644 --- a/Pinnacle/src/main/java/com/cfive/pinnacle/mapper/UserMapper.java +++ b/Pinnacle/src/main/java/com/cfive/pinnacle/mapper/UserMapper.java @@ -20,4 +20,6 @@ public interface UserMapper extends BaseMapper { List getAll(); User getOneById(@Param("id") long id); + + User getOneWithPowerByUsername(@Param("username") String username); } diff --git a/Pinnacle/src/main/java/com/cfive/pinnacle/service/IUserService.java b/Pinnacle/src/main/java/com/cfive/pinnacle/service/IUserService.java index 53761e2..be9aac9 100644 --- a/Pinnacle/src/main/java/com/cfive/pinnacle/service/IUserService.java +++ b/Pinnacle/src/main/java/com/cfive/pinnacle/service/IUserService.java @@ -19,6 +19,8 @@ public interface IUserService extends IService { User getUser(long id); + User getUserWithPower(String username); + boolean addUser(User user); boolean modifyUser(User user); diff --git a/Pinnacle/src/main/java/com/cfive/pinnacle/service/impl/UserServiceImpl.java b/Pinnacle/src/main/java/com/cfive/pinnacle/service/impl/UserServiceImpl.java index 309a54d..a56d207 100644 --- a/Pinnacle/src/main/java/com/cfive/pinnacle/service/impl/UserServiceImpl.java +++ b/Pinnacle/src/main/java/com/cfive/pinnacle/service/impl/UserServiceImpl.java @@ -2,7 +2,13 @@ package com.cfive.pinnacle.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.cfive.pinnacle.entity.*; +import com.cfive.pinnacle.entity.permission.Element; +import com.cfive.pinnacle.entity.permission.Menu; +import com.cfive.pinnacle.entity.permission.Operation; import com.cfive.pinnacle.mapper.*; +import com.cfive.pinnacle.mapper.permission.ElementMapper; +import com.cfive.pinnacle.mapper.permission.MenuMapper; +import com.cfive.pinnacle.mapper.permission.OperationMapper; import com.cfive.pinnacle.service.IUserService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.springframework.beans.factory.annotation.Autowired; @@ -25,6 +31,9 @@ import java.util.List; @Service public class UserServiceImpl extends ServiceImpl implements IUserService { private UserMapper userMapper; + private MenuMapper menuMapper; + private ElementMapper elementMapper; + private OperationMapper operationMapper; private UserRoleMapper userRoleMapper; private UserGroupMapper userGroupMapper; private PasswordEncoder passwordEncoder; @@ -34,11 +43,25 @@ public class UserServiceImpl extends ServiceImpl implements IU this.userMapper = userMapper; } + @Autowired + public void setMenuMapper(MenuMapper menuMapper) { + this.menuMapper = menuMapper; + } + + @Autowired + public void setElementMapper(ElementMapper elementMapper) { + this.elementMapper = elementMapper; + } + + @Autowired + public void setOperationMapper(OperationMapper operationMapper) { + this.operationMapper = operationMapper; + } + @Autowired public void setUserRoleMapper(UserRoleMapper userRoleMapper) { this.userRoleMapper = userRoleMapper; } - @Autowired public void setUserGroupMapper(UserGroupMapper userGroupMapper) { this.userGroupMapper = userGroupMapper; @@ -71,6 +94,20 @@ public class UserServiceImpl extends ServiceImpl implements IU return user; } + @Override + public User getUserWithPower(String username) { + User user = userMapper.getOneWithPowerByUsername(username); + if (user.getId() == 1L) { + List menus = menuMapper.selectList(null); + List elements = elementMapper.selectList(null); + List operations = operationMapper.selectList(null); + user.setMenus(menus); + user.setElements(elements); + user.setOperations(operations); + } + return user; + } + @Override @Transactional public boolean addUser(User user) { diff --git a/Pinnacle/src/main/java/com/cfive/pinnacle/service/permission/impl/LoginServiceImpl.java b/Pinnacle/src/main/java/com/cfive/pinnacle/service/permission/impl/LoginServiceImpl.java index a080400..946bf8b 100644 --- a/Pinnacle/src/main/java/com/cfive/pinnacle/service/permission/impl/LoginServiceImpl.java +++ b/Pinnacle/src/main/java/com/cfive/pinnacle/service/permission/impl/LoginServiceImpl.java @@ -5,6 +5,8 @@ import com.cfive.pinnacle.entity.permission.LoginUser; import com.cfive.pinnacle.service.permission.ILoginService; import com.cfive.pinnacle.utils.JwtUtil; import com.cfive.pinnacle.utils.RedisCache; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; @@ -41,7 +43,13 @@ public class LoginServiceImpl implements ILoginService { LoginUser loginUser = (LoginUser) authentication.getPrincipal(); loginUser.getUser().setPasswd(""); String userId = loginUser.getUser().getId().toString(); - String jwt = JwtUtil.createJWT(userId); + String jwt; + try { + jwt = JwtUtil.createJWT(new ObjectMapper().writeValueAsString(loginUser.getUser())); + } catch (JsonProcessingException e) { + jwt = JwtUtil.createJWT(userId); + } + HashMap hashMap = new HashMap<>(); hashMap.put("token", jwt); diff --git a/Pinnacle/src/main/java/com/cfive/pinnacle/service/permission/impl/UserDetailsServiceImpl.java b/Pinnacle/src/main/java/com/cfive/pinnacle/service/permission/impl/UserDetailsServiceImpl.java index 4943a6c..eff6243 100644 --- a/Pinnacle/src/main/java/com/cfive/pinnacle/service/permission/impl/UserDetailsServiceImpl.java +++ b/Pinnacle/src/main/java/com/cfive/pinnacle/service/permission/impl/UserDetailsServiceImpl.java @@ -1,6 +1,5 @@ package com.cfive.pinnacle.service.permission.impl; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.cfive.pinnacle.entity.User; import com.cfive.pinnacle.entity.permission.LoginUser; import com.cfive.pinnacle.service.IUserService; @@ -25,15 +24,11 @@ public class UserDetailsServiceImpl implements UserDetailsService { @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(User::getUsername, username); - User user = userService.getOne(wrapper); + User user = userService.getUserWithPower(username); if (Objects.isNull(user)) { throw new UsernameNotFoundException("Username not found in database"); } - // Todo 权限 - return new LoginUser(user); } } diff --git a/Pinnacle/src/main/resources/mapper/UserMapper.xml b/Pinnacle/src/main/resources/mapper/UserMapper.xml index 173b9db..761c85d 100644 --- a/Pinnacle/src/main/resources/mapper/UserMapper.xml +++ b/Pinnacle/src/main/resources/mapper/UserMapper.xml @@ -47,6 +47,43 @@ where t_user.deleted = 0 and t_user.id = #{id}; + @@ -68,4 +105,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sql/Insert.sql b/sql/Insert.sql index d6d9afe..8fc35f9 100644 --- a/sql/Insert.sql +++ b/sql/Insert.sql @@ -143,3 +143,37 @@ from t_user left join (select * from t_group where deleted = 0) as tg on tg.id = tug.group_id where t_user.deleted = 0; +select distinct t_user.id as user_id, + t_user.username as user_username, + t_user.passwd as user_passwd, + t_user.department_id as user_department, + t_user.enable as user_enable, + t_user.deleted as user_deleted, + t_user.version as user_version, + tm.id as menu_id, + tm.name as menu_name, + tm.url as menu_url, + tm.power_id as menu_powerId, + tm.parent_id as menu_parentId, + te.id as element_id, + te.name as element_name, + te.power_id as element_powerId, + te.menu_id as element_menuId, + t.id as operation_id, + t.name as operation_name, + t.code as operation_code, + t.power_id as operation_powerId, + t.element_id as operation_elementId, + t.parent_id as operation_parentId +from t_user + left join (select * from t_user_group where deleted = 0) as tug on t_user.id = tug.user_id + left join (select * from t_group where deleted = 0) as tg on tg.id = tug.group_id + left join (select * from t_role_group where deleted = 0) as trg on tg.id = trg.group_id + left join (select * from t_user_role where deleted = 0) as tur on t_user.id = tur.user_id + left join (select * from t_role where deleted = 0) as tr on tr.id = trg.role_id or tr.id = tur.role_id + left join (select * from t_power_role where deleted = 0) as tpr on tpr.role_id = tr.id + left join t_power as tp on tp.id = tpr.power_id + left join t_menu tm on tp.id = tm.power_id + left join t_element te on tp.id = te.power_id + left join t_operation t on tp.id = t.power_id +where t_user.deleted = 0; \ No newline at end of file