通过aop实现接口权限控制

401 阅读2分钟

前言

spring中的另一个大头aop,其强大无法言喻,之前一直基于理论知识,没有做具体的实现,在项目上遇到了需要对接口做权限控制的时候,故想到了aop,如下是实现过程。

背景

当前项目上是在菜单管理那块做了对应的权限字符串的控制,控制当前页面是有哪些类型的操作

image-20221206111058037.png

在配置角色的权限的时候,可以去控制当前角色可以进行哪些操作

image-20221206111221404.png

总而言之,我们只需要在接口上配置对应的权限字符串,查询到该用户所对应的角色有对应的字符串权限,那就可以继续请求目标接口,否则就打回响应为403.

实现

1. 注解

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface RootManager {
    // 操作权限字符串
    String type() default "";
}

2. 标明切点是所有运用上该注解的方法

**
 * 切点,需要拦截的是所有加上该注解的方法
 */
@Pointcut("@annotation(cn.sunline.mrms.commons.AOP.RootManager)")
public void AroundPointCut(){
}

3. 权限判断方法

因为我们需要去控制目标方法的执行与否,所有必须使用环绕方法,通过point.proceed()去执行目标方法

 /**
     * 方法执行前做判断
     * @param point
     * @return
     */
    @Around("AroundPointCut()")
    public Object exceptionHandler (ProceedingJoinPoint point) throws Throwable {
        String userName = cookieService.getCurrentUser().getUserName();
        SQLQuery query = HibernateUtil.currentSession().createSQLQuery("SELECT pu.IS_ADMIN  FROM PF_USER pu WHERE pu.USER_NAME  = :userName");
        query.setParameter("userName",userName);
        String isAdmin = query.uniqueResult().toString();
        // 超级管理员可直接请求
        if ("1".equals(isAdmin)) {
            return point.proceed();
        }
​
        // 获取参数中的菜单数据,结合sql查询是否有对应的类型
        String params = RequestParamsHandle.FParams();
        //  注解获取参数
        MethodSignature signature = (MethodSignature) point.getSignature();
        RootManager rootManager = signature.getMethod().getAnnotation(RootManager.class);
        String type = rootManager.type();
        Map<String, Object> map = (Map<String, Object>) JSONObject.parse(params.replace("[","").replace("]",""));
        String opMenu = map.get("opMenu").toString();
        String menuName = opMenu.substring(opMenu.indexOf('/') + 1,opMenu.length() );
        SQLQuery sqlQuery = HibernateUtil.currentSession().createSQLQuery("SELECT\n" +
                "\t*\n" +
                "FROM\n" +
                "\tPF_RES_ATTR_DATA a\n" +
                "LEFT JOIN PF_MENU_FUNCTION b ON\n" +
                "\ta.RES_REC_ID = b.F_ID\n" +
                "WHERE\n" +
                "\ta.ATTR_REC_ID = (\n" +
                "\tSELECT\n" +
                "\t\tROLE_ID\n" +
                "\tFROM\n" +
                "\t\tPF_USER pu\n" +
                "\tWHERE\n" +
                "\t\tpu.USER_NAME    = :userName) AND b.F_MENUID = (SELECT pm.ID  FROM PF_MENU pm WHERE pm.NAME  = :menuName) AND b.F_FUNCTIONID = :type");
        sqlQuery.setParameter("menuName",menuName);
        sqlQuery.setParameter("userName",userName);
        sqlQuery.setParameter("type",type);
        List list = sqlQuery.list();
        if (list.size() > 0) {
            return point.proceed();
        }
        response.setStatus(HttpServletResponse.SC_FORBIDDEN);
        return Message.error("403","无权限");
    }

4. 汇总

/**
 * 权限控制切面
 * @Author zmx
 * @Date 2022/11/28 15:47
 */
@Aspect
@Component
public class RootManagerAdvice {
​
    @Autowired
    private CookieService cookieService;
​
    @Autowired
    private HttpServletResponse response;
​
  
​
    /**
     * 切点,在注解处切入
     */
    @Pointcut("@annotation(cn.sunline.mrms.commons.AOP.RootManager)")
    public void AroundPointCut(){
    }
​
​
    /**
     * 方法执行前做判断
     * @param point
     * @return
     */
    @Around("AroundPointCut()")
    public Object exceptionHandler (ProceedingJoinPoint point) throws Throwable {
        String userName = cookieService.getCurrentUser().getUserName();
        SQLQuery query = HibernateUtil.currentSession().createSQLQuery("SELECT pu.IS_ADMIN  FROM PF_USER pu WHERE pu.USER_NAME  = :userName");
        query.setParameter("userName",userName);
        String isAdmin = query.uniqueResult().toString();
        // 超级管理员可直接请求
        if ("1".equals(isAdmin)) {
            return point.proceed();
        }
​
        // 获取参数中的菜单数据,结合sql查询是否有对应的类型
        String params = RequestParamsHandle.FParams();
        // todo 注解获取参数
        MethodSignature signature = (MethodSignature) point.getSignature();
        RootManager rootManager = signature.getMethod().getAnnotation(RootManager.class);
        String type = rootManager.type();
        Map<String, Object> map = (Map<String, Object>) JSONObject.parse(params.replace("[","").replace("]",""));
        String opMenu = map.get("opMenu").toString();
        String menuName = opMenu.substring(opMenu.indexOf('/') + 1,opMenu.length() );
        SQLQuery sqlQuery = HibernateUtil.currentSession().createSQLQuery("SELECT\n" +
                "\t*\n" +
                "FROM\n" +
                "\tPF_RES_ATTR_DATA a\n" +
                "LEFT JOIN PF_MENU_FUNCTION b ON\n" +
                "\ta.RES_REC_ID = b.F_ID\n" +
                "WHERE\n" +
                "\ta.ATTR_REC_ID = (\n" +
                "\tSELECT\n" +
                "\t\tROLE_ID\n" +
                "\tFROM\n" +
                "\t\tPF_USER pu\n" +
                "\tWHERE\n" +
                "\t\tpu.USER_NAME    = :userName) AND b.F_MENUID = (SELECT pm.ID  FROM PF_MENU pm WHERE pm.NAME  = :menuName) AND b.F_FUNCTIONID = :type");
        sqlQuery.setParameter("menuName",menuName);
        sqlQuery.setParameter("userName",userName);
        sqlQuery.setParameter("type",type);
        List list = sqlQuery.list();
        if (list.size() > 0) {
            return point.proceed();
        }
        response.setStatus(HttpServletResponse.SC_FORBIDDEN);
        return Message.error("403","无权限");
    }
​
​
}
​