二.六 前端页面
前端页面的配置信息,与以前基本一致,故不重复写了。
重点提一下, dept.jsp 页面的按钮标识控制部分。
dept.jsp 页面设置标识:
<shiro:hasPermission name="dept:add"> <script> sessionStorage.setItem("dept_update",true); </script> </shiro:hasPermission> <shiro:hasPermission name="dept:update"> <script> sessionStorage.setItem("dept_update",true); </script> </shiro:hasPermission> <shiro:hasPermission name="dept:delete"> <script> sessionStorage.setItem("dept_delete","true") </script> </shiro:hasPermission> <script type="text/javascript" src="${pageContext.request.contextPath}/static/js/dept.js"></script>
dept.js 脚本里面获取标识:
//看是否有添加的权限 var add=sessionStorage.getItem("dept_add"); if(add){ $("#add").show(); }else{ $("#add").hide(); } //看修改和删除是否显示和隐藏 function operateFormatter(value, row, index) { var update=sessionStorage.getItem("dept_update"); var del=sessionStorage.getItem("dept_delete"); //console.log("update:"+update+",del:"+del); var udpateIcon=""; if(update){ udpateIcon='<a class="update text-primary" href="javascript:void(0)" data-toggle="tooltip" title="修改">' +'<i class="fa fa-pencil"></i> 修改 </a>'; } var delIcon=""; if(del){ delIcon='<shiro:hasPermission name="dept:delete"><a class="delete text-danger" href="javascript:void(0)" data-toggle="tooltip" title="撤销">' +'<i class="fa fa-minus"></i> 删除 </a></shiro:hasPermission">'; } return udpateIcon+delIcon; }
二.七 测试验证
输入网址: http://localhost:8080/SSM_Shiro_RBAC/User/toLogin
输入admin,1234 进行测试 (错误的密码情况就不测试了)
看起来,是正常的,
然后,当手动输入 部门的添加功能呢,
http://localhost:8080/SSM_Shiro_RBAC/Dept/add
响应是正常的, 这是因为我们没有配置具体的权限验证呢。
三. 注解式配置具体权限
在 applicationContext-shiro.xml 中的 filterChainDefinitions 属性中,虽然可以像 shiro.ini 那样,配置具体的权限,但是当权限过多时,再那样配置,就不太好了。
所以 shiro 提供了注解式配置。
只需要在某个具体的方法上面加入相应的注解即可。
如: 在 部门的 add() 方法上面 ,添加 @RequiresPermissions(“Dept:add”) 注解
@RequiresPermissions("dept:add") @RequestMapping("/add") @ResponseBody public Map<String,Object> add(){ System.out.println("实现部门添加的方法"); Map<String,Object> map=new HashMap<String,Object>(); map.put("response_status",true); return map; }
shiro 会先看一下,当前会话登录的用户,是否具有 权限 Dept:add ,如果有才执行 add 方法,如果没有,不执行,抛出异常。
会从 MyRealm 里面的 doGetAuthorizationInfo() 返回对象里面取数据进行比较。
一般常用的,就是 权限验证。
@Target({java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface RequiresPermissions { String[] value(); Logical logical() default Logical.AND; }
默认是 AND
配置单个权限:
@RequiresPermissions("dept:add")
表示具有权限 dept:add 才执行
配置多个权限与:
@RequiresPermissions({"dept:add","dept:update"})
表示具有权限 dept:add和 dept:update, 两个权限同时具有才执行
配置多个权限或:
@RequiresPermissions(value={"dept:add","dept:update"},logical=Logical.OR)
表示具有权限 dept:add 或者 dept:update 任意一个均可。
四. 注解式声明 Shiro 权限
直接在方法上 添加 @RequiresPermissions(“dept:add”) 注解是不生效的,必须要动态代理一下。
由于 权限注解被放置在 Action类的方法上,所以配置动态代理,必须要配置在 springmvc.xml 文件里面。
applicationContext-shiro.xml 文件不用动。
四.一 配置注解
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"> <property name="securityManager" ref="securityManager"></property> </bean> <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor"> <property name="proxyTargetClass" value="true"></property> </bean>
四.二 验证
admin 没有 部门的 添加权限, 当手动输入添加的地址时,会报错。
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.apache.shiro.authz.UnauthorizedException: Subject does not have permission [dept:add]
当输入 delete 网址时:
说明,注解权限是可以的。
需要处理一下异常,如果没有权限的话,就跳转到 无权限那个提示页面。
四.三 springmvc.xml 捕获异常
关于 SpringMVC 的异常处理,可以看老蝴蝶以前写的 SpringMVC系列文章。
<!-- 配置异常 --> <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionMappings"> <props> <!-- 每个异常类,对应一个jsp --> <!-- 没有权限,到哪个具体的页面 --> <prop key="org.apache.shiro.authz.AuthorizationException">noPrivilege</prop> <!-- 没有认证通过 --> <prop key="org.apache.shiro.authc.AuthenticationException">login</prop> <!-- 可继续添加多个 ,如StudentException --> </props> </property> </bean>
配置好之后,重新测试
当登录成功后,再输入 部门添加的网址后,
注意观察控制台的打印信息:
发现,自定义Realm 中的授权方法,被执行了很多次, 每一个注解方法,每一个前端的 shiro:hasPermission 判断,都需要执行一下这个方法,频繁地取数据, 影响数据库的效率, 所以我们需要做缓存的处理。 老蝴蝶下一章节再讲缓存。
本章节代码链接为:
链接:https://pan.baidu.com/s/1qjZcQfKQa4f_SdCjXvTtxQ 提取码:ko9l
谢谢您的观看,如果喜欢,请关注我,再次感谢 !!!