SpEL表达式实现接口权限的控制

SpEL表达式

Spring Expression Language


前言

Spring Expression Language,Spring Framework的核心技术之一,支持在运行时查询和操作对象图;最特别的是方法调用与字符串模板功能.
Spring表达式语言Spring3.0提供的最强大的功能, 可以通过运行期间执行的表达式将值装配到我们的属性 或 构造函数 之中。

一、SpEL是什么?

SpEL 全称是Spring Expression Language。是Spring Framework的核心技术之一。使用AOP +SpEL表达式来实现接口权限的控制。

二、使用步骤

1.自定义权限注解

代码如下(示例):


@Target({ ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface PreAuth {
        String value();
}

2.定义切面类

代码如下(示例):


@Aspect
@Component
public class AuthorAspect{...}

3.指定注解为切点,形成切面(增强通知)

代码如下(示例):



@Around("@annotation(com.shop.annotation.PreAuth) || " + "@within(com.shop.annotation.PreAuth)")
    public Object preAuth(ProceedingJoinPoint point) throws Throwable {
    //连接点 + SpEl表达式实现
   Boolean flag =  this.handleAuth(point);
        if ( flag ) {
            return point.proceed();
        }
        throw new AdminGlobalException("Request_REJECT");
    }

4.SpEl表达式代码实现

代码如下(示例):



  private boolean handleAuth(ProceedingJoinPoint point) {
  //三目运算也是SpEl表达式的基本
    MethodSignature ms = point.getSignature() instanceof MethodSignature? (MethodSignature) point.getSignature():null;
    Method method = ms.getMethod();
    // 读取权限注解,优先方法上,没有则读取类
    PreAuth preAuth = ClassUtil.getAnnotation(method, PreAuth.class);
    // 判断表达式
    String condition = preAuth.value();
    if (StringUtils.isNotBlank(condition)) {
      // 方法参数值
        Object[] args = point.getArgs();

        //1.构造一个解析器
        ExpressionParser expressionPparser= new SpelExpressionParser();
        //2.其次解析器解析字符串表达式
        Expression  expression = expressionParser.parseExpression(condition);
        //3.构造上下文
        StandardEvaluationContext context = this.getEvaluationContext(method, args);
        //4.最后根据上下文得到表达式运算后的值
        return expression.getValue(context, Boolean.class);
    }
    return false;
}```

----------------------------------------------------------------------------------

```java
 private StandardEvaluationContext getEvaluationContext(Method method, Object[] args) {
        //3.1 初始化Spring el表达式上下文,并设置 AuthFun 权限按钮类
        StandardEvaluationContext context = new StandardEvaluationContext(new AuthFun());
        //3.2设置表达式支持spring bean
        context.setBeanResolver(new BeanFactoryResolver(SpringContextUtils.applicationContext));
        for (int i = 0; i < args.length; i++) {
            //读取方法参数
            MethodParameter methodParam = ClassUtil.getMethodParameter(method, i);
            // 3.3设置方法 参数名和值 为spel变量
            context.setVariable(methodParam.getParameterName(), args[i]);
        }
        return context;
    }

5.ClassUtil的依赖包


  <dependency>
            <groupId>net.dreamlu</groupId>
            <artifactId>mica-ip2region</artifactId>
            <version>2.5.6</version>
 </dependency>
 

6.SpringContextUtils获取上下文


@Component
public class SpringContextUtils implements ApplicationContextAware {
	public static ApplicationContext applicationContext; 

	@Override
	public void setApplicationContext(ApplicationContext applicationContext)
			throws BeansException {
		SpringContextUtils.applicationContext = applicationContext;
	}

	public static Object getBean(String name) {
		return applicationContext.getBean(name);
	}

	public static <T> T getBean(String name, Class<T> requiredType) {
		return applicationContext.getBean(name, requiredType);
	}

	public static boolean containsBean(String name) {
		return applicationContext.containsBean(name);
	}

	public static boolean isSingleton(String name) {
		return applicationContext.isSingleton(name);
	}

	public static Class<? extends Object> getType(String name) {
		return applicationContext.getType(name);
	}

}

6.AuthFun类 权限控制类

public class AuthFun {

    /**
     * 判断角色是否具有接口权限
     *
     * @return {boolean}
     */
    public boolean permissionAll() {
        //TODO  全部接口权限
        return true;
    }

    /**
     * 判断角色是否具有接口权限
     *
     * @param permission 权限编号,对应菜单的MENU_CODE
     * @return {boolean}
     */
    public boolean hasPermission(String permission) {
        //TODO 全部接口权限
        return true;
    }

    /**
     * 放行所有请求
     *
     * @return {boolean}
     */
    public boolean permitAll() {
        // TODO  全部接口权限
        return true;
    }

    /**
     * 只有超管角色才可访问
     *
     * @return {boolean}
     */
    public boolean denyAll() {
        return hasRole(SysTypeEnum.ADMIN.name());
    }

    /**
     * 是否已授权
     *
     * @return {boolean}
     */
    public boolean hasAuth() {
        SysUserAuthVO sysUser = SecurityUtils.getSysUser();

        if(sysUser == null ){
            // TODO 返回异常提醒
            return false;
        }else{
            return true;
        }
    }

    /**
     * 是否有时间授权
     *
     * @param start 开始时间
     * @param end   结束时间
     * @return {boolean}
     */
    public boolean hasTimeAuth(Integer start, Integer end) {
        Integer hour = DateUtil.hour(new Date(), true);
        return hour >= start && hour <= end;
    }

    /**
     * 判断是否有该角色权限
     *
     * @param role 单角色
     * @return {boolean}
     */
    public boolean hasRole(String role) {
        return hasAnyRole(role);
    }

    /**
     * 判断是否具有所有角色权限
     *
     * @param role 角色集合
     * @return {boolean}
     */
    public boolean hasAllRole(String... role) {
        for (String r : role) {
            if (!hasRole(r)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 判断是否有该角色权限
     *
     * @param role 角色集合
     * @return {boolean}
     */
    public boolean hasAnyRole(String... role) {
        //获取当前登录用户
        SysUserAuthVO user = SecurityUtils.getSysUser();

        if (user == null) {
            return false;
        }
        String userRole = user.getUsername();
        if (StringUtils.isBlank(userRole)) {
            return false;
        }
        String[] roles = (String[]) user.getAuthorities().toArray();
        for (String r : role) {
            if (CollectionUtil.contains(Arrays.asList(roles), r)) {
                return true;
            }
        }
        return false;
    }


}

总结

利用aop + spel表达式 结合项目实现接口权限控制,实际功能根据自己需要进行扩展.本人在此记录一下我在项目里测试的代码.
项目里的接口权限的控制 实际是用 org.springframework.security 框架实现的,这个框架自带的功能;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值