一個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是否合法,返回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/