SpringBoot+Shiro配置数据库实现后台管理页面根据角色权限动态生成菜单栏
发布日期:2021-05-15 00:00:26 浏览次数:15 分类:精选文章

本文共 4819 字,大约阅读时间需要 16 分钟。

SpringBoot + Shiro后台管理系统权限配置方案

前言

使用SpringBoot和Shiro搭建后台管理系统时,传统的权限验证方式是通过在HTML页面中嵌入Shiro标签直接验证用户权限。这种方法虽然简单,但在菜单数量较多时容易导致页面臃肿,并且需要手动管理权限标识,容易出错。本文将介绍一种通过动态从数据库获取权限信息的方法,将菜单栏生成到页面中,解决传统方法的不足。

数据库设计

为了实现动态生成菜单栏,我们需要设计一个完整的数据库架构,包含以下表:

  • user表:存储用户信息。
  • user_role表:记录用户与角色的关系。
  • role表:存储系统角色信息。
  • permission表:存储系统权限信息。
  • role_permission表:记录角色与权限的映射关系。
  • menu表:存储菜单信息。
  • menu_move表:存储菜单之间的操作关系。
  • menu_permission表:存储菜单与权限的映射关系。
  • 系统实现

    Controller

    @GetMapping("/index")
    public String login(Model model) {
    if (!subject.isAuthenticated()) {
    return "/login";
    }
    String username = subject.getPrincipal().toString();
    List
    menuTree = menuService.findMenuTreeByUsername(username);
    model.addAttribute("menuTree", menuTree);
    return "index";
    }

    Service

    public interface MenuService extends IService {
    List
    findMenuTreeByUsername(String username);
    }

    Service Implementation

    @Service
    public class MenuServiceImpl extends ServiceImpl {
    private MenuMapper menuMapper;
    @Override
    public List
    findMenuTreeByUsername(String username) {
    return menuMapper.findMenuTreeByUsername(username);
    }
    }

    Mapper

    public interface MenuMapper extends BaseMapper {
    List
    findMenuTreeByUsername(String username);
    }

    XML映射文件

    VO对象

    @Data
    public class Menu {
    private Long id;
    private String menuName;
    private String menuUrl;
    private String menuIcon;
    private List
    subMenus;
    }

    页面渲染

    Shiro配置

    ShiroConfig

    @Bean("shiroFilter")
    public ShiroFilterFactoryBean shiroFilter(@Qualifier("securityManager") SecurityManager manager) {
    ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
    bean.setSecurityManager(manager);
    bean.setLoginUrl("/login");
    bean.setSuccessUrl("/index");
    bean.setUnauthorizedUrl("/auth.html");
    Map
    filterChainDefinitionMap = new LinkedHashMap<>();
    filterChainDefinitionMap.put("/index", "anon");
    filterChainDefinitionMap.put("/login", "anon");
    filterChainDefinitionMap.put("/static/**", "anon");
    filterChainDefinitionMap.put("/swagger-ui.html", "anon");
    filterChainDefinitionMap.put("/swagger-resources", "anon");
    filterChainDefinitionMap.put("/api/**", "anon");
    List
    permissionList = permissionMapper.getAll();
    for (Permission permission : permissionList) {
    filterChainDefinitionMap.put(permission.getResource(), "perms["+permission.getSn()+"]");
    }
    filterChainDefinitionMap.put("/**", "anon");
    bean.setFilterChainDefinitionMap(filterChainDefinitionMap);
    return bean;
    }

    PermissionMapper

    public interface PermissionMapper extends BaseMapper {
    List
    getAll();
    List
    getPermissionsByUserName(String username);
    }

    XML映射文件

    RoleMapper

    public interface RoleMapper extends BaseMapper {
    List
    getRolesByUserName(String username);
    }

    XML映射文件

    PermissionMapper

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
    log.info("Shiro开始授权操作");
    String username = SecurityUtils.getSubject().getPrincipal().toString();
    SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
    Set
    roles = new HashSet<>();
    List
    rolesList = roleMapper.getRolesByUserName(username);
    for (Role role : rolesList) {
    roles.add(role.getRoleName());
    }
    List
    permissionsList = permissionMapper.getPermissionsByUserName(username);
    for (Permission permission : permissionsList) {
    authorizationInfo.addStringPermission(permission.getSn());
    }
    authorizationInfo.setRoles(roles);
    return authorizationInfo;
    }

    总结

    通过这种方法,动态生成菜单栏的优点非常明显:只需在数据库中添加数据即可,无需手动管理Shiro标签,减少页面臃肿,提高可维护性。如果需要更具体的实现细节,可以参考全文获取完整代码。

    上一篇:七.Ribbon介绍及配置
    下一篇:SpringBoot返回前端时间格式化处理

    发表评论

    最新留言

    第一次来,支持一个
    [***.219.124.196]2025年04月11日 16时19分48秒