需求

因为在开发环境,测试环境,有时候需要跳过shiro的权限验证.所以想写个简单的配置跳过shiro的权限验证.
跳过权限验证的原理就是重写**@RequiresPermissions**的实现,然后在配置文件中写一个开关,最后通过Aop注入进去就大功告成.

@RequiresPermissions 处理类

在 org.apache.shiro.authz.aop.PermissionAnnotationHandler 中处理这个注解,这就是我们要
覆写的类.我准备将它替换成log日志.

/**
* 检查是否有@{@link org.apache.shiro.authz.annotation。注释是
*声明,如果是,执行权限检查,看是否允许调用Subject继续
*访问。
*
* @since 0.9.0
*/
public class PermissionAnnotationHandler extends AuthorizingAnnotationHandler { /**
*确保调用Subject具有注释指定的权限,如果没有,则抛出
* AuthorizingException表示拒绝访问。
*
*/
public void assertAuthorized(Annotation a) throws AuthorizationException {
if (!(a instanceof RequiresPermissions)) return; RequiresPermissions rpAnnotation = (RequiresPermissions) a;
//获取注解的值
String[] perms = getAnnotationValue(a);
//获取主体
Subject subject = getSubject(); //如果只有一个需要权限
if (perms.length == 1) {
subject.checkPermission(perms[0]);
return;
}
//与的处理
if (Logical.AND.equals(rpAnnotation.logical())) {
getSubject().checkPermissions(perms);
return;
}
//或的处理
if (Logical.OR.equals(rpAnnotation.logical())) {
// Avoid processing exceptions unnecessarily - "delay" throwing the exception by calling hasRole first
boolean hasAtLeastOnePermission = false;
for (String permission : perms) if (getSubject().isPermitted(permission)) hasAtLeastOnePermission = true;
// Cause the exception if none of the role match, note that the exception message will be a bit misleading
if (!hasAtLeastOnePermission) getSubject().checkPermission(perms[0]); }
}
}

通过 AopAllianceAnnotationsAuthorizingMethodInterceptor 加入拦截处理,通过Shiro starter 的 Conguration配置到将AuthorizationAttributeSourceAdvisor注入到 Spring Bean中.AuthorizationAttributeSourceAdvisor 实现了 StaticMethodMatcherPointcutAdvisor

破解

既然找到了实现的方法,那么注入一个自己实现类就可以跳过shiro的权限了.
但是为了只在测试和开发环境破解,需要使用配置来实现

1.配置跳过shiro开关

首先在spring的配置中加入 spring.profiles.active ,同时配置 xfs.shiro.skipShiro为true.
破解时根据当前运行环境和skipShiro来判断是否要跳过shiro

spring:
# 环境 dev|test|prod
profiles:
active: dev
application:
name: system
xfs:
shiro:
skipShiro: true #危险配置,跳过shiro权限控制,用于开发和测试环境调试,慎用
2.重写自己的@RequiresPermissions处理方法

在日志上打log,防止严重的生产问题

package cn.lanhi.auth.starter.interceptor;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.aop.PermissionAnnotationHandler; import java.lang.annotation.Annotation; /**
*

*
* @author : snx cn.shennaixin@gmail.net
* @date : 2020-06-16 11:39
*/
@Slf4j
public class ShiroPermissionHandler extends PermissionAnnotationHandler { public ShiroPermissionHandler() { super();
log.warn("使用了自定义的PermissionHandler,如果是生产环境,使用这个类将会导致权限控制模块失效");
} /**
* 重写权限认证方法,仅仅打印log,不做拦截处理
*
* @param a 注解
* @throws AuthorizationException 一个不可能抛出的异常
*/
@Override
public void assertAuthorized(Annotation a) throws AuthorizationException { if (!(a instanceof RequiresPermissions)) return;
//如果是数组,打印效果不好,使用json序列化
log.warn("警告!! 跳过了权限:{}", JSON.toJSONString(getAnnotationValue(a)));
}
}
3.设置注解处理器

在 AnnotationsAuthorizingMethodInterceptor 这个抽象类的实现类中,添加了对注解的拦截器


