shiro授权

授权本质分为两部分:1、添加权限Flag 2、定义权限Flag

权限Flag:角色(Role)和权限(Permission)

Shiro 支持三种定义(角色/权限)方式:

编程式:通过写 if/else 授权代码块完成: 

Subject subject = SecurityUtils.getSubject();
if(subject.hasRole(“admin”)) {
    //有权限
} else {
    //无权限
}
Subject subject = SecurityUtils.getSubject();
if(subject.subject.checkPermission("user:find:*")) {
    //有权限
} else {
    //无权限
}

注解式:通过在执行的 Java 方法上放置相应的注解完成:

@RequiresRoles("admin")
public void hello() {
    //有权限
}
    @GetMapping("/add")
    @RequiresPermissions(value={"user:add:*"})
    public String add(){
        return "add";
    }

没有权限将抛出相应的异常;

JSP/GSP 标签:在 JSP/GSP 页面通过相应的标签完成:

<shiro:hasRole name="admin">
<!— 有权限 —>
</shiro:hasRole>

角色(Role)

前期准备

Role数据准备

CREATE TABLE `t_role`  (
  `ROLE_ID` BIGINT(0) NOT NULL AUTO_INCREMENT COMMENT '角色ID',
  `ROLE_NAME` VARCHAR(30) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '角色名称',
  `REMARK` VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '角色描述',
  `DELETE_FLAG` TINYINT(0) NOT NULL DEFAULT 0 COMMENT '删除',
  `CREATE_TIME` DATETIME(0) NOT NULL COMMENT '创建时间',
  `CREATE_USER` VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '创建人',
  `MODIFY_TIME` DATETIME(0) NOT NULL COMMENT '修改时间',
  `MODIFY_USER` VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '修改人',
  PRIMARY KEY (`ROLE_ID`) USING BTREE,
  INDEX `t_role_index1`(`ROLE_ID`) USING BTREE
) ENGINE = INNODB AUTO_INCREMENT = 15 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = COMPACT;

-- ----------------------------
-- Records of t_role
-- ----------------------------
INSERT INTO `t_role` VALUES (1, '管理员', '管理员', 0, '2021-06-15 10:04:36', 'sys', '2021-06-23 13:14:31', 'admin');
INSERT INTO `t_role` VALUES (2, '宾客', '宾客', 0, '2021-06-15 10:04:36', 'sys', '2021-06-23 13:14:40', 'admin');


CREATE TABLE `t_user_role`  (
  `ID` BIGINT(0) NOT NULL AUTO_INCREMENT COMMENT '管理ID',
  `USER_ID` BIGINT(0) NOT NULL COMMENT '用户ID',
  `ROLE_ID` BIGINT(0) NOT NULL COMMENT '角色ID',
  `DELETE_FLAG` TINYINT(0) NOT NULL DEFAULT 0 COMMENT '删除',
  `CREATE_TIME` DATETIME(0) NOT NULL COMMENT '创建时间',
  `CREATE_USER` VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '创建人',
  `MODIFY_TIME` DATETIME(0) NOT NULL COMMENT '修改时间',
  `MODIFY_USER` VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '修改人',
  PRIMARY KEY (`ID`) USING BTREE,
  INDEX `t_user_index1`(`ID`, `USER_ID`, `ROLE_ID`) USING BTREE
) ENGINE = INNODB AUTO_INCREMENT = 147 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = COMPACT;


INSERT INTO `t_user_role`(`ID`, `USER_ID`, `ROLE_ID`, `DELETE_FLAG`, `CREATE_TIME`, `CREATE_USER`, `MODIFY_TIME`, `MODIFY_USER`) VALUES (1, 1, 1, 0, '2019-01-23 07:33:20', 'sys', '2020-11-27 16:12:21', '管理员');
INSERT INTO `t_user_role`(`ID`, `USER_ID`, `ROLE_ID`, `DELETE_FLAG`, `CREATE_TIME`, `CREATE_USER`, `MODIFY_TIME`, `MODIFY_USER`) VALUES (2, 2, 2, 0, '2019-01-23 07:33:20', 'sys', '2020-11-27 16:12:21', '管理员');
View Code

RoleMapper

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.marw.mapper.RoleMapper">
    <resultMap id="roleMap" type="om.marw.entity.Role">
        <result column="ROLE_ID" jdbcType="DECIMAL" property="roleId"/>
        <result column="ROLE_NAME" jdbcType="VARCHAR" property="roleName"/>
        <result column="REMARK" jdbcType="VARCHAR" property="remark"/>
        <result column="CREATE_TIME" jdbcType="TIMESTAMP" property="createTime"/>
        <result column="MODIFY_TIME" jdbcType="TIMESTAMP" property="modifyTime"/>
    </resultMap>

    <select id="findUserRole" resultMap="roleMap">
        select r.*
        from t_role r
                 inner join t_user_role ur on (r.role_id = ur.role_id)
                 inner join t_user u on (u.user_id = ur.user_id)
        where u.username = #{userName}
          and r.DELETE_FLAG = '0'
          and ur.DELETE_FLAG = '0'
    </select>
