结合shiro使用aop自定义权限验证

#场景 为了敏捷开发,作者在平台中把dao、service、甚至controller三层基本的增删改查都抽象到顶层,这样在一个新模块中只要有了这三层就拥有了增删改查的功能,结合代码生成器大大提升了开发效率,但是在这种情况下,shiro自带的权限验证_@RequiresPermissions_注解就显得有点力不从心了。

#方案 1、采用自定义注解将资源权限分成两块,一块是功能模块注解(@PermissionModule),一块是资源操作注解(@PermissionOperate),这样在抽象出去的controller层面就可以只在@PermissionOperate()定义可访问的资源权限名称,在实际的功能模块类中定义模块名称,两块拼在一起即一个完整的资源权限

代码如下:

/**
 * use for:资源模块
 * Created by javahao on 2017/2/20.
 * auth:JavaHao
 */
@Documented
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface PermissionModule {
    String value() default "";
}
/**
 * use for:资源
 * Created by javahao on 2017/2/20.
 * auth:JavaHao
 */
@Documented
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface PermissionOperate {
    /**
     * 资源
     * @return
     */
    String[] value() default "";

    /**
     * 关系
     * @return
     */
    Relation relation() default Relation.AND;
}

/**
 * use for:关系
 * Created by javahao on 2017/2/24.
 * auth:JavaHao
 */
public enum Relation {
    OR,AND;
}

2、使用AOP在添加了指定注解的方法加切入点,这样在访问指定资源之前,先进行权限校验,如果验证通过则继续访问,如果验证失败则跳转越权页面。

代码如下:

@Aspect
@Component
public class PermissionAop {
    @Before(value="@annotation(operate)")
    public void permission(JoinPoint jp,PermissionOperate operate) throws Throwable{
        Class aspectClz = jp.getTarget().getClass();
        if(aspectClz.isAnnotationPresent(PermissionModule.class)){
            PermissionModule module = (PermissionModule) aspectClz.getAnnotation(PermissionModule.class);
            String[] operates = operate.value();
            String[] checks = new String[operates.length];
            for(int i = 0 ; i < operates.length ; i++){
                checks[i] = module.value()+":"+operates[i];
            }
            if(!UserUtil.isPermitted(operate.relation(),checks))
                throw new UnauthorizedException("用户:["+UserUtil.getName()+"]正在越权访问资源:"+ ArraysUtil.joinStringArray(Arrays.asList(operates),","));
        }
    }
}
/**
 * use for:检测到请求未授权回调
 * Created by javahao on 2017/2/24.
 * auth:JavaHao
 */
@ControllerAdvice
public class UnAuthorizationHandler {
    @ExceptionHandler({UnauthorizedException.class})
    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    public ModelAndView processUnauthenticatedException(NativeWebRequest request, UnauthorizedException e) {
        ModelAndView mv = new ModelAndView();
        mv.addObject("exception", e);
        mv.setViewName("unauthorized");
        return mv;
    }
}

注:

此处作者遇到的难点在aop的@Before地方,初始写法是

@Before(value="@annotation()")
    public void permission(JoinPoint jp) throws Throwable{
        
    }

大家可能注意到了变化@annotation()和方法无参数,这种情况下,如果想要获取到完整的权限标示是比较困难的,作者尝试过N种方法都没能成功这篇博客虽然说得很详细,但是按照博主的方法测试之后,始终还是获取到的代理方法,无法获取到切面的注解。 最终作者在这篇博客中受到启发

@Before(value="@annotation(operate)")
    public void permission(JoinPoint jp,PermissionOperate operate) throws Throwable{
        ......
    }

还有一点资源权限验证是作者扣的shiro的标签源码,大家需要“自扣”即可

<shiro:hasPermission name=""/>

附赠一段使用aop的列选择代码

