今天发现一个问题:使用shiro的时候,虽然隐藏掉了一些菜单,但是当我们通过get请求直接访问菜单的时候还是会访问到,也就是shiro可以在界面实现隐藏一些信息,但是没有真正的根据权限码验证请求,于是自己在后台实现验证。

  

需求:有权限(权限码是systemmanager:settings)的人可以点击系统设置跳转到系统设置页面,没权限的人看不到菜单,但是通过get访问可以访问到,于是需要在后台拦截。

实现思路:在需要精确验证的方法开始先验证权限,如果验证成功啥也不做,验证失败的话就抛出一个没有权限的异常。在拦截器中捕捉到异常就记录日志,并返回到提醒页面。

1.  验证Shiro权限的工具类(此工具还可以进一步完善,封装为判断是否有指定角色,或者有任意角色)

  1. package cn.xm.exam.utils;
  2.  
  3. import org.apache.shiro.SecurityUtils;
  4. import org.apache.shiro.subject.Subject;
  5. import org.slf4j.Logger;
  6. import org.slf4j.LoggerFactory;
  7.  
  8. import cn.xm.exam.bean.system.User;
  9. import cn.xm.exam.exception.NoPermissionException;
  10.  
  11. /**
  12. * 验证shiro权限的工具类
  13. *
  14. * @author QiaoLiQiang
  15. * @time 2018年11月3日下午9:30:46
  16. */
  17. public class ShiroPermissionUtils {
  18.  
  19. private static final Logger log = LoggerFactory.getLogger(ShiroPermissionUtils.class);
  20.  
  21. private ShiroPermissionUtils() {
  22.  
  23. }
  24.  
  25. /**
  26. * 检查当前用户是否有权限(任意一项)
  27. *
  28. * @param permissionCodes
  29. * 任意权限
  30. * @throws NoPermissionException
  31. */
  32. public static void checkPerissionAny(String... permissionCodes) {
  33. if (permissionCodes == null || permissionCodes.length == 0) {
  34. return;
  35. }
  36.  
  37. // 获取用户信息
  38. Subject currentUser = SecurityUtils.getSubject();
  39. for (String permission : permissionCodes) {
  40. boolean permitted = currentUser.isPermitted(permission);// 判断是否有权限
  41. if (permitted) {
  42. return;
  43. }
  44. }
  45.  
  46. // 没权限就抛出一个异常
  47. Object principal = currentUser.getPrincipal();
  48. if (principal instanceof User) {
  49. User user = (User) principal;
  50. log.error("user {} no permission !", user.getUsername());
  51. }
  52. throw new NoPermissionException("no permission ");
  53. }
  54.  
  55. /**
  56. * 检查当前用户是否有权限(所有的)
  57. *
  58. * @param permissionCodes
  59. * 任意权限
  60. * @throws NoPermissionException
  61. */
  62. public static void checkPerissionAll(String... permissionCodes) {
  63. if (permissionCodes == null || permissionCodes.length == 0) {
  64. return;
  65. }
  66.  
  67. // 获取用户信息
  68. Subject currentUser = SecurityUtils.getSubject();
  69. for (String permission : permissionCodes) {
  70. boolean permitted = currentUser.isPermitted(permission);// 判断是否有权限
  71. if (!permitted) {
  72. // 没权限就抛出一个异常
  73. Object principal = currentUser.getPrincipal();
  74. if (principal instanceof User) {
  75. User user = (User) principal;
  76. log.error("user {} no permission !", user.getUsername());
  77. }
  78. throw new NoPermissionException("no permission ");
  79. }
  80. }
  81. }
  82. }

解释:

  (1)Subject currentUser = SecurityUtils.getSubject();    先获取到Subject,

  (2)boolean permitted = currentUser.isPermitted(permission);     然后验证权限

  (3)如果验证失败就记录日志,(获取到subject中的principal,principal其实是认证的时候装进SimpleAuthenticationInfo的user对象)

Object principal = currentUser.getPrincipal();
if (principal instanceof User) {
User user = (User) principal;
log.error("user {} no permission !", user.getUsername());
}
throw new NoPermissionException("no permission ");

认证时候装进去的User对象:---principal

2.自定义异常(如果不自定义异常,也可以在程序中抛出一个运行时异常throw new RuntimeException("XXXXX");)

  必须继承RuntimeException,运行时异常不需要在抛出异常的时候显示的捕捉或者声明(throws.....),如果继承Exception为检查异常,需要捕捉或者throws声明.

  1. package cn.xm.exam.exception;
  2.  
  3. /**
  4. * 没有权限异常
  5. *
  6. * @author QiaoLiQiang
  7. * @time 2018年11月3日下午9:34:12
  8. */
  9. public class NoPermissionException extends RuntimeException {
  10.  
  11. /**
  12. *
  13. */
  14. private static final long serialVersionUID = -4442982597754920924L;
  15.  
  16. public NoPermissionException(String msg) {
  17. super(msg);
  18. }
  19. }

