先在数据库中建立相应的数据表,以及后面使用需要的sql语句
#建表脚本 CREATE TABLE t_sys_user ( userid INT PRIMARY KEY AUTO_INCREMENT COMMENT '用户ID,主键', username VARCHAR(10) UNIQUE NOT NULL COMMENT '用户账号', PASSWORD VARCHAR(32) NOT NULL COMMENT '用户密码=MD5+盐加密', salt VARCHAR(32) NOT NULL COMMENT '盐', createdate TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建日期' ); CREATE TABLE t_sys_role ( roleid INT PRIMARY KEY AUTO_INCREMENT COMMENT '角色ID,主键', rolename VARCHAR(100) UNIQUE NOT NULL COMMENT '角色名称', description VARCHAR(100) COMMENT '角色描述' ); CREATE TABLE t_sys_permission ( perid INT PRIMARY KEY AUTO_INCREMENT COMMENT 'ID,主键', pername VARCHAR(100) NOT NULL COMMENT '权限名称', pid INT COMMENT '父编号', permission VARCHAR(100) NOT NULL COMMENT '权限字符串:例如:system:user:create:1' ); CREATE TABLE t_sys_user_role ( urid INT PRIMARY KEY AUTO_INCREMENT COMMENT 'ID,主键', userid INT NOT NULL COMMENT '用户ID', roleid INT NOT NULL COMMENT '角色ID' ); CREATE TABLE t_sys_role_permission ( roleid INT NOT NULL COMMENT '角色ID', perid INT NOT NULL COMMENT '权限ID' ); #数据添加 insert into `t_sys_permission`(`perid`,`pername`,`pid`,`permission`) values (10,'书本管理',-1,''),(11,'系统管理',-1,''),(1001,'书本管理',10,'bookmanager:book:*'),(1002,'订单管理',10,'bookmanager:order:*'),(1101,'用户管理',11,'system:user:*'),(100101,'书本查询',1001,'bookmanager:book:query'),(100102,'书本新增',1001,'bookmanager:book:add'),(100103,'书本修改',1001,'bookmanager:book:edit'),(100104,'书本删除',1001,'bookmanager:book:del'),(110101,'用户查询',1101,'system:user:query'),(110102,'用户新增',1101,'system:user:add'),(110103,'用户修改',1101,'system:user:edit'); /*Data for the table `t_sys_role` */ insert into `t_sys_role`(`roleid`,`rolename`,`description`) values (1,'管理员',NULL),(2,'高级用户',NULL),(3,'普通用户',NULL); /*Data for the table `t_sys_role_permission` */ insert into `t_sys_role_permission`(`roleid`,`perid`) values (1,1001),(1,100101),(1,100102),(1,100103),(1,100104),(1,1101),(1,110101),(1,110102),(1,110103),(2,100101),(2,100102); /*Data for the table `t_sys_user` */ insert into `t_sys_user`(`userid`,`username`,`password`,`salt`,`createdate`) values (1,'admin','c3b3ac764e1dbf4a1e4483f42c7140cb','af0111353776182a4f166e1d49a7dd2f','2018-11-26 15:02:42'),(2,'zhangsan','9c917b6f860eeb24361c75f27a236d6b','bcdf6f5c2237bdb440684b6c4ce943d4','2018-11-28 16:44:33'); /*Data for the table `t_sys_user_role` */ insert into `t_sys_user_role`(`urid`,`userid`,`roleid`) values (1,1,1),(2,2,2); select * from t_sys_user; SELECT * FROM t_sys_user_role; select * from t_sys_role; select * from t_sys_role_permission; select * from t_sys_permission; #关系:用户->角色->权限 #前提:用户登录后,根据用户账号(唯一)获取角色和权限 #1.根据username获取用户对应的角色 select r.rolename from t_sys_user u,t_sys_user_role ur,t_sys_role r where u.userid=ur.userid and ur.roleid=r.roleid and u.username='zhangsan'; #2.根据username获取用户对象的角色权限 select p.permission from t_sys_user u,t_sys_user_role ur,t_sys_role r,t_sys_role_permission rp,t_sys_permission p where u.userid=ur.userid and ur.roleid=r.roleid and r.roleid=rp.roleid and rp.perid=p.perid and u.username='zhangsan';
定义mapper层的方法
在相对应的xml中实现方法
注意!!!如果是我这种传值请在方法参数添加注解@Param
如图:
然后在对应的Service中添加方法注意删除注解
如图:
然后在Serive的实现类中实现方法的调用
如图:
然后在自定义Real的安全数据源(采用数据库方式)中写入:
@Autowired private ISysUserService sysUserService; /** * 授权 * @param principalCollection * @return */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { //获取登录账号 String username=principalCollection.getPrimaryPrincipal().toString(); // 根据username获取用户对应角色 Set<String> roles=sysUserService.findRoles(username); // 根据username获取用户对应的角色权限 Set<String> permissions = sysUserService.findPermissions(username); // 创建SimpleAuthorizationInfo SimpleAuthorizationInfo simple=new SimpleAuthorizationInfo(); // 填充用户的角色和权限 simple.setRoles(roles); simple.setStringPermissions(permissions); return simple; }
在index.jsp页面中引入shiro
如图:
然后在想要区分权限的地方使用shiro的标签即可
如图:
启动项目
来到登录页面,我们先登录有权限的账号:
登录成功后,我们来到首页,可以看到有权限的账号能看到被限制的部分
然后使用没有权限的普通用户账号:
我们能清晰的看到显示的内容少了很多:
看看网页源代码:
发现在客户端根本就没有被限制的内容,并不是隐藏,这种使用标签的方式太暴力了
所以介绍另一种方式:在spring-mvc.xml中开启注解
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor"> <property name="proxyTargetClass" value="true"></property> </bean> <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"> <property name="securityManager" ref="securityManager"/> </bean>
然后在你需要使用的Controller.java中的相应方法上加入注解
@RequiresRoles("管理员") //效果是限定身份是管理员才能使用或者是:
@RequiresPermissions("bookmanager:book:update")//限定只有权限有bookmanager:book:update的才能使用如图:
加入注解后启动项目,登录一个没有权限的账号,使用被限定了的查询功能
(因为不是标签,所以是在后台中调用时判断生效)
得到:
什么也没有查到。
通过Debug可以知道是因为不是管理员的原因
导致了异常,但是这里的全局异常处理并没有收集,所以此处的map集合是空的,所以此处既没有填充错误码,也没有填充错误信息,直接把空的map集合返回了
所以我们添加一个判断
然后在来一遍上面的操作就会看到:
如果没效果,那么可能是缓存问题,重新启动项目可以解决
其他方法并不会受到影响。
使用有权限的账号进行相同的操作:
可以正常查询。
@RequiresRoles(value = {"管理员","高级用户"},logical = Logical.OR) //限定身份是管理员或者高级用户才能使用@RequiresRoles(value = {"管理员","高级用户"},logical = Logical.AND) //限定身份是管理员并且也是高级用户才能使用,单独的一个身份无法使用
Shiro标签库
guest标签 :验证当前用户是否为“访客”,即未认证(包含未记住)的用户
user标签 :认证通过或已记住的用户
authenticated标签 :已认证通过的用户。不包含已记住的用户,这是与user标签的区别所在
notAuthenticated标签 :未认证通过用户,与authenticated标签相对应。与guest标签的区别是,该标签包含已记住用户
principal 标签 :输出当前用户信息,通常为登录帐号信息
hasRole标签 :验证当前用户是否属于该角色
lacksRole标签 :与hasRole标签逻辑相反,当用户不属于该角色时验证通过
hasAnyRole标签 :验证当前用户是否属于以下任意一个角色
hasPermission标签 :验证当前用户是否拥有指定权限
lacksPermission标签 :与hasPermission标签逻辑相反,当前用户没有制定权限时,验证通过Shiro注解
@RequiresAuthenthentication:表示当前Subject已经通过login进行身份验证;即 Subjecj.isAuthenticated()返回 true
@RequiresUser:表示当前Subject已经身份验证或者通过记住我登录的
@RequiresGuest:表示当前Subject没有身份验证或者通过记住我登录过,即是游客身份
@RequiresRoles(value = {"admin","user"},logical = Logical.AND):表示当前Subject需要角色admin和user
@RequiresPermissions(value = {"user:delete","user:b"},logical = Logical.OR):表示当前Subject需要权限user:delete或者user:b