@AfterReturning(pointcut="within(com..*) && @annotation(columnSelect)",returning="modelAndView")
	public void getCurrentDictColumn(Object modelAndView,ColumnSelect columnSelect) throws Exception{
		//加入列选择
		DictColumns dictColumns = new DictColumns();			
		Module module = new Module();
		module.setId(columnSelect.moduleId());
		String accountId=CurrentProperties.getCurrentAccountCache().getAccount().getId();
		dictColumns.setAccountId(accountId);
		dictColumns.setModule(module);
		List<DictColumns> dictColumnsList=dictColumnsService.listDictColumnsByAccount(dictColumns);
//		HttpServletResponse response = CurrentProperties.getCurrentResponse();
//		response.setCharacterEncoding("UTF-8");
//		PrintWriter printWriter = response.getWriter();
		ModelMap modelMap = ((ModelAndView)modelAndView).getModelMap();
		modelMap.put("dictColumnsList",dictColumnsList);
		modelMap.put("module",module);
		
		/*JsonConfig jsonConfig = new JsonConfig();  
		
		//排除不需要进行转换的属性
		jsonConfig.setExcludes(new String[] { "beanClass","prefix","callback","propertyEditorClass","propertyType","propertyValue","propertyValues","readMethod","writeMethod","writeMethodForActualAccess","writeMethodParameter"});  
		
		//防止自包含形成死循环
		jsonConfig.setCycleDetectionStrategy(CycleDetectionStrategy.LENIENT);
		
		// 当输出时间格式时,采用和JS兼容的格式输出 
		//注:JsDateJsonBeanProcessor 是json-lib已经提供的类,我们也可以实现自己的JsonBeanProcessor
		jsonConfig.registerJsonBeanProcessor(Date.class,new JsDateJsonBeanProcessor());
		
		JSONObject json = JSONObject.fromObject(modelMap,jsonConfig);
		
		printWriter.print(json);
		printWriter.close();*/
	}

更详细的aop讲解 请看这里 共同学习,共同进步!

转载于:https://my.oschina.net/u/2287170/blog/845553

课程简介:历经半个多月的时间,Debug亲自撸的 “企业员工角色权限管理平台” 终于完成了。正如字面意思,本课程讲解的是一个真正意义上的、企业级的项目实战,主要介绍了企业级应用系统中后端应用权限的管理,其中主要涵盖了六大核心业务模块、十几张数据库表。 其中的核心业务模块主要包括用户模块、部门模块、岗位模块、角色模块、菜单模块和系统日志模块;与此同时,Debug还亲自撸了额外的附属模块,包括字典管理模块、商品分类模块以及考勤管理模块等等,主要是为了更好地巩固相应的技术栈以及企业应用系统业务模块的开发流程! 核心技术栈列表: 值得介绍的是,本课程在技术栈层面涵盖了前端和后端的大部分常用技术,包括Spring Boot、Spring MVC、Mybatis、Mybatis-Plus、Shiro(身份认证与资源授权跟会话等等)、Spring AOP、防止XSS攻击、防止SQL注入攻击、过滤器Filter、验证码Kaptcha、热部署插件Devtools、POI、Vue、LayUI、ElementUI、JQuery、HTML、Bootstrap、Freemarker、一键打包部署运行工具Wagon等等,如下图所示: 课程内容与收益: 总的来说,本课程是一门具有很强实践性质的“项目实战”课程,即“企业应用员工角色权限管理平台”,主要介绍了当前企业级应用系统中员工、部门、岗位、角色、权限、菜单以及其他实体模块的管理;其中,还重点讲解了如何基于Shiro的资源授权实现员工-角色-操作权限、员工-角色-数据权限的管理;在课程的最后,还介绍了如何实现一键打包上传部署运行项目等等。如下图所示为本权限管理平台的数据库设计图: 以下为项目整体的运行效果截图: 值得一提的是,在本课程中,Debug也向各位小伙伴介绍了如何在企业级应用系统业务模块的开发中,前端到后端再到数据库,最后再到服务器的上线部署运行等流程,如下图所示:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值