3.测试Action

   方法开始先验证权限,但是没有捕捉异常,如果验证失败异常会抛出在拦截器中被捕捉。

  1. package cn.xm.exam.action.system;
  2.  
  3. import org.slf4j.Logger;
  4. import org.slf4j.LoggerFactory;
  5. import org.springframework.context.annotation.Scope;
  6. import org.springframework.stereotype.Controller;
  7.  
  8. import com.opensymphony.xwork2.ActionSupport;
  9.  
  10. import cn.xm.exam.utils.ShiroPermissionUtils;
  11.  
  12. @Controller
  13. @Scope("prototype")
  14. public class SettingsAction extends ActionSupport {
  15.  
  16. /**
  17. * serial
  18. */
  19. private static final long serialVersionUID = -5885555441378384728L;
  20. private static final Logger log = LoggerFactory.getLogger(ShiroPermissionUtils.class);
  21.  
  22. public String settings() {
  23. ShiroPermissionUtils.checkPerissionAny("systemmanager:settings");
  24.  
  25. return "settings";
  26. }
  27.  
  28. }

4.struts全局异常拦截器

  捕捉到NoPermissionException异常就返回noPermissionError在全局结果集中处理

  1. package cn.xm.exam.interceptor;
  2.  
  3. import org.slf4j.Logger;
  4. import org.slf4j.LoggerFactory;
  5.  
  6. import com.opensymphony.xwork2.ActionInvocation;
  7. import com.opensymphony.xwork2.interceptor.Interceptor;
  8.  
  9. import cn.xm.exam.exception.NoPermissionException;
  10.  
  11. public class ExceptionInterception implements Interceptor {
  12. private static final Logger log = LoggerFactory.getLogger(ExceptionInterception.class);
  13. /**
  14. *
  15. */
  16. private static final long serialVersionUID = 2268867259828199826L;
  17.  
  18. @Override
  19. public void destroy() {
  20.  
  21. }
  22.  
  23. @Override
  24. public void init() {
  25.  
  26. }
  27.  
  28. @Override
  29. public String intercept(ActionInvocation arg0) throws Exception {
  30. log.info("enter ExceptionInterception intercept ... ");
  31. String result = "";
  32. try {
  33. result = arg0.invoke();
  34. log.info("result -> {}", result);
  35. } catch (NoPermissionException e) {
  36. log.error("no permission", e);
  37. return "noPermissionError";
  38. } catch (Throwable e) {
  39. log.error("未处理的异常在拦截器被拦截,class:{}", arg0.getAction().getClass(), e);
  40. return "interceptorError";
  41. }
  42. log.debug("exit ExceptionInterception intercept ... ");
  43. return result;
  44. }
  45.  
  46. }

5.Struts.xml配置全局异常错误界面:

  返回值是noPermissionError跳转到noPermissionError.jsp页面

  1. <package name="interceptPackage" extends="json-default">
  2. <!-- 拦截器 -->
  3. <interceptors>
  4. <!-- 定义刚才的拦截器 -->
  5. <interceptor name="exceptionInterceptor"
  6. class="cn.xm.exam.interceptor.ExceptionInterception"></interceptor>
  7. <!-- 定义拦截器栈 -->
  8. <interceptor-stack name="myStack">
  9. <!-- 拦截器栈里面可以引用另外一个拦截器,也可以引用另外一个拦截器栈 -->
  10. <interceptor-ref name="defaultStack"></interceptor-ref>
  11. <interceptor-ref name="exceptionInterceptor"></interceptor-ref>
  12. </interceptor-stack>
  13. </interceptors>
  14. <!-- 这句是设置所有Action自动调用的拦截器堆栈 -->
  15. <default-interceptor-ref name="myStack" />
  16.  
  17. <!-- 拦截器拦截的全局异常 -->
  18. <global-results>
  19. <result name="interceptorError">/interceptorError.jsp</result>
  20. <result name="noPermissionError">/noPermissionError.jsp</result>
  21. </global-results>
  22. </package>

6.noPermissionError.jsp页面

  给出没权限提醒。

  1. <%@ page language="java" contentType="text/html; charset=UTF-8"
  2. pageEncoding="UTF-8"%>
  3. <%
  4. String path = request.getContextPath();
  5. String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()
  6. + path + "/";
  7. %>
  8.  
  9. <!DOCTYPE html>
  10. <html lang="en">
  11. <head>
  12. <meta charset="UTF-8">
  13. <title>错误提醒</title>
  14. </head>
  15. <body>
  16. <br />
  17. <span style="font-weight: bold; font-size: 20px; margin: 20px;">对不起,您没有权限访问该请求!</span>
  18. <br />
  19. </body>
  20. </html>

7.测试:

至此,完成了后台验证,也就是在所有方法开始先验证权限。

还有另一种办法就是自定义注解实现权限验证,有点类似于shiro自带的注解验证权限,参考:https://www.cnblogs.com/qlqwjy/p/7257616.html

