spring AOP 和自定義註解進行身份驗證

一個SSH的項目(springmvc+hibernate),須要提供接口給app使用。首先考慮的就是權限問題,app要遵循極簡模式,部份內容無需驗證,用過濾器不能解決某些無需驗證的方法 因此最終選擇用AOP 解決。大體思路是使用自定義註解,在須要權限控制的方法前(controller層)使用註解而後使用AOP攔截訪問的方法,判斷當前用戶是否登陸了(判斷是否攜帶了登陸以後獲取到的 token ),從而決定是否攔截。javascript

開啓切面代理

    <!--aop配置,基於類的代理 -->
    <!-- <aop:aspectj-autoproxy  proxy-target-class="true"/>-->
    <aop:aspectj-autoproxy/>

注意:1、必定要放在spring的配置文件中,不要單獨新建一個文件html

         二、proxy-target-class屬性值決定是基於接口的仍是基於類的代理被建立。若是proxy-target-class 屬性值被設置爲true,那麼基於類的代理將起做用(這時須要cglib庫)。若是proxy-target-class屬值被設置爲false或者這個屬性被省略,那麼標準的JDK 基於接口的代理將起做用。前端

編寫一個自定義註解

@Retention(RetentionPolicy.RUNTIME)//註解會在class中存在,運行時可經過反射獲取    
@Target(ElementType.METHOD)//目標是方法  
@Documented
public @interface LoginRequired{

}

ElementType.MeTHOD 表示該自定義註解能夠用在方法上
RetentionPolicy.RUNTIME 表示該註解在代碼運行時起做用java

能夠在自定義註解中加入一些默認方法jquery

定義切面類驗證權限

@Component
@Aspect
public class TokenInterceptor {

    private static final Logger logger = Logger.getLogger(TokenInterceptor.class);

    @Resource
    private BllUserService bllUserService;

    @Pointcut("@annotation(org.jeecgframework.core.annotation.LoginRequired)")  
    public  void serviceAspect() {  
    }  
//環繞通知(特別適合作權限系統)
//@Before @Around("serviceAspect()") public Object checkPermission(ProceedingJoinPoint joinPoint) throws Throwable{ AjaxJson json=new AjaxJson(); // String methodName = joinPoint.getSignature().getName(); // Object target = joinPoint.getTarget(); // Method method = getMethodByClassAndName(target.getClass(), methodName); //獲得攔截的方法 Object[] args = joinPoint.getArgs(); HttpServletRequest request=(HttpServletRequest)args[0]; if(!validate(request)){ //request.setAttribute("message", "您沒有執行該操做權限"); json.setMsg("您沒有執行該操做權限"); json.setSuccess(false); return json; } return joinPoint.proceed(); } private boolean validate(HttpServletRequest request)throws Exception {
// String token=request.getParameter("token");//根據前端傳值進行修改 String token
=request.getHeader("token"); if(StringUtil.isEmpty(token)){ } Map<String, Object> resultMap=Jwt.validToken(token); TokenState state=TokenState.getTokenState((String)resultMap.get("state")); switch (state) { case VALID: //取出payload中數據,放入到request做用域中 request.setAttribute("data", resultMap.get("data")); break; case EXPIRED://暫時沒作 case INVALID: return false; } return true; } public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { }

@Aspect放在類頭上,把這個類做爲一個切面。ajax

@Compenent註解標識其爲Spring管理Bean,而@Aspect註解不能被Spring自動識別並註冊爲Bean,必須經過@Component註解來完成spring

注:這兒用了JWT作token驗證,感興趣的同窗自行百度json

TOKEN驗證類

   /**
     * 校驗token是否合法,返回Map集合,集合中主要包含    state狀態碼   data鑑權成功後從token中提取的數據
     * 該方法在過濾器中調用,每次請求API時都校驗
     * @param token
     * @return  Map<String, Object>
     */
    public static Map<String, Object> validToken(String token) {
        Map<String, Object> resultMap = new HashMap<String, Object>();
        try {
            JWSObject jwsObject = JWSObject.parse(token);
            Payload payload = jwsObject.getPayload();
            JWSVerifier verifier = new MACVerifier(SECRET);

            if (jwsObject.verify(verifier)) {
                JSONObject jsonOBj = payload.toJSONObject();
                // token校驗成功(此時沒有校驗是否過時)
                resultMap.put("state", TokenState.VALID.toString());
                // 若payload包含ext字段,則校驗是否過時
                if (jsonOBj.containsKey("ext")) {
                    long extTime = Long.valueOf(jsonOBj.get("ext").toString());
                    long curTime = new Date().getTime();
                    // 過時了
                    if (curTime > extTime) {
                        resultMap.clear();
                        resultMap.put("state", TokenState.EXPIRED.toString());
                    }
                }
                resultMap.put("data", jsonOBj);

            } else {
                // 校驗失敗
                resultMap.put("state", TokenState.INVALID.toString());
            }

        } catch (Exception e) {
            //e.printStackTrace();
            // token格式不合法致使的異常
            resultMap.clear();
            resultMap.put("state", TokenState.INVALID.toString());
        }
        return resultMap;
    }    

配置攔截器

    @RequestMapping(params = "physicalList")
    @ResponseBody
    @LoginRequired
    public AjaxJson getPhysicalList(HttpServletRequest request){
    
    }

測試

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="initial-scale=1, maximum-scale=1">
        <title></title>
    </head>
    <body>
        
        <button type="button"  onclick="getdata()">測試頁面</button><br/>
        <script type="text/javascript" src="js/jquery.min.js" ></script>
        <script>
             var token="123";
            function getdata(){
                $.ajax({
                    type:"post",
                    dataType:"json",
                    url:"",
                    headers:{
                        token:token//將token放到請求頭中
                    },
        //            beforeSend: function(request) {
         //               request.setRequestHeader("token", token);
          //          },
                    success:function(data){
                        console.log(data);
                        $('body').append(JSON.stringify(data));
                        
                    },
            });
            }
        </script>
    </body>
</html>

能夠發現頁面請求被攔截了restful

 

 

參考:http://blog.csdn.net/caomiao2006/article/details/51287206mvc

http://www.jianshu.com/p/576dbf44b2ae

http://www.scienjus.com/restful-token-authorization/

相關文章
相關標籤/搜索