package org.apache.shiro.spring.security.interceptor; public class AopAllianceAnnotationsAuthorizingMethodInterceptor
extends AnnotationsAuthorizingMethodInterceptor implements MethodInterceptor { //Shiro拦截器
public AopAllianceAnnotationsAuthorizingMethodInterceptor() { List<AuthorizingAnnotationMethodInterceptor> interceptors =
new ArrayList<AuthorizingAnnotationMethodInterceptor>(5);
AnnotationResolver resolver = new SpringAnnotationResolver();
interceptors.add(new RoleAnnotationMethodInterceptor(resolver));
//注入了我们要破解的权限控制拦截器,
interceptors.add(new PermissionAnnotationMethodInterceptor(resolver));
interceptors.add(new AuthenticatedAnnotationMethodInterceptor(resolver));
interceptors.add(new UserAnnotationMethodInterceptor(resolver));
interceptors.add(new GuestAnnotationMethodInterceptor(resolver)); setMethodInterceptors(interceptors);
}
........
}

那么破解一下,自己继承一下AopAllianceAnnotationsAuthorizingMethodInterceptor,然后获取自身属性,修改值

package cn.lanhi.auth.starter.shiro;

import com.xfs.auth.starter.interceptor.ShiroPermissionHandler;
import org.apache.shiro.authz.aop.AuthorizingAnnotationMethodInterceptor;
import org.apache.shiro.authz.aop.PermissionAnnotationMethodInterceptor;
import org.apache.shiro.spring.security.interceptor.AopAllianceAnnotationsAuthorizingMethodInterceptor; import java.util.List;
import java.util.stream.Collectors; /**
*

shiro 权限重定义


*
* @author : snx cn.shennaixin@gmail.net
* @date : 2020-06-16 11:34
*/
public class ShiroMethodInterceptor extends AopAllianceAnnotationsAuthorizingMethodInterceptor { public ShiroMethodInterceptor() { super();
} /**
* 跳过shiro RequirePremissions 注解验证
*/
public ShiroMethodInterceptor skipPremissionHandler() { List<AuthorizingAnnotationMethodInterceptor> interceptors = this.getMethodInterceptors().stream()
.filter(authorizingAnnotationMethodInterceptor ->
!(authorizingAnnotationMethodInterceptor instanceof PermissionAnnotationMethodInterceptor))
.collect(Collectors.toList());
PermissionAnnotationMethodInterceptor interceptor = new PermissionAnnotationMethodInterceptor();
//设置成自己的注解处理器!
interceptor.setHandler(new ShiroPermissionHandler());
interceptors.add(interceptor);
setMethodInterceptors(interceptors);
return this;
}
}
4.重写shiroAop
package org.apache.shiro.spring.config;
/**
* shiro AOP
* @since 1.4.0
*/
@Configuration
public class ShiroAnnotationProcessorConfiguration extends AbstractShiroAnnotationProcessorConfiguration{ @Bean
@DependsOn("lifecycleBeanPostProcessor")
protected DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() { return super.defaultAdvisorAutoProxyCreator();
} @Bean
protected AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) { return super.authorizationAttributeSourceAdvisor(securityManager);
} } --------------------
--------------------
--------------------
这个 AuthorizationAttributeSourceAdvisor 提供了AOP的拦截器实现.接下来我们要覆盖他,
/**
* Create a new AuthorizationAttributeSourceAdvisor.
*/
public AuthorizationAttributeSourceAdvisor() { setAdvice(new AopAllianceAnnotationsAuthorizingMethodInterceptor());
}
--------------------
--------------------
--------------------
5.覆盖Shiro Bean

判断了一下环境,跳过Shiro 权限验证,仅在测试和开发环境生效,且需要开启配置
注意bean要设置成@primary

 /**
* 跳过Shiro 权限验证,仅在测试和开发环境生效
*
* @param securityManager
* @return
*/
@Bean("authorizationAttributeSourceAdvisor")
@Primary
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(
SecurityManager securityManager,
Environment environment,
@Value("${xfs.shiro.skipShiro:false}") boolean skipShiro) {
//获取当前运行环境
String profile = environment.getRequiredProperty("spring.profiles.active");
//创建要生成的Bean
AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
advisor.setSecurityManager(securityManager);
//判断是否可以跳过shiro
if (skipShiro && ("dev".equals(profile) || "test".equals(profile))) {
//运行跳过shiro权限验证方法
advisor.setAdvice(new ShiroMethodInterceptor().skipPremissionHandler());
}
return advisor;
}

到此为止,就大功告成啦.

