zhoushihao
2024-04-25 2c2d541aa1c5060b47c1ba5c6e3d192b2ff82fef
fixbug:权限功能实现用户重复登录异常
9个文件已修改
1个文件已删除
439 ■■■■■ 已修改文件
hangzhoumesParent/common/springsecurity/src/main/java/com/mes/common/filter/JwtAuthenticationTokenFilter.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/springsecurity/src/main/java/com/mes/common/utils/RedisUtil.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/springsecurity/src/main/java/com/mes/menu/controller/SysMenuController.java 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/springsecurity/src/main/java/com/mes/menu/entity/SysMenu.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/springsecurity/src/main/java/com/mes/menu/service/impl/SysMenuServiceImpl.java 161 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/springsecurity/src/main/java/com/mes/role/controller/SysRoleController.java 117 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/springsecurity/src/main/java/com/mes/role/controller/SysRoleMenuController.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/springsecurity/src/main/java/com/mes/userinfo/entity/LoginUser.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/springsecurity/src/main/java/com/mes/userinfo/service/SysUserService.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/springsecurity/src/main/java/com/mes/userinfo/service/impl/SysUserServiceImpl.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/springsecurity/src/main/java/com/mes/common/filter/JwtAuthenticationTokenFilter.java
@@ -60,8 +60,10 @@
        String redisKey = "login:" + userid;
        LoginUser loginUser = redisUtil.getCacheObject(redisKey);
        if (Objects.isNull(loginUser)) {
            response.setHeader("token", "");
            throw new RuntimeException("用户未登录");
        }
        //存入SecurityContextHolder,以供后面的过滤器使用
        List<String> permissionKeyList = menuMapper.selectPermsByUserId(Long.parseLong(userid));
        List<GrantedAuthority> authorities = permissionKeyList.stream().
hangzhoumesParent/common/springsecurity/src/main/java/com/mes/common/utils/RedisUtil.java
@@ -217,4 +217,19 @@
    public Collection<String> keys(final String pattern) {
        return redisTemplate.keys(pattern);
    }
    /**
     * 判断key是否存在
     *
     * @param key 键
     * @return true 存在 false不存在
     */
    public boolean hasKey(String key) {
        try {
            return redisTemplate.hasKey(key);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
}
hangzhoumesParent/common/springsecurity/src/main/java/com/mes/menu/controller/SysMenuController.java
@@ -1,23 +1,17 @@
package com.mes.menu.controller;
import cn.hutool.core.map.MapUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.mes.base.BaseController;
import com.mes.menu.entity.SysMenu;
import com.mes.menu.service.SysMenuService;
import com.mes.role.entity.SysRoleMenu;
import com.mes.userinfo.entity.SysUser;
import com.mes.utils.Result;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
import java.util.List;
/**
@@ -32,10 +26,6 @@
@RestController
@RequestMapping("/menu/sysMenu")
public class SysMenuController extends BaseController {
    @Autowired
    SysMenuService sysMenuService;
    @ApiOperation("获取用户有权限的所有菜单")
    @GetMapping("/list")
    public Result<List<SysMenu>> getMenuTree(String userName) {
@@ -56,20 +46,21 @@
     */
    @GetMapping("/nav")
    public Result nav(String userName) {
        SysUser sysUser = sysUserService.getByUsername(userName);
        // 获取权限信息
        String authorityInfo = sysUserService.getUserAuthorityInfo(sysUser.getId());// ROLE_admin,ROLE_normal,sys:user:list,....
        String[] authorityInfoArray = StringUtils.tokenizeToStringArray(authorityInfo, ",");
        // 获取导航栏信息
        List<SysMenuDto> navs = sysMenuService.getCurrentUserNav();
        return Result.success(MapUtil.builder()
                .put("authoritys", authorityInfoArray)
                .put("nav", navs)
                .map()
        );
//        SysUser sysUser = sysUserService.listByUserNameName(userName);
//
//        // 获取权限信息
//       sysUserService.getUserAuthorityInfo(sysUser.getId());// ROLE_admin,ROLE_normal,sys:user:list,....
//        String[] authorityInfoArray = StringUtils.tokenizeToStringArray(authorityInfo, ",");
//
//        // 获取导航栏信息
//        List<SysMenuDto> navs = sysMenuService.getCurrentUserNav();
//
//        return Result.success(MapUtil.builder()
//                .put("authoritys", authorityInfoArray)
//                .put("nav", navs)
//                .map()
//        );
        return null;
    }
    @GetMapping("/info/{id}")
@@ -78,29 +69,23 @@
        return Result.success(sysMenuService.getById(id));
    }
    @GetMapping("/list")
    @PreAuthorize("hasAuthority('sys:menu:list')")
    public Result list() {
        List<SysMenu> menus = sysMenuService.tree();
        return Result.success(menus);
    }
