博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Shiro后台实现验证权限
阅读量:6609 次
发布时间:2019-06-24

本文共 6490 字,大约阅读时间需要 21 分钟。

  今天发现一个问题:使用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页面

/interceptorError.jsp
/noPermissionError.jsp

 

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 + "/";%>
错误提醒
对不起,您没有权限访问该请求!

 

7.测试:

 

 

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

 

 

还有另一种办法就是自定义注解实现权限验证,有点类似于shiro自带的注解验证权限,参考:

 

转载地址:http://lpiso.baihongyu.com/

你可能感兴趣的文章
python命令行下安装redis客户端
查看>>
如何在Oracle中复制表结构和表数据
查看>>
[河南省ACM省赛-第四届] 序号互换 (nyoj 303)
查看>>
SICIP-1.3-Defining a new function
查看>>
3 Oracle 32位客户端安装及arcgis连接
查看>>
scala2.12.5在windows10、osmac10.13上的安装
查看>>
转自老叶茶馆]系列 — processlist中哪些状态要引起关注
查看>>
小程序上拉加载的坑
查看>>
c++强制类型转换(总结)
查看>>
Server Develop (七) Linux 守护进程
查看>>
libevent (三) 事件注册与循环监听
查看>>
seaborn笔记
查看>>
win10安装ubuntu16.04双系统
查看>>
读人月神话有感
查看>>
Python第一天
查看>>
管理工具
查看>>
未找到工作先遇黑客 八大人事局网站被挂马
查看>>
VB100十二月成绩公布
查看>>
ifanr访谈:GuruDigger — Web工程师排排坐
查看>>
Windows Phone 7新开发工具发布
查看>>