</mapper>
View Code

RoleServiceImpl

@Service
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements IRoleService {
    @Override
    public List<Role> findUserRole(String userName) {
        return baseMapper.findUserRole(userName);
    }
}
View Code

添加角色

认证和授权的操作都是在Realm中完成的

    @Autowired
    private IRoleService roleServiceImpl;

    /**
     * 授权
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("123");
        String username = (String) principalCollection.getPrimaryPrincipal();

        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();

        // 获取用户角色集
        List<Role> roleList = roleServiceImpl.findUserRole(username);
        Set<String> roleSet = roleList.stream().map(Role::getRoleName).collect(Collectors.toSet());
        simpleAuthorizationInfo.setRoles(roleSet);

        return simpleAuthorizationInfo;
    }

如果不定义角色,这个授权就没有任何意义

定义角色

用户角色为管理员可以用户管理、角色管理、菜单管理,用户角色是宾客只能访问用户管理

shiro整合thymeleaf

添加依赖

        <dependency>
            <groupId>com.github.theborakompanioni</groupId>
            <artifactId>thymeleaf-extras-shiro</artifactId>
            <version>2.0.0</version>
        </dependency>

添加配置:在ShiroConfig配置类中定义整合thymeleaf

    //用于整合shiro、thymeleaf
    @Bean
    public ShiroDialect shiroDialect(){
        return new ShiroDialect();
    }

前端页面:使用标签方式定义角色

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
      xmlns:shiro="http://www.thymeleaf.org/thymeleaf-extras-shiro">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
首页<br />
<div shiro:hasAnyRoles="管理员,宾客">
<a href="/user/list">用户管理</a><br />
</div>
<div shiro:hasRole="管理员">
    <a href="/role/list">角色管理</a><br />
    <a href="/menu/list">菜单管理</a><br />
</div>
shiro:guest:判断是否是未登录,即游客<br />
shiro:hasRole:判断是否有xxx角色<br />
shiro:hasPermission:判断是否有xxx权限<br />
shiro:hasAnyRoles:判断是否有任何一个指定的权限<br />
</body>
</html>
View Code

实际开发中,逻辑思想:用户具有什么角色,角色具有哪些权限,角色可以有菜单权限和操作权限

权限(Permission)

字符串通配符权限

规则:“资源标识符:操作:对象实例 ID” 即对哪个资源的哪个实例可以进行什么操作。其默认支持通配符权限字符串,“:”表示资源/操作/实例的分割;“,”表示操作的分割;“*”表示任意资源/操作/实例。

权限:菜单权限(显示菜单)和操作权限(增、删、改、查)

角色和权限的关系:

前期准备

菜单、操作权限与角色关联的数据准备

CREATE TABLE `t_menu` (
  `MENU_ID` bigint NOT NULL AUTO_INCREMENT COMMENT '菜单/按钮ID',
  `PARENT_ID` bigint NOT NULL COMMENT '上级菜单ID',
  `MENU_NAME` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '菜单/按钮名称',
  `PATH` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '对应路由path',
  `COMPONENT` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '对应路由组件component',
  `PERMS` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '权限标识',
  `ICON` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '图标',
  `TYPE` char(2) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '类型 0菜单 1按钮',
  `ORDER_NUM` double(20,0) DEFAULT NULL COMMENT '排序',
  `DELETE_FLAG` tinyint NOT NULL DEFAULT '0' COMMENT '删除',
  `CREATE_TIME` datetime NOT NULL COMMENT '创建时间',
  `CREATE_USER` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '创建人',
  `MODIFY_TIME` datetime NOT NULL COMMENT '修改时间',
  `MODIFY_USER` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '修改人',
  PRIMARY KEY (`MENU_ID`) USING BTREE,
  KEY `t_menu_index1` (`MENU_ID`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=117 DEFAULT CHARSET=utf8mb3 ROW_FORMAT=COMPACT;

insert  into `t_menu`(`MENU_ID`,`PARENT_ID`,`MENU_NAME`,`PATH`,`COMPONENT`,`PERMS`,`ICON`,`TYPE`,`ORDER_NUM`,`DELETE_FLAG`,`CREATE_TIME`,`CREATE_USER`,`MODIFY_TIME`,`MODIFY_USER`) values 
(1,0,'系统管理','/','PageView',NULL,'appstore-o','0',1,0,'2017-12-27 16:39:07','管理员','2021-06-15 11:40:23','admin'),
(2,1,'用户管理','/user/list','User',NULL,'','0',1,0,'2017-12-27 16:47:13','管理员','2021-06-17 15:45:26','admin'),
(3,1,'角色管理','/role/list','Role',NULL,'','0',2,1,'2017-12-27 16:48:09','管理员','2017-12-27 16:48:09','管理员'),
(4,1,'菜单管理','/menu/list','Menu',NULL,'','0',3,1,'2017-12-27 16:48:57','管理员','2017-12-27 16:48:57','管理员'),
(5,2,'新增用户','','','user:add',NULL,'1',NULL,0,'2017-12-27 17:02:58','管理员','2017-12-27 17:02:58','管理员'),
(6,2,'修改用户','','','user:update',NULL,'1',NULL,0,'2017-12-27 17:04:07','管理员','2017-12-27 17:04:07','管理员'),
(7,2,'删除用户','','','user:delete',NULL,'1',NULL,0,'2017-12-27 17:04:58','管理员','2017-12-27 17:04:58','管理员'),
(8,3,'新增角色','','','role:add',NULL,'1',NULL,0,'2017-12-27 17:06:38','管理员','2017-12-27 17:06:38','管理员'),
(9,3,'修改角色','','','role:update',NULL,'1',NULL,0,'2017-12-27 17:06:38','管理员','2017-12-27 17:06:38','管理员'),
(10,3,'删除角色','','','role:delete',NULL,'1',NULL,0,'2017-12-27 17:06:38','管理员','2017-12-27 17:06:38','管理员'),
(11,4,'新增菜单','','','menu:add',NULL,'1',NULL,0,'2017-12-27 17:08:02','管理员','2017-12-27 17:08:02','管理员'),
(12,4,'修改菜单','','','menu:update',NULL,'1',NULL,0,'2017-12-27 17:08:02','管理员','2017-12-27 17:08:02','管理员'),
(13,4,'删除菜单','','','menu:delete',NULL,'1',NULL,0,'2017-12-27 17:08:02','管理员','2017-12-27 17:08:02','管理员');


CREATE TABLE `t_role_menu` (
  `ID` bigint NOT NULL AUTO_INCREMENT COMMENT '管理ID',
  `ROLE_ID` bigint NOT NULL COMMENT '角色ID',
  `MENU_ID` bigint NOT NULL COMMENT '菜单ID',
  `DELETE_FLAG` tinyint NOT NULL DEFAULT '0' COMMENT '删除',
  `CREATE_TIME` datetime NOT NULL COMMENT '创建时间',
  `CREATE_USER` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '创建人',
  `MODIFY_TIME` datetime NOT NULL COMMENT '修改时间',
  `MODIFY_USER` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '修改人',
  PRIMARY KEY (`ID`) USING BTREE,
  KEY `t_role_menu_index1` (`ID`,`ROLE_ID`,`MENU_ID`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1946 DEFAULT CHARSET=utf8mb3 ROW_FORMAT=COMPACT;

/*Data for the table `t_role_menu` */