Shiro后台实现验证权限的更多相关文章

  1. 基于权限安全框架Shiro的登录验证功能实现

    目前在企业级项目里做权限安全方面喜欢使用Apache开源的Shiro框架或者Spring框架的子框架Spring Security. Apache Shiro是一个强大且易用的Java安全框架,执行身 ...

  2. SpringMVC+Apache Shiro+JPA(hibernate)案例教学(二)基于SpringMVC+Shiro的用户登录权限验证

    序: 在上一篇中,咱们已经对于项目已经做了基本的配置,这一篇文章开始学习Shiro如何对登录进行验证. 教学: 一.Shiro配置的简要说明. 有心人可能注意到了,在上一章的applicationCo ...

  3. 项目一:第十二天 1、常见权限控制方式 2、基于shiro提供url拦截方式验证权限 3、在realm中授权 5、总结验证权限方式(四种) 6、用户注销7、基于treegrid实现菜单展示

    1 课程计划 1. 常见权限控制方式 2. 基于shiro提供url拦截方式验证权限 3. 在realm中授权 4. 基于shiro提供注解方式验证权限 5. 总结验证权限方式(四种) 6. 用户注销 ...

  4. 将 Shiro 作为应用的权限基础 一:shiro的整体架构

    将 Shiro 作为应用的权限基础 一:shiro的整体架构 近来在做一个重量级的项目,其中权限.日志.报表.工作量由我负责,工作量还是蛮大的,不过想那么多干嘛,做就是了. 这段时间,接触的东西挺多, ...

  5. [转]后台页面访问权限:页面基类&内置票据认证 使用方法

    本文转自:http://www.cnblogs.com/fishtreeyu/archive/2011/01/29/1947421.html 一般网站后台页面除了登录页面login.aspx未登录用户 ...

  6. 使用Mongodb+Shiro+SpringMVC实现动态权限分配

    此次的文档只对Mongodb整合Shiro并且实现动态权限分配做整理,其它的内容以后会补上. 第一步.创建在web.xml中配置 Spring .Shiro shiroFilter 过滤器是用来将请求 ...

  7. spring boot(十四)shiro登录认证与权限管理

    这篇文章我们来学习如何使用Spring Boot集成Apache Shiro.安全应该是互联网公司的一道生命线,几乎任何的公司都会涉及到这方面的需求.在Java领域一般有Spring Security ...

  8. 将 Shiro 作为应用的权限基础 二:shiro 认证

    认证就是验证用户身份的过程.在认证过程中,用户需要提交实体信息(Principals)和凭据信息(Credentials)以检验用户是否合法.最常见的“实体/凭证”组合便是“用户名/密码”组合. 一. ...

  9. ecshop 管理后台菜单及权限管理机制

    ecshop 所有的一级菜单选项存放于languages\zh_cn\admin\common.php 文件里面,使用 $_LANG['02_cat_and_goods'] = '商品管理';  这样 ...

随机推荐

  1. CSS覆盖公共样式中的某个属性

    CSS如何覆盖公共样式中的某个属性?利用CSS样式的优先级. 如下例子: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transition ...

  2. MT【69】斯图姆定理

    评:如果说零点存在定理是"只在此山中,云深不知处"的意境.那么斯图姆定理就能处理多项式的零点个数以及定位.

  3. 19 Zabbix web监控实例

    点击返回:自学Zabbix之路 点击返回:自学Zabbix4.0之路 点击返回:自学zabbix集锦 9 Zabbix web监控实例 通过前面的介绍你已经了解Web scenario的配置,下面我们 ...

  4. 自学Zabbix3.11-宏Macros

    点击返回:自学Zabbix之路 点击返回:自学Zabbix4.0之路 点击返回:自学zabbix集锦 自学Zabbix3.11-宏Macros zabbix宏变量让zabbix变得更灵活,它根据一系列 ...

  5. 【BZOJ2427】[HAOI2010]软件安装(动态规划,Tarjan)

    [BZOJ2427][HAOI2010]软件安装(动态规划,Tarjan) 题面 BZOJ 洛谷 题解 看到这类题目就应该要意识到依赖关系显然是可以成环的. 注意到这样一个性质,依赖关系最多只有一个, ...

  6. 洛谷 P1582 倒水 解题报告

    P1582 倒水 题目描述 一天,CC买了N个容量可以认为是无限大的瓶子,开始时每个瓶子里有1升水.接着~~CC发现瓶子实在太多了,于是他决定保留不超过K个瓶子.每次他选择两个当前含水量相同的瓶子,把 ...

  7. 软Raid50制作

    =====创建Raid50的步骤====== 1.创建分区[root@localhost ~]# fdisk /dev/sdb[root@localhost ~]# fdisk /dev/sdc[ro ...

  8. HDU 3416 Marriage Match IV (最短路径,网络流,最大流)

    HDU 3416 Marriage Match IV (最短路径,网络流,最大流) Description Do not sincere non-interference. Like that sho ...

  9. checkBox全选全不选及数据提交后台

    <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...

  10. 解决QtCreator中文乱码

    在QT的菜单栏”Tools“ -> "Options" -> "Behavior" -> "File Encoding" ...