SpringMVC集成shiro

- 日理万妓 2021-12-09 14:59 581阅读 0赞

最近公司一个老的后台管理系统需要加权限验证(前端使用easyUI),经过各种踩坑,终于是完成了,话不多说,直接进入主题
数据库结构
用户表(使用的项目本身已经在用的表)

  1. CREATE TABLE `pay_user` (
  2. `ID` INT(11) NOT NULL AUTO_INCREMENT COMMENT 'ID主键',
  3. `USER_NAME` VARCHAR(45) NOT NULL COMMENT '登录名称',
  4. `PASSWORD` VARCHAR(50) NOT NULL COMMENT '密码',
  5. `STATUS` VARCHAR(1) NOT NULL DEFAULT '0' COMMENT '状态:0:正常,1:禁用;default:0',
  6. `CREATE_TIME` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  7. `UPDATE_TIME` DATETIME NULL DEFAULT NULL COMMENT '更新时间',
  8. PRIMARY KEY (`ID`),
  9. UNIQUE INDEX `ID_UNIQUE` (`ID`) USING BTREE,
  10. UNIQUE INDEX `USER_NAME_UK` (`USER_NAME`) USING BTREE
  11. )
  12. COMMENT='运营管理用户表'
  13. COLLATE='utf8_general_ci'
  14. ENGINE=InnoDB
  15. AUTO_INCREMENT=48
  16. ;