insert  into `t_role_menu`(`ID`,`ROLE_ID`,`MENU_ID`,`DELETE_FLAG`,`CREATE_TIME`,`CREATE_USER`,`MODIFY_TIME`,`MODIFY_USER`) values 
(1886,1,1,0,'2021-06-23 13:14:31','admin','2021-06-23 13:14:31','admin'),
(1887,1,2,0,'2021-06-23 13:14:31','admin','2021-06-23 13:14:31','admin'),
(1888,1,3,0,'2021-06-23 13:14:31','admin','2021-06-23 13:14:31','admin'),
(1889,1,4,0,'2021-06-23 13:14:31','admin','2021-06-23 13:14:31','admin'),
(1890,1,5,0,'2021-06-23 13:14:31','admin','2021-06-23 13:14:31','admin'),
(1891,1,6,0,'2021-06-23 13:14:31','admin','2021-06-23 13:14:31','admin'),
(1892,1,7,0,'2021-06-23 13:14:31','admin','2021-06-23 13:14:31','admin'),
(1893,1,8,0,'2021-06-23 13:14:31','admin','2021-06-23 13:14:31','admin'),
(1894,1,9,0,'2021-06-23 13:14:31','admin','2021-06-23 13:14:31','admin'),
(1895,1,10,0,'2021-06-23 13:14:31','admin','2021-06-23 13:14:31','admin'),
(1896,1,11,0,'2021-06-23 13:14:31','admin','2021-06-23 13:14:31','admin'),
(1897,1,12,0,'2021-06-23 13:14:31','admin','2021-06-23 13:14:31','admin'),
(1898,1,13,0,'2021-06-23 13:14:31','admin','2021-06-23 13:14:31','admin'),
(1916,2,2,0,'2021-06-23 13:14:40','admin','2021-06-23 13:14:40','admin'),
(1917,2,5,0,'2021-06-23 13:14:40','admin','2021-06-23 13:14:40','admin'),
(1918,2,6,0,'2021-06-23 13:14:41','admin','2021-06-23 13:14:41','admin'),
(1919,2,7,0,'2021-06-23 13:14:41','admin','2021-06-23 13:14:41','admin');
View Code

