Shiro后台实现验证权限
今天发现一个问题:使用shiro的时候,虽然隐藏掉了一些菜单,但是当我们通过get请求直接访问菜单的时候还是会访问到,也就是shiro可以在界面实现隐藏一些信息,但是没有真正的根据权限码验证请求,于是自己在后台实现验证。
需求:有权限(权限码是systemmanager:settings)的人可以点击系统设置跳转到系统设置页面,没权限的人看不到菜单,但是通过get访问可以访问到,于是需要在后台拦截。
实现思路:在需要精确验证的方法开始先验证权限,如果验证成功啥也不做,验证失败的话就抛出一个没有权限的异常。在拦截器中捕捉到异常就记录日志,并返回到提醒页面。
1. 验证Shiro权限的工具类(此工具还可以进一步完善,封装为判断是否有指定角色,或者有任意角色)
- package cn.xm.exam.utils;
- import org.apache.shiro.SecurityUtils;
- import org.apache.shiro.subject.Subject;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import cn.xm.exam.bean.system.User;
- import cn.xm.exam.exception.NoPermissionException;
- /**
- * 验证shiro权限的工具类
- *
- * @author QiaoLiQiang
- * @time 2018年11月3日下午9:30:46
- */
- public class ShiroPermissionUtils {
- private static final Logger log = LoggerFactory.getLogger(ShiroPermissionUtils.class);
- private ShiroPermissionUtils() {
- }
- /**
- * 检查当前用户是否有权限(任意一项)
- *
- * @param permissionCodes
- * 任意权限
- * @throws NoPermissionException
- */
- public static void checkPerissionAny(String... permissionCodes) {
- if (permissionCodes == null || permissionCodes.length == 0) {
- return;
- }
- // 获取用户信息
- Subject currentUser = SecurityUtils.getSubject();
- for (String permission : permissionCodes) {
- boolean permitted = currentUser.isPermitted(permission);// 判断是否有权限
- if (permitted) {
- return;
- }
- }
- // 没权限就抛出一个异常
- Object principal = currentUser.getPrincipal();
- if (principal instanceof User) {
- User user = (User) principal;
- log.error("user {} no permission !", user.getUsername());
- }
- throw new NoPermissionException("no permission ");
- }
- /**
- * 检查当前用户是否有权限(所有的)
- *
- * @param permissionCodes
- * 任意权限
- * @throws NoPermissionException
- */
- public static void checkPerissionAll(String... permissionCodes) {
- if (permissionCodes == null || permissionCodes.length == 0) {
- return;
- }
- // 获取用户信息
- Subject currentUser = SecurityUtils.getSubject();
- for (String permission : permissionCodes) {
- boolean permitted = currentUser.isPermitted(permission);// 判断是否有权限
- if (!permitted) {
- // 没权限就抛出一个异常
- Object principal = currentUser.getPrincipal();
- if (principal instanceof User) {
- User user = (User) principal;
- log.error("user {} no permission !", user.getUsername());
- }
- throw new NoPermissionException("no permission ");
- }
- }
- }
- }
解释:
(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声明.
- package cn.xm.exam.exception;
- /**
- * 没有权限异常
- *
- * @author QiaoLiQiang
- * @time 2018年11月3日下午9:34:12
- */
- public class NoPermissionException extends RuntimeException {
- /**
- *
- */
- private static final long serialVersionUID = -4442982597754920924L;
- public NoPermissionException(String msg) {
- super(msg);
- }
- }
3.测试Action
方法开始先验证权限,但是没有捕捉异常,如果验证失败异常会抛出在拦截器中被捕捉。
- package cn.xm.exam.action.system;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.context.annotation.Scope;
- import org.springframework.stereotype.Controller;
- import com.opensymphony.xwork2.ActionSupport;
- import cn.xm.exam.utils.ShiroPermissionUtils;
- @Controller
- @Scope("prototype")
- public class SettingsAction extends ActionSupport {
- /**
- * serial
- */
- private static final long serialVersionUID = -5885555441378384728L;
- private static final Logger log = LoggerFactory.getLogger(ShiroPermissionUtils.class);
- public String settings() {
- ShiroPermissionUtils.checkPerissionAny("systemmanager:settings");
- return "settings";
- }
- }
4.struts全局异常拦截器
捕捉到NoPermissionException异常就返回noPermissionError在全局结果集中处理
- package cn.xm.exam.interceptor;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import com.opensymphony.xwork2.ActionInvocation;
- import com.opensymphony.xwork2.interceptor.Interceptor;
- import cn.xm.exam.exception.NoPermissionException;
- public class ExceptionInterception implements Interceptor {
- private static final Logger log = LoggerFactory.getLogger(ExceptionInterception.class);
- /**
- *
- */
- private static final long serialVersionUID = 2268867259828199826L;
- @Override
- public void destroy() {
- }
- @Override
- public void init() {
- }
- @Override
- public String intercept(ActionInvocation arg0) throws Exception {
- log.info("enter ExceptionInterception intercept ... ");
- String result = "";
- try {
- result = arg0.invoke();
- log.info("result -> {}", result);
- } catch (NoPermissionException e) {
- log.error("no permission", e);
- return "noPermissionError";
- } catch (Throwable e) {
- log.error("未处理的异常在拦截器被拦截,class:{}", arg0.getAction().getClass(), e);
- return "interceptorError";
- }
- log.debug("exit ExceptionInterception intercept ... ");
- return result;
- }
- }
5.Struts.xml配置全局异常错误界面:
返回值是noPermissionError跳转到noPermissionError.jsp页面
- <package name="interceptPackage" extends="json-default">
- <!-- 拦截器 -->
- <interceptors>
- <!-- 定义刚才的拦截器 -->
- <interceptor name="exceptionInterceptor"
- class="cn.xm.exam.interceptor.ExceptionInterception"></interceptor>
- <!-- 定义拦截器栈 -->
- <interceptor-stack name="myStack">
- <!-- 拦截器栈里面可以引用另外一个拦截器,也可以引用另外一个拦截器栈 -->
- <interceptor-ref name="defaultStack"></interceptor-ref>
- <interceptor-ref name="exceptionInterceptor"></interceptor-ref>
- </interceptor-stack>
- </interceptors>
- <!-- 这句是设置所有Action自动调用的拦截器堆栈 -->
- <default-interceptor-ref name="myStack" />
- <!-- 拦截器拦截的全局异常 -->
- <global-results>
- <result name="interceptorError">/interceptorError.jsp</result>
- <result name="noPermissionError">/noPermissionError.jsp</result>
- </global-results>
- </package>
6.noPermissionError.jsp页面
给出没权限提醒。
- <%@ page language="java" contentType="text/html; charset=UTF-8"
- pageEncoding="UTF-8"%>
- <%
- String path = request.getContextPath();
- String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()
- + path + "/";
- %>
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>错误提醒</title>
- </head>
- <body>
- <br />
- <span style="font-weight: bold; font-size: 20px; margin: 20px;">对不起,您没有权限访问该请求!</span>
- <br />
- </body>
- </html>
7.测试:
至此,完成了后台验证,也就是在所有方法开始先验证权限。
还有另一种办法就是自定义注解实现权限验证,有点类似于shiro自带的注解验证权限,参考:https://www.cnblogs.com/qlqwjy/p/7257616.html
Shiro后台实现验证权限的更多相关文章
- 基于权限安全框架Shiro的登录验证功能实现
目前在企业级项目里做权限安全方面喜欢使用Apache开源的Shiro框架或者Spring框架的子框架Spring Security. Apache Shiro是一个强大且易用的Java安全框架,执行身 ...
- SpringMVC+Apache Shiro+JPA(hibernate)案例教学(二)基于SpringMVC+Shiro的用户登录权限验证
序: 在上一篇中,咱们已经对于项目已经做了基本的配置,这一篇文章开始学习Shiro如何对登录进行验证. 教学: 一.Shiro配置的简要说明. 有心人可能注意到了,在上一章的applicationCo ...
- 项目一:第十二天 1、常见权限控制方式 2、基于shiro提供url拦截方式验证权限 3、在realm中授权 5、总结验证权限方式(四种) 6、用户注销7、基于treegrid实现菜单展示
1 课程计划 1. 常见权限控制方式 2. 基于shiro提供url拦截方式验证权限 3. 在realm中授权 4. 基于shiro提供注解方式验证权限 5. 总结验证权限方式(四种) 6. 用户注销 ...
- 将 Shiro 作为应用的权限基础 一:shiro的整体架构
将 Shiro 作为应用的权限基础 一:shiro的整体架构 近来在做一个重量级的项目,其中权限.日志.报表.工作量由我负责,工作量还是蛮大的,不过想那么多干嘛,做就是了. 这段时间,接触的东西挺多, ...
- [转]后台页面访问权限:页面基类&内置票据认证 使用方法
本文转自:http://www.cnblogs.com/fishtreeyu/archive/2011/01/29/1947421.html 一般网站后台页面除了登录页面login.aspx未登录用户 ...
- 使用Mongodb+Shiro+SpringMVC实现动态权限分配
此次的文档只对Mongodb整合Shiro并且实现动态权限分配做整理,其它的内容以后会补上. 第一步.创建在web.xml中配置 Spring .Shiro shiroFilter 过滤器是用来将请求 ...
- spring boot(十四)shiro登录认证与权限管理
这篇文章我们来学习如何使用Spring Boot集成Apache Shiro.安全应该是互联网公司的一道生命线,几乎任何的公司都会涉及到这方面的需求.在Java领域一般有Spring Security ...
- 将 Shiro 作为应用的权限基础 二:shiro 认证
认证就是验证用户身份的过程.在认证过程中,用户需要提交实体信息(Principals)和凭据信息(Credentials)以检验用户是否合法.最常见的“实体/凭证”组合便是“用户名/密码”组合. 一. ...
- ecshop 管理后台菜单及权限管理机制
ecshop 所有的一级菜单选项存放于languages\zh_cn\admin\common.php 文件里面,使用 $_LANG['02_cat_and_goods'] = '商品管理'; 这样 ...
随机推荐
- CSS覆盖公共样式中的某个属性
CSS如何覆盖公共样式中的某个属性?利用CSS样式的优先级. 如下例子: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transition ...
- MT【69】斯图姆定理
评:如果说零点存在定理是"只在此山中,云深不知处"的意境.那么斯图姆定理就能处理多项式的零点个数以及定位.
- 19 Zabbix web监控实例
点击返回:自学Zabbix之路 点击返回:自学Zabbix4.0之路 点击返回:自学zabbix集锦 9 Zabbix web监控实例 通过前面的介绍你已经了解Web scenario的配置,下面我们 ...
- 自学Zabbix3.11-宏Macros
点击返回:自学Zabbix之路 点击返回:自学Zabbix4.0之路 点击返回:自学zabbix集锦 自学Zabbix3.11-宏Macros zabbix宏变量让zabbix变得更灵活,它根据一系列 ...
- 【BZOJ2427】[HAOI2010]软件安装(动态规划,Tarjan)
[BZOJ2427][HAOI2010]软件安装(动态规划,Tarjan) 题面 BZOJ 洛谷 题解 看到这类题目就应该要意识到依赖关系显然是可以成环的. 注意到这样一个性质,依赖关系最多只有一个, ...
- 洛谷 P1582 倒水 解题报告
P1582 倒水 题目描述 一天,CC买了N个容量可以认为是无限大的瓶子,开始时每个瓶子里有1升水.接着~~CC发现瓶子实在太多了,于是他决定保留不超过K个瓶子.每次他选择两个当前含水量相同的瓶子,把 ...
- 软Raid50制作
=====创建Raid50的步骤====== 1.创建分区[root@localhost ~]# fdisk /dev/sdb[root@localhost ~]# fdisk /dev/sdc[ro ...
- HDU 3416 Marriage Match IV (最短路径,网络流,最大流)
HDU 3416 Marriage Match IV (最短路径,网络流,最大流) Description Do not sincere non-interference. Like that sho ...
- checkBox全选全不选及数据提交后台
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...
- 解决QtCreator中文乱码
在QT的菜单栏”Tools“ -> "Options" -> "Behavior" -> "File Encoding" ...