菜单表

  1. CREATE TABLE `sys_menu` (
  2. `id` BIGINT(8) NOT NULL AUTO_INCREMENT COMMENT '主键',
  3. `name` VARCHAR(64) NOT NULL COMMENT '菜单名称',
  4. `icon` VARCHAR(64) NOT NULL DEFAULT 'icon-nav' COMMENT '图标',
  5. `url` VARCHAR(255) NULL DEFAULT NULL COMMENT '菜单路径',
  6. `pid` BIGINT(8) UNSIGNED NOT NULL DEFAULT '0' COMMENT '父级资源id',
  7. `sort` TINYINT(2) NOT NULL DEFAULT '0' COMMENT '排序',
  8. `permission_code` VARCHAR(50) NULL DEFAULT NULL COMMENT '权限层级',
  9. `status` TINYINT(2) NOT NULL DEFAULT '0' COMMENT '状态',
  10. `menu_flag` TINYINT(1) NULL DEFAULT '0' COMMENT '是否是菜单 0主菜单 1页面 2按钮',
  11. `description` VARCHAR(255) NULL DEFAULT NULL COMMENT '备注',
  12. `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  13. `update_time` DATETIME NULL DEFAULT NULL COMMENT '更新时间',
  14. PRIMARY KEY (`id`)
  15. )
  16. COMMENT='菜单'
  17. COLLATE='utf8_general_ci'
  18. ENGINE=InnoDB
  19. AUTO_INCREMENT=297
  20. ;

角色表(这里当时有个设计缺陷就是应该多加一个code字段)

  1. CREATE TABLE `sys_role` (
  2. `id` BIGINT(19) NOT NULL AUTO_INCREMENT COMMENT '主键id',
  3. `name` VARCHAR(64) NOT NULL COMMENT '角色名',
  4. `sort` TINYINT(2) NOT NULL DEFAULT '0' COMMENT '排序号',
  5. `description` VARCHAR(255) NULL DEFAULT NULL COMMENT '描述',
  6. `create_time` DATETIME NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  7. `update_time` DATETIME NULL DEFAULT NULL COMMENT '更新时间',
  8. PRIMARY KEY (`id`)
  9. )
  10. COMMENT='角色'
  11. COLLATE='utf8_general_ci'
  12. ENGINE=InnoDB
  13. AUTO_INCREMENT=7
  14. ;

角色-菜单关系表

  1. CREATE TABLE `sys_role_menu` (
  2. `id` BIGINT(8) NOT NULL AUTO_INCREMENT COMMENT '主键id',
  3. `role_id` BIGINT(8) NOT NULL COMMENT '角色id',
  4. `menu_id` BIGINT(8) NOT NULL COMMENT '菜单id',
  5. PRIMARY KEY (`id`)
  6. )
  7. COMMENT='角色-菜单关系表'
  8. COLLATE='utf8_general_ci'
  9. ENGINE=InnoDB
  10. AUTO_INCREMENT=2763
  11. ;

用户-角色关系表

  1. CREATE TABLE `sys_user_role` (
  2. `id` BIGINT(8) NOT NULL AUTO_INCREMENT COMMENT '主键id',
  3. `user_id` BIGINT(8) NOT NULL COMMENT '用户id',
  4. `role_id` BIGINT(8) NOT NULL COMMENT '角色id',
  5. PRIMARY KEY (`id`)
  6. )
  7. COMMENT='用户-角色关系表'
  8. COLLATE='utf8_general_ci'
  9. ENGINE=InnoDB
  10. AUTO_INCREMENT=28
  11. ;

1.首先引入依赖

  1. <!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-web -->
  2. <dependency>
  3. <groupId>org.apache.shiro</groupId>
  4. <artifactId>shiro-web</artifactId>
  5. <version>1.4.0</version>
  6. </dependency>
  7. <!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-spring -->
  8. <dependency>
  9. <groupId>org.apache.shiro</groupId>
  10. <artifactId>shiro-spring</artifactId>
  11. <version>1.4.0</version>
  12. </dependency>
  13. <!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-ehcache -->
  14. <dependency>
  15. <groupId>org.apache.shiro</groupId>
  16. <artifactId>shiro-ehcache</artifactId>
  17. <version>1.4.0</version>
  18. </dependency>
  19. <dependency>
  20. <groupId>org.apache.shiro</groupId>
  21. <artifactId>shiro-core</artifactId>
  22. <version>1.4.0</version>
  23. </dependency>

当然像ehcache如果用不到可以不添加

2.web.xml配置
添加配置

  1. <!--<!–Shiro配置 DelegatingFilterProxy通过代理模式将spring容器中的bean和filter关联起来–>-->
  2. <filter>
  3. <filter-name>shiroFilter</filter-name>
  4. <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
  5. <!-- 设置true由servlet容器控制filter的生命周期 -->
  6. <init-param>
  7. <param-name>targetFilterLifecycle</param-name>
  8. <param-value>true</param-value>
  9. </init-param>
  10. </filter>
  11. <filter-mapping>
  12. <filter-name>shiroFilter</filter-name>
  13. <url-pattern>/*</url-pattern>
  14. </filter-mapping>

3.spring-shiro.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
  4. xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
  5. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  6. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
  7. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
  8. http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
  9. http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">
  10. <!-- shiro -->
  11. <!-- 1. 将Shiro的生命周期加入Spring
  12. <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
  13. -->
  14. <!-- 凭证匹配器 -->
  15. <bean id="credentialsMatcher"
  16. class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
  17. <property name="hashAlgorithmName" value="md5"/>
  18. <property name="hashIterations" value="1"/>
  19. </bean>
  20. <!-- 2. 自定义Realm来管理权限 -->
  21. <bean id="shiroDbRealm" class="com.joiest.jpf.manage.web.shiro.ShiroDbRealm">
  22. <property name="credentialsMatcher" ref="credentialsMatcher"/>
  23. </bean>
  24. <!--<!– 缓存管理器 –>-->
  25. <!--<bean id="cacheMnager" class="org.apache.shiro.cache.ehcache.EhCacheManager">-->
  26. <!--<property name="cacheManagerConfigFile" value="classpath:spring/shiro-ehcache.xml"/>-->
  27. <!--</bean>-->
  28. <!--<!– 会话管理器 –>-->
  29. <!--<bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">-->
  30. <!--<!– session的失效时长,单位毫秒 –>-->
  31. <!--<property name="globalSessionTimeout" value="1800000"/>-->
  32. <!--<!– 删除失效的session –>-->
  33. <!--<property name="deleteInvalidSessions" value="true"/>-->
  34. <!--</bean>-->
  35. <!-- 3. 将自定义Realm赋值给securityManager -->
  36. <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
  37. <property name="realm" ref="shiroDbRealm"/>
  38. <!--<property name="sessionManager" ref="sessionManager" />-->
  39. <!--<property name="cacheManager" ref="cacheMnager" />-->
  40. </bean>
  41. <!-- 4. 配置SecurityUtils将securityManager-->
  42. <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
  43. <property name="staticMethod" value="org.apache.shiro.SecurityUtils.setSecurityManager"/>
  44. <property name="arguments" ref="securityManager"/>
  45. </bean>
  46. <!-- 5. 配置shiroFilter-->
  47. <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
  48. <!-- Shiro的核心安全接口,这个属性是必须的 -->
  49. <property name="securityManager" ref="securityManager"/>
  50. <!-- 要求登录时的链接(登录页面地址),非必须的属性,默认会自动寻找Web工程根目录下的"/login.jsp"页面 -->
  51. <property name="loginUrl" value="/"/>
  52. <!-- 登录成功后要跳转的连接(本例中此属性用不到,因为登录成功后的处理逻辑在页面处理的) -->
  53. <property name="successUrl" value="/backIndex.jsp" ></property>
  54. <!-- 用户访问未对其授权的资源时,所显示的连接 -->
  55. <property name="unauthorizedUrl" value="/refuse.jsp"></property>
  56. <!-- 过虑器链定义,从上向下顺序执行,一般将/**放在最下边 -->
  57. <property name="filterChainDefinitionMap" ref="filterChainDefinitionMap">
  58. </property>
  59. <property name="filterChainDefinitions">
  60. <value>
  61. <!-- anon不需要认证-->
  62. <!--/login = anon-->
  63. /resources/** = anon
  64. /user/login = anon
  65. /user/logout = anon
  66. <!--这里可以控制地址栏输入url也进行拦截,但是这样配置太繁琐,下篇文章会扩展-->
  67. /user/index = perms["userManage:all"]
  68. <!--/user/index = anon-->
  69. <!--所有的请求(除去配置的静态资源请求或请求地址为anon的请求)都要通过登录验证,如果未登录则跳到/login -->
  70. /** = authc
  71. </value>
  72. </property>
  73. </bean>
  74. </beans>

4.创建自定义Realm

  1. package com.joiest.jpf.manage.web.shiro;
  2. import com.joiest.jpf.common.po.SysMenu;
  3. import com.joiest.jpf.common.po.SysRoleMenu;
  4. import com.joiest.jpf.common.po.SysUserRole;
  5. import com.joiest.jpf.common.util.Md5Encrypt;
  6. import com.joiest.jpf.common.util.SHA1;
  7. import com.joiest.jpf.entity.UserInfo;
  8. import com.joiest.jpf.facade.SysMenuFacade;
  9. import com.joiest.jpf.facade.SysRoleMenuFacade;
  10. import com.joiest.jpf.facade.SysUserRoleFacade;
  11. import com.joiest.jpf.facade.UserServiceFacade;
  12. import org.apache.commons.lang3.StringUtils;
  13. import org.apache.shiro.authc.*;
  14. import org.apache.shiro.authz.AuthorizationInfo;
  15. import org.apache.shiro.authz.SimpleAuthorizationInfo;
  16. import org.apache.shiro.realm.AuthorizingRealm;
  17. import org.apache.shiro.subject.PrincipalCollection;
  18. import org.apache.shiro.util.ByteSource;
  19. import org.springframework.beans.factory.annotation.Autowired;
  20. import java.util.ArrayList;
  21. import java.util.HashSet;
  22. import java.util.List;
  23. public class ShiroDbRealm extends AuthorizingRealm {
  24. @Autowired
  25. private UserServiceFacade userServiceFacade;
  26. @Autowired
  27. private SysUserRoleFacade sysUserRoleFacade;
  28. @Autowired
  29. private SysRoleMenuFacade sysRoleMenuFacade;
  30. @Autowired
  31. private SysMenuFacade sysMenuFacade;
  32. //认证
  33. @Override
  34. protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
  35. System.out.println("=================doGetAuthenticationInfo[登录认证]=====================");
  36. UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
  37. System.out.println("当前认证用户:" + token.getUsername());
  38. UserInfo user = userServiceFacade.getByLoginName(token.getUsername());
  39. if (user != null) {
  40. ShiroUser shiroUser = new ShiroUser(user.getUserName());
  41. shiroUser.setId(user.getId()+"");
  42. shiroUser.setName(user.getUserName());
  43. //以创建时间作为盐(加密用的)
  44. // String salt = String.valueOf(user.getCreateTime().getTime());
  45. return new SimpleAuthenticationInfo(shiroUser, Md5Encrypt.md5(user.getPassword()), getName());
  46. }
  47. return null;
  48. }
  49. //授权
  50. @Override
  51. protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
  52. System.out.println("=================doGetAuthorizationInfo[授权认证]=====================");
  53. ShiroUser shiroUser = (ShiroUser) principalCollection.getPrimaryPrincipal();
  54. SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
  55. List<String> permissions = new ArrayList<>();
  56. //由于炒鸡管理员权限太多,加载每次点击菜单加载数据很慢,所以这里用了缓存,只第一次加载
  57. if (shiroUser.getPermissions()==null || shiroUser.getPermissions().size() == 0){
  58. //获取所有权限
  59. List<SysUserRole> sysUserRoles =sysUserRoleFacade.selectRolesByUserId(shiroUser.getId());
  60. for (SysUserRole sysUserRole : sysUserRoles) {
  61. List<SysRoleMenu> sysRoleMenus = sysRoleMenuFacade.getRoleMenuByRoleId(sysUserRole.getRoleId());
  62. if (sysRoleMenus.size()>0){
  63. for (SysRoleMenu sysRoleMenu : sysRoleMenus) {
  64. SysMenu menu = sysMenuFacade.getMenuById(sysRoleMenu.getMenuId());
  65. if(menu!=null&& StringUtils.isNotBlank(menu.getPermissionCode())){
  66. permissions.add(menu.getPermissionCode());
  67. }
  68. }
  69. }
  70. }
  71. shiroUser.setPermissions(new HashSet<>(permissions));
  72. info.addStringPermissions(permissions);
  73. }else{
  74. //info里存的就是所有的权限
  75. info.addStringPermissions(shiroUser.getPermissions());
  76. }
  77. return info;
  78. }
  79. }

5.User类 shiroUser

  1. package com.joiest.jpf.manage.web.shiro;
  2. import java.io.Serializable;
  3. import java.util.Set;
  4. public class ShiroUser implements Serializable {
  5. private String id;
  6. private final String loginName;
  7. private String name;
  8. private Set<String> permissions;
  9. public String getId() {
  10. return id;
  11. }
  12. public void setId(String id) {
  13. this.id = id;
  14. }
  15. public ShiroUser(String loginName) {
  16. this.loginName = loginName;
  17. }
  18. public String getLoginName() {
  19. return loginName;
  20. }
  21. public String getName() {
  22. return name;
  23. }
  24. public void setName(String name) {
  25. this.name = name;
  26. }
  27. public Set<String> getPermissions() {
  28. return permissions;
  29. }
  30. public void setPermissions(Set<String> permissions) {
  31. this.permissions = permissions;
  32. }
  33. }

6.Tree

  1. package com.joiest.jpf.entity;
  2. import java.io.Serializable;
  3. import java.util.Date;
  4. import java.util.List;
  5. public class Tree implements Serializable {
  6. private Integer id;
  7. private String text;
  8. private int seq;
  9. private boolean checked = false;// true,false
  10. private boolean onlyLeafCheck = false;
  11. private String state = "open";
  12. private String code;
  13. private List<Tree> children;
  14. private String iconCls;
  15. private Integer pid;
  16. private Integer isLeaf;
  17. private String url;
  18. private String createTime;
  19. private String updateTime;
  20. public String getState() {
  21. return state;
  22. }
  23. public void setState(String state) {
  24. this.state = state;
  25. }
  26. public boolean getOnlyLeafCheck() {
  27. return onlyLeafCheck;
  28. }
  29. public void setOnlyLeafCheck(boolean onlyLeafCheck) {
  30. this.onlyLeafCheck = onlyLeafCheck;
  31. }
  32. public Integer getId() {
  33. return id;
  34. }
  35. public void setId(Integer id) {
  36. this.id = id;
  37. }
  38. public String getText() {
  39. return text;
  40. }
  41. public void setText(String text) {
  42. this.text = text;
  43. }
  44. public boolean getChecked() {
  45. return checked;
  46. }
  47. public void setChecked(boolean checked) {
  48. this.checked = checked;
  49. }
  50. public String getCode() {
  51. return code;
  52. }
  53. public void setCode(String code) {
  54. this.code = code;
  55. }
  56. public List<Tree> getChildren() {
  57. return children;
  58. }
  59. public void setChildren(List<Tree> children) {
  60. this.children = children;
  61. }
  62. public String getIconCls() {
  63. return iconCls;
  64. }
  65. public void setIconCls(String iconCls) {
  66. this.iconCls = iconCls;
  67. }
  68. public Integer getPid() {
  69. return pid;
  70. }
  71. public void setPid(Integer pid) {
  72. this.pid = pid;
  73. }
  74. public Integer getIsLeaf() {
  75. return isLeaf;
  76. }
  77. public void setIsLeaf(Integer isLeaf) {
  78. this.isLeaf = isLeaf;
  79. }
  80. public String getUrl() {
  81. return url;
  82. }
  83. public void setUrl(String url) {
  84. this.url = url;
  85. }
  86. public int getSeq() {
  87. return seq;
  88. }
  89. public void setSeq(int seq) {
  90. this.seq = seq;
  91. }
  92. public String getCreateTime() {
  93. return createTime;
  94. }
  95. public void setCreateTime(String createTime) {
  96. this.createTime = createTime;
  97. }
  98. public String getUpdateTime() {
  99. return updateTime;
  100. }
  101. public void setUpdateTime(String updateTime) {
  102. this.updateTime = updateTime;
  103. }
  104. }

7.登录 调用shiro的login()方法

  1. @RequestMapping(value = "/user/login", method = RequestMethod.POST)
  2. public ModelAndView login(HttpServletRequest request,HttpSession httpSession, Model model) {
  3. String loginName = request.getParameter("user");
  4. String password = request.getParameter("pwd");
  5. Subject user = SecurityUtils.getSubject();
  6. UsernamePasswordToken token = new UsernamePasswordToken(loginName, SHA1.getInstance().getMySHA1Code(password));
  7. if (StringUtils.isBlank(loginName)||StringUtils.isBlank(password)) {
  8. model.addAttribute("error", "用户名或密码错误");
  9. return new ModelAndView("login");
  10. }
  11. UserInfo info = userServiceFacade.getByLoginName(loginName);
  12. if (info == null){
  13. model.addAttribute("error", "用户不存在或者密码错误!");
  14. return new ModelAndView("login");
  15. }
  16. if (!EnumConstants.UserStatus.normal.value().equals(info.getStatus())){
  17. model.addAttribute("error", "用户已禁用!");
  18. return new ModelAndView("login");
  19. }
  20. List<SysUserRole> userRoles = sysUserRoleFacade.selectRolesByUserId(info.getId() + "");
  21. if (userRoles.size() == 0){
  22. model.addAttribute("error", "用户未分配角色,请联系管理员!");
  23. return new ModelAndView("login");
  24. }
  25. try {
  26. //shiro的login()方法
  27. user.login(token);
  28. } catch (UnknownAccountException e) {
  29. model.addAttribute("error", "用户不存在或者密码错误!");
  30. return new ModelAndView("login");
  31. } catch (IncorrectCredentialsException ex) {
  32. model.addAttribute("error","用户不存在或者密码错误!") ;
  33. return new ModelAndView("login");
  34. } catch (AuthenticationException ex) {
  35. model.addAttribute("error","用户名或密码错误");
  36. return new ModelAndView("login");
  37. } catch (Exception ex) {
  38. model.addAttribute("error","内部错误,请重试!");
  39. return new ModelAndView("login");
  40. }
  41. PayUser userInfo = userServiceFacade.loginVerify(loginName, password);
  42. //登录信息存进session
  43. httpSession.setAttribute(ManageConstants.USERINFO_SESSION,userInfo);
  44. httpSession.setMaxInactiveInterval(30*60);//以秒为单位,即在没有活动30分钟后,session将失效
  45. return new ModelAndView("/backIndex");
  46. }

8.跳转到首页后发送ajax请求(/menu)查询当前用户下的所有菜单

controller

  1. @RequestMapping("/menu")
  2. @ResponseBody
  3. public Object getMenu(){
  4. UserInfo sessionUser = SessionUtil.getSessionUser();
  5. Integer id = sessionUser.getId();
  6. List<Tree> treeList = sysMenuFacade.treeList(id);
  7. JSONArray jsonArray = JSONArray.parseArray(JSON.toJSONString(treeList));
  8. return jsonArray;
  9. }

serviceImpl

  1. @Override
  2. public List<Tree> treeList(Integer id) {
  3. List<SysMenu> menuList = sysMenuMapper.selectMenuListByUserId(id);
  4. List<Tree> treeList = prepareTree(menuList);
  5. //排序调整菜单顺序
  6. Collections.sort(treeList, new Comparator<Tree>() {
  7. @Override
  8. public int compare(Tree t1, Tree t2) {
  9. return t1.getSeq() - t2.getSeq();
  10. }
  11. });
  12. return treeList;
  13. }
  14. private List<Tree> prepareTree(List<SysMenu> menuList) {
  15. List<Tree> allTreeList = menuListToTreeList(menuList);
  16. List<Tree> topList = new ArrayList<>();
  17. for (Tree tree : allTreeList) {
  18. // 遍历所有节点,将父菜单id与传过来的id比较
  19. if (tree.getPid() == 0) {
  20. tree.setChildren(prepareTreeChiled(tree.getId(), allTreeList));
  21. topList.add(tree);
  22. Collections.sort(topList, new Comparator<Tree>() {
  23. @Override
  24. public int compare(Tree o1, Tree o2) {
  25. return o1.getSeq() - o2.getSeq();
  26. }
  27. });
  28. }
  29. }
  30. return topList;
  31. }
  32. private List<Tree> prepareTreeChiled(Integer id, List<Tree> allTreeList) {
  33. // 子菜单
  34. List<Tree> childList = new ArrayList<>();
  35. for (Tree tree : allTreeList) {
  36. // 遍历所有节点,将父菜单id与传过来的id比较
  37. //这里有个坑 因为常量池里127 == 127是成立的 129 == 129不成立 所以比较用equals
  38. if (!"0".equals(tree.getPid()+"") && (id+"").equals(tree.getPid()+"")) {
  39. childList.add(tree);
  40. Collections.sort(childList, new Comparator<Tree>() {
  41. @Override
  42. public int compare(Tree o1, Tree o2) {
  43. return o1.getSeq() - o2.getSeq();
  44. }
  45. });
  46. }
  47. }
  48. // 把子菜单的子菜单再循环一遍
  49. for (Tree tree : childList) {
  50. tree.setChildren(prepareTreeChiled(tree.getId(), allTreeList));
  51. }
  52. // 递归退出条件
  53. if (childList.size() == 0) {
  54. return null;
  55. }
  56. return childList;
  57. }
  58. private List<Tree> menuListToTreeList(List<SysMenu> menuList) {
  59. List<Tree> treeList = new ArrayList<>();
  60. if (menuList != null && menuList.size() > 0) {
  61. for (SysMenu menu : menuList) {
  62. treeList.add(menuToTree(menu));
  63. }
  64. }
  65. return treeList;
  66. }
  67. private Tree menuToTree(SysMenu menu) {
  68. Tree tree = new Tree();
  69. tree.setId(Integer.valueOf(menu.getId()));
  70. tree.setText(menu.getName());
  71. tree.setIconCls(menu.getIcon());
  72. tree.setIsLeaf(Integer.valueOf(menu.getMenuFlag()));
  73. tree.setPid(Integer.valueOf(menu.getPid()));
  74. tree.setSeq(menu.getSort());
  75. tree.setUrl(menu.getUrl());
  76. tree.setCode(menu.getPermissionCode());
  77. tree.setChecked(menu.getChecked());
  78. SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  79. String createTime = formatter.format(menu.getCreateTime());
  80. if (menu.getUpdateTime() != null){
  81. String updateTime = formatter.format(menu.getUpdateTime());
  82. tree.setUpdateTime(updateTime);
  83. }
  84. tree.setCreateTime(createTime);
  85. return tree;
  86. }

selectMenuListByUserId sql

  1. <select id="selectMenuListByUserId" resultMap="BaseResultMap">
  2. select distinct m.id,m.name,m.icon,m.url,m.pid,m.sort,m.permission_code,m.`status`,m.menu_flag,
  3. m.description,m.create_time,m.update_time
  4. from sys_menu m
  5. left join sys_role_menu rm
  6. on m.id = rm.menu_id
  7. left join sys_role r
  8. on r.id = rm.role_id
  9. left join sys_user_role ur
  10. on ur.role_id = r.id
  11. left join pay_user u
  12. on u.id = ur.user_id
  13. where u.id = #{id}
  14. and m.menu_flag != 2
  15. </select>

8.页面配置
//menu:add 是你表中自定义的权限code


//这里是你要控制的按钮代码

这样只要你的用户下有menu:add这个权限,就可以看到被shiro标签包含的按钮,反之则看不到

9.至于上面配置文件中提到的:
/user/index = perms[“userManage:all”]
这个是用来防止有人直接在地址栏输入地址的,你可以尝试一下,一个用户没有某个页面的权限,但是直接地址栏输入地址还是可以访问的,只不过没有权限的按钮不会显示出来,但这样明显是不可行的,所以每多一个页面都需要在配置文件配置这个参数,这样很繁琐,下一篇文章会介绍一种自定义filterChainDefinitionMap的方式

发表评论

表情:
评论列表 (有 0 条评论,581人围观)

还没有评论,来说两句吧...

相关阅读

    相关 SpringMVC集成shiro

    最近公司一个老的后台管理系统需要加权限验证(前端使用easyUI),经过各种踩坑,终于是完成了,话不多说,直接进入主题 数据库结构 用户表(使用的项目本身已经在用的表)