MenuMapper

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.marw.mapper.MenuMapper">
    <resultMap id="menu" type="com.marw.entity.Menu">
        <id column="MENU_ID" jdbcType="DECIMAL" property="menuId"/>
        <result column="PARENT_ID" jdbcType="DECIMAL" property="parentId"/>
        <result column="MENU_NAME" jdbcType="VARCHAR" property="menuName"/>
        <result column="PATH" jdbcType="VARCHAR" property="path"/>
        <result column="COMPONENT" jdbcType="VARCHAR" property="component"/>
        <result column="PERMS" jdbcType="VARCHAR" property="perms"/>
        <result column="ICON" jdbcType="VARCHAR" property="icon"/>
        <result column="TYPE" jdbcType="CHAR" property="type"/>
        <result column="ORDER_NUM" jdbcType="DOUBLE" property="orderNum"/>
        <result column="CREATE_TIME" jdbcType="TIMESTAMP" property="createTime"/>
        <result column="MODIFY_TIME" jdbcType="TIMESTAMP" property="modifyTime"/>
    </resultMap>

    <select id="findUserPermissions" resultMap="menu">
        select distinct m.perms
        from t_role r
                 left join t_user_role ur on (r.role_id = ur.role_id and ur.DELETE_FLAG = '0')
                 left join t_user u on (u.user_id = ur.user_id and u.STATUS = '1')
                 left join t_role_menu rm on (rm.role_id = r.role_id and rm.DELETE_FLAG = '0')
                 left join t_menu m on (m.menu_id = rm.menu_id and m.DELETE_FLAG = '0')
        where u.username = #{userName}
          and m.perms is not null
          and m.perms &lt;&gt; ''
          and m.DELETE_FLAG = '0'
    </select>
</mapper>
View Code

MenuServiceImpl

@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements IMenuService {
    @Override
    public List<Menu> findUserPermissions(String username) {
        return this.baseMapper.findUserPermissions(username);
    }
}
View Code

添加权限

    @Autowired
    private IMenuService menuServiceImpl;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        String username = (String) principalCollection.getPrimaryPrincipal();

        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();

        // 获取用户角色集
        List<Role> roleList = roleServiceImpl.findUserRole(username);
        Set<String> roleSet = roleList.stream().map(Role::getRoleName).collect(Collectors.toSet());
        simpleAuthorizationInfo.setRoles(roleSet);

        // 获取用户权限集
        List<Menu> permissionList = menuServiceImpl.findUserPermissions(username);
        Set<String> permissionSet = permissionList.stream().map(Menu::getPerms).collect(Collectors.toSet());
        simpleAuthorizationInfo.setStringPermissions(permissionSet);
        return simpleAuthorizationInfo;
    }

定义权限

管理员可以用户管理(增、删、改)、角色管理(增、删、改)、菜单管理(增、删、改),用户角色是宾客只能访问用户管理(增、删、改)

用户管理

@RestController
@RequestMapping("/user")
public class UserController {

    @GetMapping("/list")
    public ModelAndView list(){
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("user/list");
        return modelAndView;
    }

    @GetMapping("/add")
    @RequiresPermissions(value={"user:add"})
    public ModelAndView add(){
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("user/add");
        return modelAndView;
    }

    @GetMapping("/update")
    @RequiresPermissions(value={"user:update"})
    public ModelAndView update(){
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("user/update");
        return modelAndView;
    }

    @GetMapping("/delete")
    @RequiresPermissions(value={"user:delete"})
    public ModelAndView delete(){
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("user/delete");
        return modelAndView;
    }
}
View Code

角色管理

@RestController
@RequestMapping("/role")
public class RoleController {
    @RequestMapping("/list")
    public ModelAndView list(){
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("role/list");
        return modelAndView;
    }

    @RequestMapping("/add")
    //@RequiresPermissions("role:add")
    public ModelAndView add(){
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("role/add");
        return modelAndView;
    }

    @RequestMapping("/update")
    @RequiresPermissions("role:update")
    public ModelAndView update(){
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("role/update");
        return modelAndView;
    }

    @RequestMapping("/delete")
    @RequiresPermissions("role:delete")
    public ModelAndView delete(){
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("role/delete");
        return modelAndView;
    }
}
View Code

 

posted @ 2021-08-25 14:09  一杯水M  阅读(148)  评论(0编辑  收藏  举报