天天看點

[Spring] Web層AOP方式處理登入和權限問題

參考: [Spring] Web層AOP方式進行參數校驗

方法一樣,隻是把原來登陸和權限校驗放在了AOP方法裡。

使用者權限是存放在session裡的。

另外,如果登入時需要在注解裡傳入角色字段,可以用@Around("aopMethod() && @annotation(loginRequired)")實作。

其中,loginRequired是自定義的注解,如下:

package com.zp.haveplace.annotation;

import com.zp.haveplace.common.RoleConst;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 自定義注解
 * 有此注解的方法必須檢查是否登入管理者,且是否具備value所指定的權限
 * @author zp
 * @date 2018/4/20
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LoginRequired {
    String value() default RoleConst.ADMIN + "";//預設值為管理者權限
}
           

AOP部分代碼

package com.zp.haveplace.aop;

import com.zp.haveplace.annotation.LoginRequired;
import com.zp.haveplace.bean.LoggerBean;
import com.zp.haveplace.bean.ResponseBean;
import com.zp.haveplace.common.ResponseBeanCode;
import com.zp.haveplace.common.ResponseBeanType;
import com.zp.haveplace.common.RoleConst;
import com.zp.haveplace.common.SessionConstant;
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.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.net.ResponseCache;

/**
 * 對有 @LoginRequired 注解的web方法檢查是否登入,并檢查是否具有value所指定的權限
 * AOP方式
 * @author zp
 * @date 2018/4/20
 */
@Component
@Aspect
public class LoginRequiredAop {

    /**
     * 切入點
     * 設定切入點為web層
     * AspectJ支援命名切入點,方法必須是傳回void類型
     */
    @Pointcut("execution(* com.zp.haveplace.web..*.*(..))")
    public void aopMethod(){}

    /**
     * 檢查是否已經登入
     * web層方法且方法上有 '@LoginRequired' 注解
     * @param joinPoint
     * @return
     * @throws Throwable
     */
    @Around("aopMethod() && @annotation(loginRequired)")
    public Object around(ProceedingJoinPoint joinPoint, LoginRequired loginRequired) throws Throwable{
        HttpServletRequest request = null;

        for(Object arg:joinPoint.getArgs()){//周遊被通知方法的參數清單
            if(arg instanceof HttpServletRequest){
                request = (HttpServletRequest) arg;
            }
        }

        // 沒有找到request參數,無法檢查權限
        if(request == null){
            LoggerBean.SYSTEM.error("檢查權限時未找到HttpServletRequest參數,可能綁定失敗");
            return new ResponseBean().setErrorResponse("系統出現錯誤,檢查權限時未找到HttpServletRequest參數");
        }

        // 檢查登入
        if(request.getSession().getAttribute(SessionConstant.LOGIN_ADMIN_ACCOUNT_SESSION_KEY) == null){
            return new ResponseBean().setResponse(ResponseBeanType.ERROR,
                    ResponseBeanCode.NO_LOGIN,
                    "您未登入");
        }

        // 檢查權限
        Integer role = (Integer)request.getSession().getAttribute(SessionConstant.LOGIN_ADMIN_ROLE_SESSION_KEY);
        if(role > Integer.valueOf(loginRequired.value())){
            return new ResponseBean().setResponse(ResponseBeanType.ERROR,
                    ResponseBeanCode.NO_POWER,
                    "您沒有權限,需要" +
                            RoleConst.ROLE_INFO[Integer.valueOf(loginRequired.value())] +
                            "權限");
        }

        return joinPoint.proceed();//執行目标方法
    }
}