//    @GetMapping("/list")
//    @PreAuthorize("hasAuthority('sys:menu:list')")
//    public Result list() {
//
////        List<SysMenu> menus = sysMenuService.tree();
//        return Result.success(null);
//    }
    @PostMapping("/save")
    @PreAuthorize("hasAuthority('sys:menu:save')")
    public Result save(@Validated @RequestBody SysMenu sysMenu) {
        sysMenu.setCreated(LocalDateTime.now());
        sysMenuService.save(sysMenu);
        return Result.success(sysMenu);
        return Result.success(sysMenuService.save(sysMenu));
    }
    @PostMapping("/update")
    @PreAuthorize("hasAuthority('sys:menu:update')")
    public Result update(@Validated @RequestBody SysMenu sysMenu) {
        sysMenu.setUpdated(LocalDateTime.now());
        sysMenuService.updateById(sysMenu);
@@ -115,7 +100,7 @@
        int count = sysMenuService.count(new QueryWrapper<SysMenu>().eq("parent_id", id));
        if (count > 0) {
            return Result.fail("请先删除子菜单");
            return Result.error("请先删除子菜单");
        }
        // 清除所有与该菜单相关的权限缓存
hangzhoumesParent/common/springsecurity/src/main/java/com/mes/menu/entity/SysMenu.java
@@ -30,7 +30,7 @@
     * 自增id
     */
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    private Long id;
    /**
     * 父id
hangzhoumesParent/common/springsecurity/src/main/java/com/mes/menu/service/impl/SysMenuServiceImpl.java
@@ -1,21 +1,17 @@
package com.mes.menu.service.impl;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mes.menu.entity.SysMenu;
import com.mes.menu.mapper.SysMenuMapper;
import com.mes.menu.service.SysMenuService;
import com.mes.userinfo.entity.SysUser;
import com.mes.userinfo.mapper.SysUserMapper;
import com.mes.userinfo.service.SysUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@@ -43,11 +39,12 @@
    @Override
    public List<String> getAuthorityInfo(String userName) {
        SysUser sysUser = sysUserService.listByUserName(userName);
        log.info("获取用户信息,用户名为{}", userName);
        SysUser sysUser = sysUserService.getOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUserName, userName));
        // 获取权限信息
        String authorityInfo = sysUserService.getUserAuthorityInfo(sysUser.getId());// ROLE_admin,ROLE_normal,sys:user:list,....
        String[] authorityInfoArray = StringUtils.tokenizeToStringArray(authorityInfo, ",");
        // ROLE_admin,ROLE_normal,sys:user:list,....
        return sysUserService.getUserAuthorityInfo(sysUser.getId());
    }
@@ -85,79 +82,79 @@
        return res;
    }
    @Autowired
    SysUserMapper sysUserMapper;
    @Override
    public List<SysMenuDto> getCurrentUserNav() {
        String username = (String) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        SysUser sysUser = sysUserService.getByUsername(username);
        List<Long> menuIds = sysUserMapper.getNavMenuIds(sysUser.getId());
        List<SysMenu> menus = this.listByIds(menuIds);
        // 转树状结构
        List<SysMenu> menuTree = buildTreeMenu(menus);
        // 实体转DTO
        return convert(menuTree);
    }
    @Override
    public List<SysMenu> tree() {
        // 获取所有菜单信息
        List<SysMenu> sysMenus = this.list(new QueryWrapper<SysMenu>().orderByAsc("orderNum"));
        // 转成树状结构
        return buildTreeMenu(sysMenus);
    }
    private List<SysMenuDto> convert(List<SysMenu> menuTree) {
        List<SysMenuDto> menuDtos = new ArrayList<>();
        menuTree.forEach(m -> {
            SysMenuDto dto = new SysMenuDto();
            dto.setId(m.getId());
            dto.setName(m.getPerms());
            dto.setTitle(m.getName());
            dto.setComponent(m.getComponent());
            dto.setPath(m.getPath());
            if (m.getChildren().size() > 0) {
                // 子节点调用当前方法进行再次转换
                dto.setChildren(convert(m.getChildren()));
            }
            menuDtos.add(dto);
        });
        return menuDtos;
    }
    private List<SysMenu> buildTreeMenu(List<SysMenu> menus) {
        List<SysMenu> finalMenus = new ArrayList<>();
        // 先各自寻找到各自的孩子
        for (SysMenu menu : menus) {
            for (SysMenu e : menus) {
                if (menu.getId() == e.getParentId()) {
                    menu.getChildren().add(e);
                }
            }
            // 提取出父节点
            if (menu.getParentId() == 0L) {
                finalMenus.add(menu);
            }
        }
        System.out.println(JSONUtil.toJsonStr(finalMenus));
        return finalMenus;
    }
//
//    @Autowired
//    SysUserMapper sysUserMapper;
//
//    @Override
//    public List<SysMenuDto> getCurrentUserNav() {
//        String username = (String) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
//        SysUser sysUser = sysUserService.listByUserNameName(username);
//
//        List<Long> menuIds = sysUserMapper.getNavMenuIds(sysUser.getId());
//        List<SysMenu> menus = this.listByIds(menuIds);
//
//        // 转树状结构
//        List<SysMenu> menuTree = buildTreeMenu(menus);
//
//        // 实体转DTO
//        return convert(menuTree);
//    }
//
//    @Override
//    public List<SysMenu> tree() {
//        // 获取所有菜单信息
//        List<SysMenu> sysMenus = this.list(new QueryWrapper<SysMenu>().orderByAsc("orderNum"));
//
//        // 转成树状结构
//        return buildTreeMenu(sysMenus);
//    }
//
//    private List<SysMenuDto> convert(List<SysMenu> menuTree) {
//        List<SysMenuDto> menuDtos = new ArrayList<>();
//
//        menuTree.forEach(m -> {
//            SysMenuDto dto = new SysMenuDto();
//
//            dto.setId(m.getId());
//            dto.setName(m.getPerms());
//            dto.setTitle(m.getName());
//            dto.setComponent(m.getComponent());
//            dto.setPath(m.getPath());
//
//            if (m.getChildren().size() > 0) {
//
//                // 子节点调用当前方法进行再次转换
//                dto.setChildren(convert(m.getChildren()));
//            }
//
//            menuDtos.add(dto);
//        });
//
//        return menuDtos;
//    }
//
//    private List<SysMenu> buildTreeMenu(List<SysMenu> menus) {
//
//        List<SysMenu> finalMenus = new ArrayList<>();
//
//        // 先各自寻找到各自的孩子
//        for (SysMenu menu : menus) {
//
//            for (SysMenu e : menus) {
//                if (menu.getId() == e.getParentId()) {
//                    menu.getChildren().add(e);
//                }
//            }
//
//            // 提取出父节点
//            if (menu.getParentId() == 0L) {
//                finalMenus.add(menu);
//            }
//        }
//
//        System.out.println(JSONUtil.toJsonStr(finalMenus));
//        return finalMenus;
//    }
}
hangzhoumesParent/common/springsecurity/src/main/java/com/mes/role/controller/SysRoleController.java
@@ -1,23 +1,9 @@
package com.mes.role.controller;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.mes.role.entity.SysRole;
import com.mes.role.entity.SysRoleMenu;
import com.mes.userinfo.entity.SysUserRole;
import com.mes.utils.Result;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import com.mes.base.BaseController;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
 * <p>
@@ -29,101 +15,6 @@
 */
@RestController
@RequestMapping("/role/sys-role")
public class SysRoleController {
    @PreAuthorize("hasAuthority('sys:role:list')")
    @GetMapping("/info/{id}")
    public Result info(@PathVariable("id") Long id) {
        SysRole sysRole = sysRoleService.getById(id);
        // 获取角色相关联的菜单id
        List<SysRoleMenu> roleMenus = sysRoleMenuService.list(new QueryWrapper<SysRoleMenu>().eq("role_id", id));
        List<Long> menuIds = roleMenus.stream().map(p -> p.getMenuId()).collect(Collectors.toList());
        sysRole.setMenuIds(menuIds);
        return Result.success(sysRole);
    }
    @PreAuthorize("hasAuthority('sys:role:list')")
    @GetMapping("/list")
    public Result list(String name) {
        Page<SysRole> pageData = sysRoleService.page(getPage(),
                new QueryWrapper<SysRole>()
                        .like(StrUtil.isNotBlank(name), "name", name)
        );
        return Result.success(pageData);
    }
    @PostMapping("/save")
    @PreAuthorize("hasAuthority('sys:role:save')")
    public Result save(@Validated @RequestBody SysRole sysRole) {
        sysRole.setCreated(LocalDateTime.now());
        sysRole.setStatu(Const.STATUS_ON);
        sysRoleService.save(sysRole);
        return Result.success(sysRole);
    }
    @PostMapping("/update")
    @PreAuthorize("hasAuthority('sys:role:update')")
    public Result update(@Validated @RequestBody SysRole sysRole) {
        sysRole.setUpdated(LocalDateTime.now());
        sysRoleService.updateById(sysRole);
        // 更新缓存
        sysUserService.clearUserAuthorityInfoByRoleId(sysRole.getId());
        return Result.success(sysRole);
    }
    @PostMapping("/delete")
    @PreAuthorize("hasAuthority('sys:role:delete')")
    @Transactional
    public Result info(@RequestBody Long[] ids) {
        sysRoleService.removeByIds(Arrays.asList(ids));
        // 删除中间表
        sysUserRoleService.remove(new QueryWrapper<SysUserRole>().in("role_id", ids));
        sysRoleMenuService.remove(new QueryWrapper<SysRoleMenu>().in("role_id", ids));
        // 缓存同步删除
        Arrays.stream(ids).forEach(id -> {
            // 更新缓存
            sysUserService.clearUserAuthorityInfoByRoleId(id);
        });
        return Result.success("");
    }
    @Transactional
    @PostMapping("/perm/{roleId}")
    @PreAuthorize("hasAuthority('sys:role:perm')")
    public Result info(@PathVariable("roleId") Long roleId, @RequestBody Long[] menuIds) {
        List<SysRoleMenu> sysRoleMenus = new ArrayList<>();
        Arrays.stream(menuIds).forEach(menuId -> {
            SysRoleMenu roleMenu = new SysRoleMenu();
            roleMenu.setMenuId(menuId);
            roleMenu.setRoleId(roleId);
            sysRoleMenus.add(roleMenu);
        });
        // 先删除原来的记录,再保存新的
        sysRoleMenuService.remove(new QueryWrapper<SysRoleMenu>().eq("role_id", roleId));
        sysRoleMenuService.saveBatch(sysRoleMenus);
        // 删除缓存
        sysUserService.clearUserAuthorityInfoByRoleId(roleId);
        return Result.success(menuIds);
    }
public class SysRoleController extends BaseController {
}
hangzhoumesParent/common/springsecurity/src/main/java/com/mes/role/controller/SysRoleMenuController.java
File was deleted
hangzhoumesParent/common/springsecurity/src/main/java/com/mes/userinfo/entity/LoginUser.java
@@ -28,7 +28,7 @@
    /**
     * 存储SpringSecurity调用getAuthorities()方法获取的权限信息的集合
     */
//    @JSONField(serialize = false)
    @JSONField(serialize = false)
    private List<GrantedAuthority> authorities;
hangzhoumesParent/common/springsecurity/src/main/java/com/mes/userinfo/service/SysUserService.java
@@ -72,4 +72,14 @@
     * @return
     */
    String deleteUser(List<Long> ids);
    /**
     * 获取用户角色权限信息
     *
     * @param userId
     * @return
     */
    List<String> getUserAuthorityInfo(Long userId);
    void clearUserAuthorityInfoByMenuId(Long userId);
}
hangzhoumesParent/common/springsecurity/src/main/java/com/mes/userinfo/service/impl/SysUserServiceImpl.java
@@ -9,6 +9,7 @@
import com.mes.common.utils.RedisUtil;
import com.mes.menu.mapper.SysMenuMapper;
import com.mes.role.entity.SysRole;
import com.mes.role.service.SysRoleService;
import com.mes.userinfo.entity.LoginUser;
import com.mes.userinfo.entity.SysUser;
import com.mes.userinfo.entity.SysUserRole;
@@ -35,6 +36,7 @@
import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
@@ -61,7 +63,10 @@
    @Resource
    private SysUserRoleService sysUserRoleService;
    @Autowired
    @Resource
    private SysRoleService sysRoleService;
    @Resource
    BCryptPasswordEncoder passwordEncoder;
    @Override
@@ -74,12 +79,12 @@
        //使用userid生成token
        LoginUser loginUser = (LoginUser) authenticate.getPrincipal();
        String userId = loginUser.getUser().getId().toString();
        String jwt = JwtUtil.createJWT(userId);
        String jwt = JwtUtil.generateToken(userId);
        //查询权限信息
//        List<String> perms = sysMenuMapper.selectPermsByUserId(userId);
        //authenticate存入redis
        redisUtil.setCacheObject("login:" + userId, loginUser.getAuthorities());
        redisUtil.setCacheObject("login:" + userId, loginUser);
        //把token响应给前端
        HashMap<String, String> map = new HashMap<>();
        map.put("token", jwt);
@@ -154,6 +159,42 @@
    }
    @Override
    public List<String> getUserAuthorityInfo(Long userId) {
        SysUser sysUser = baseMapper.selectById(userId);
        //  ROLE_admin,ROLE_normal,sys:user:list,....
        String authority = "";
        if (redisUtil.hasKey("GrantedAuthority:" + sysUser.getUserName())) {
            authority = redisUtil.getCacheObject("GrantedAuthority:" + sysUser.getUserName());
        } else {
            // 获取角色编码
            List<SysRole> roles = sysRoleService.list(new QueryWrapper<SysRole>()
                    .inSql("id", "select role_id from sys_user_role where user_id = " + userId));
            if (roles.size() > 0) {
                String roleCodes = roles.stream().map(r -> "ROLE_" + r.getRoleKey()).collect(Collectors.joining(","));
                authority = roleCodes.concat(",");
            }
            // 获取菜单操作编码
            List<String> perms = sysMenuMapper.selectPermsByUserId(userId);
            if (perms.size() > 0) {
                String menuPerms = String.join(",", perms);
                authority = authority.concat(menuPerms);
            }
            redisUtil.setCacheObject("GrantedAuthority:" + sysUser.getUserName(), authority, 60 * 60, TimeUnit.SECONDS);
        }
        return Arrays.stream(authority.split(",")).collect(Collectors.toList());
    }
    @Override
    public void clearUserAuthorityInfoByMenuId(Long userId) {
    }
    /**
     * 实现UserDetailsService接口,从数据库内获取用户及权限信息
     *