Shiro配置跳过权限验证的更多相关文章

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

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

  2. JavaEE权限管理系统的搭建(六)--------使用拦截器实现菜单URL的跳转权限验证和页面的三级菜单权限按钮显示

    本小结讲解,点击菜单进行页面跳转,看下图,点击管理员列表后会被认证拦截器首先拦截,验证用户是否登录,如果登录就放行,紧接着会被权限验证拦截器再次拦截,拦截的时候,会根据URL地址上找到对应的方法,然后 ...

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

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

  4. 简单两步快速实现shiro的配置和使用,包含登录验证、角色验证、权限验证以及shiro登录注销流程(基于spring的方式,使用maven构建)

    前言: shiro因为其简单.可靠.实现方便而成为现在最常用的安全框架,那么这篇文章除了会用简洁明了的方式讲一下基于spring的shiro详细配置和登录注销功能使用之外,也会根据惯例在文章最后总结一 ...

  5. shiro配置unauthorizedUrl,无权限抛出无权限异常,但是不跳转

    在使用shiro配置无授权信息的url的时候,发现这样的一个scenario,配置好unauthorizedUrl后仍然无法跳转,然后就在网上开始找,找了原因以及解决方案 原因,先post一个源码: ...

  6. Shiro权限验证代码记录,正确找到shiro框架在什么地方做了权限识别

    权限验证方式的验证代码: org.apache.shiro.web.servlet.AdviceFilter这个类是所有shiro框架提供的默认权限验证实例类的父类 验证代码: public void ...

  7. 自定义shiro实现权限验证方法isAccessAllowed

    由于Shiro filterChainDefinitions中 roles默认是and, admin= user,roles[system,general] 比如:roles[system,gener ...

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

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

  9. Spring+shiro配置JSP权限标签+角色标签+缓存

    Spring+shiro,让shiro管理所有权限,特别是实现jsp页面中的权限点标签,每次打开页面需要读取数据库看权限,这样的方式对数据库压力太大,使用缓存就能极大减少数据库访问量. 下面记录下sh ...

  10. shiro登陆权限验证

    一>引入shirojar包 <!-- shiro登陆权限控制 -->        <dependency>            <groupId>org. ...

随机推荐

  1. Serilog文档翻译系列(八) - 记录器的生命周期、可靠性

    01.记录器的生命周期 Serilog 大多数情况下"只需使用",并且在创建和处理日志记录器时不需要过多考虑.然而,由于以下原因: 某些接收器(sink)涉及后台进程,特别是那些使 ...

  2. .Net 理解异步的学习

    // 异步 - 在方法中使用 // 异步约等于线程 async await 一起使用 // 异步只有三种返回值 // 1. Task // 2. Task<T> // 3. void 几乎 ...

  3. DDD实体和对象

    实体 entity 标识符用来唯一定位一个对象,在数据库中我们一般用表的主键来实现标识符,主键和标识符的思考角度不同,就是 id 字段 : 实体:拥有唯一的标识符,标识符的值不会改变,而其他对象的状态 ...

  4. Python之py9-微信监控获取mp3_url

    #!/usr/bin/env python # -*- coding:utf-8 -*- import re import requests import wxpy name_url_list = [ ...

  5. 自学PHP笔记(一)PHP语法

    PHP基本语法 php使用一对特殊的标记包含php代码,与HTML代码混在一起.当服务器解析页面时,能够自动过滤出PHP脚本并进行解释,最后把生成的静态网页传递给客户端. 1.PHP标记 一般情况下, ...

  6. Re:从零开始的pwn学习(栈溢出篇)

    写在前面:本文旨在帮助刚接触pwn题的小伙伴少走一些弯路,快速上手pwn题,内容较为基础,大佬轻喷.本文默认读者明白最基础的汇编指令的含义,并且已经配置好linux64位环境,明白基础的Linux指令 ...

  7. 使用wxpython开发跨平台桌面应用,对常用消息对话框的封装处理

    在很多程序中,封装常用消息对话框有很多好处,尤其是在 GUI 应用程序中,本篇随笔结合.net 开发Winform界面的经验,对使用wxpython开发中 wx.MessageDialog 和 wx. ...

  8. C240731B

    B 游戏类问题 先假设一瓶毒药都不用, 先把治疗的贡献加进答案里面,这样治疗.毒药.攻击的贡献分别是独立的. 如果 \(i\) 位置本来是治疗, 那么用毒药多扣的血是 \(a[i]=(p+r) \ti ...

  9. 如何在国内使用gcr.io镜像进行拉取

    [root@k8scloude2 ~]# docker pull gcr.io/google-samples/microservices-demo/emailservice:v0.4.0 换成 [ro ...

  10. ServiceMesh 4:实现流量染色和分级发布

    ★ ServiceMesh系列 1 什么是流量染色 在复杂的生产场景中,经常会有同一个服务中,存在多个版本长期共存的需求.为了让不同的用户在不一样的版本中使用,就需要对用户的请求进行采样和染色,打上不 ...