aop+annotation实现权限管理

功能需求

遇到一个问题,要实现权限管理,也就是有些按钮点击时要提示,没有权限,有很多接口,如果要是按照老的方式,就是每个方法都手写权限判断.十分浪费时间

问题的重要点

  1. 重复的工作,如何解决
  2. 项目并没有引入shiro之类的模块而且session是保存在redis中的,所以分布式的环境也可使用session,如何从session中获取用户信息

话不多少,直接说怎么做

  1. 采用aop实现重复的权限判断
  2. 根据RequestContextHolder这个类可以获取session

Permission注解

import java.lang.annotation.*;

@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
/**
 * 此处在使用时,可以在方法上面加注解
 * example:   @Permission({"/admin/hasPermission","/admin/isAlive"})
 * */
public @interface Permission {
    String[] value() default {};
}
复制代码

PermissionAop

import com.seniortech.test.annotation.Permission;
import com.seniortech.test.entity.Admin;
import com.seniortech.test.response.LayData;
import com.seniortech.test.service.PermissionService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.aspectj.lang.reflect.MethodSignature;
import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Method;
import java.util.Objects;

/**
 * @author husky
 * @date 2019/6/24 17:46
 */
@Aspect
@Configuration
public class PermissionAop {
    @Resource
    private PermissionService permissionService;

    // 定义切点Pointcut
    @Pointcut(value="@annotation(com.seniortech.test.annotation.Permission)")
    public void excudeService(){
    }

    @Around("excudeService()")
    public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        HttpSession session = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest().getSession();
        Admin admin =(Admin) session.getAttribute("admin");//上面两行代码可以获取到request,即可以获取session
        if(!Objects.isNull(admin)){
            System.out.println(admin);
            MethodSignature ms = (MethodSignature) proceedingJoinPoint.getSignature();
            Method method = ms.getMethod();
            Permission permission = ((Method) method).getAnnotation(Permission.class);
            String[] permissions = permission.value();//此处可以获取@Permission中的注解,字符串数组
            //当然要对这个permissions这个判断是否长度为0,本代码中未判断是不严谨的
            if(!permissionService.hasPermission(admin.getId(),permissions)){
                return LayData.builder().code(-1).msg("没有权限").build();
            }
            //此处的LayData是response的统一格式
        }
        Object result = proceedingJoinPoint.proceed();
        return result;
    }
}
复制代码

前端ajax处的封装代码

/**
             * ajax封装
             * url 发送请求的地址
             * data 发送到服务器的数据,数组存储,如: {"date":new Date().getTime(),"state":1}
             * successfn 成功回调函数
             * errorfn 失败回调函数
             * */
            jQuery.postAjax = function (url,data,successfn,errorfn) {
                data = (data === null || data === "" 
                        || typeof (data) === "undefined")
                        ?{"date":new Date().getTime()}:data;
                var loadObj = layer.load(2);
                $.ajax({
                    type: "post",
                    data: data,
                    url: url,
                    success: function (d,textStatus,jqXHR) {
                        layer.close(loadObj);
                        if(d.code === -100){//登录状态已失效
                            layer.confirm("登录已失效,请重新登录",
                                    {icon:2,title: '提示',btn: ['确定'],
                                    closeBtn:0},function (index) {
                                        window.location.href = "/login.html";
                                    })
                            return;
                        }
                        if(d.code === -1) {//无权操作或权限被禁
                            console.log("没有权限");
                            layer.msg(d.msg,{icon:0});
                            return;
                        }
                        successfn(d);
                    },
                    error:function (e) {
                        layer.close(loadObj);
                        if(errorfn !== undefined){
                            errorfn(e);
                        }
                    }
                })
            }
复制代码

后端调用代码

@Permission("/admin/disable")
    @RequestMapping("/disable")
    @ResponseBody
    public Object administratorDisable(Integer userId){
        Integer returnCode = adminService.setStatus(Admin.builder().id(userId.longValue()).status(false).build());
        if(returnCode == 0){
            return LayData.builder().code(400).build();
        }else{
            return LayData.builder().code(200).build();
        }
    }
复制代码

我会更加赞同一些观点,偷懒也是人类进步的阶梯.

在我发现要做重复的事情的时候,第一个想到的事情,应该是十分有方法简化它

此处,要感谢guns开源框架,给我的灵感,使用注解实现aop

aop中获取request 注解配合aop使用,来自guns源码

猜你喜欢

转载自juejin.im/post/5d10e22be51d455ca043627d