基于注解使用AOP,实现实时刷新Shiro 过滤器链,验证用户每次访问API接口权限

15 篇文章 0 订阅
6 篇文章 0 订阅

前言:

后端接口的调用,必须受到用户权限的限制,对某个用户是否有权限访问该接口,其角色,部门,等都是影响因素,还有一个用户的状态,也是变化的等,需要做到每次调用接口,都要实时刷新一下,该用户是否有权限访问?

步骤:

从需求出发,既然是需要做到每次调用接口,都要实时刷新一下,该用户是否有权限访问?肯定要用注解!

建自定义注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RefreshFilterChain {
}

凡是标记该注解,均会引发 Shiro 过滤器链的变化, 将刷新过滤器链.

建AOP刷新切面类

@Aspect
@Component
public class RefreshFilterChainAspect {

    @Resource
    private ShiroService shiroService;

    @Pointcut("@annotation(aaaa.bbbb.common.annotation.RefreshFilterChain)")
    public void updateFilterChain() {}

    @AfterReturning("updateFilterChain()")
    public void doAfter() {
        shiroService.updateFilterChain();
    }

}

建AOP的刷新切面类,便于以后注解到各个API上,实现更新过滤器链!

在shiro服务类ShiroService,加入实现

public void updateFilterChain() {
	synchronized (shiroFilterFactoryBean) {
		AbstractShiroFilter shiroFilter;
		try {
			shiroFilter = (AbstractShiroFilter) shiroFilterFactoryBean.getObject();
		} catch (Exception e) {
			throw new ShiroException("get ShiroFilter from shiroFilterFactoryBean error!");
		}
		PathMatchingFilterChainResolver filterChainResolver = (PathMatchingFilterChainResolver) shiroFilter.getFilterChainResolver();
		DefaultFilterChainManager manager = (DefaultFilterChainManager) filterChainResolver.getFilterChainManager();
		// 清空老的权限控制
		manager.getFilterChains().clear();
		shiroFilterFactoryBean.getFilterChainDefinitionMap().clear();
		shiroFilterFactoryBean.setFilterChainDefinitionMap(getUrlPermsMap());
		userNameRealm.clearAllAuthCache();

		// 清除每个 Filter 中的 appliedPaths 信息
		for (Map.Entry<String, Filter> filterEntry : manager.getFilters().entrySet()) {
			if (filterEntry.getValue() instanceof PathMatchingFilter) {
				PathMatchingFilter filter = (PathMatchingFilter) filterEntry.getValue();
				Map<String, Object> appliedPaths = (Map<String, Object>) ReflectUtil.getFieldValue(filter, "appliedPaths");
				synchronized (appliedPaths) {
					appliedPaths.clear();
				}
			}
		}

		// 重新构建生成
		Map<String, String> chains = shiroFilterFactoryBean
				.getFilterChainDefinitionMap();
		for (Map.Entry<String, String> entry : chains.entrySet()) {
			String url = entry.getKey();
			String chainDefinition = entry.getValue().trim().replace(" ", "");
			manager.createChain(url, chainDefinition);
		}

		log.info("更新 Shiro 过滤器链");
	}
}

在shiroService实现updateFilterChain()方法,实现清空老的权限控制,清除每个 Filter 中的 appliedPaths 信息,重新构建生成权限控制,从而实现更新 Shiro 过滤器链

在Controller中的crud的API方法上加上@RefreshFilterChain

@OperationLog("新增菜单")
@RefreshFilterChain
@PostMapping
@ResponseBody
public ResultBean add(Menu menu) {
	menuService.insert(menu);
	return ResultBean.success();
}

这样就可以安全的开放接口,给别人,防止自己的接口,被恶搞了!

总结:

以上是一种思路,从需求出发,进而展开,对代码的编写,涉及到很多知识点,如:

spring的aop的运用

  • Pointcut:Pointcut定义时,还可以使用&&、||、! 这三个运算。进行逻辑运算。可以把各种条件组合起来使用
  • AfterReturning:使用@AfterReturning注解时,指定了一个returning属性,该属性值为rvt,这表明允许在Advice方法(log()方法)中定义名为rvt的形参,程序可通过rvt形参来访问目标方法的返回值

shiro的三个核心组件:Subject, SecurityManager 和 Realms.

  • Subject:即“当前操作用户”。但是,在Shiro中,Subject这一概念并不仅仅指人,也可以是第三方进程、后台帐户(Daemon Account)或其他类似事物。它仅仅意味着“当前跟软件交互的东西”。Subject代表了当前用户的安全操作,SecurityManager则管理所有用户的安全操作。
  • SecurityManager:它是Shiro框架的核心,典型的Facade模式,Shiro通过SecurityManager来管理内部组件实例,并通过它来提供安全管理的各种服务。
  • Realm: Realm充当了Shiro与应用安全数据间的“桥梁”或者“连接器”。也就是说,当对用户执行认证(登录)和授权(访问控制)验证时,Shiro会从应用配置的Realm中查找用户及其权限信息。

在ShiroFilterFactoryBean中,createFilterChainManager方法比较重要,包含以下必要操作:

  • DefaultFilterChainManager对象的创建
  • defaultFilters的获取和相关url的填充
  • 自定义filters的获取和相关url的填充
  • 获取FilterChainDefinitionMap (这个就是配置文件中的filterChainDefinitions的映射关系)
  • 对url和权限的映射关系作处理

DefaultFilterChainManager,是路径和filter的管理类filterChainManager的实现类,用于管理我们在shiroFilterFactoryBean中配置的过滤器和模板,以及配置的参数

  • 获得spring中的所有filters,都被放入到这个类(filterChainManager)中
  • filter根据pathPattern(路径模板)进行分类,方便再查找某个路径的对应的filterChain时,采取的提前分类处理。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿啄debugIT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值