應用場景,在方法級別對本次調用進行鑑權,如api接口中有個用戶惟一標示accessToken,對於有accessToken的每次請求能夠在方法加一個攔截器,得到本次請求的用戶,存放到request或者session域。java
python中,以前在python flask中能夠使用裝飾器來對方法進行預處理,進行權限處理python
先看一個實例,使用@access_required攔截:web
@api.route('/post_apply') @access_required def apply(): """ 活動報名 """ print '報名者是:'+g.user return jsonify(response_data)
實現很簡單:spring
# 驗證access_token並保存當前用戶到g中 def access_required(f): @wraps(f) def decorated_func(*args, **kwargs): access_token = request.values.get('access_token') if access_token == None: return error_msg('500', 'access_token required') if access_token == "": return error_msg('500', 'access_token can not empty') if is_access_token(access_token) == False: return error_msg('500', 'invalid_access_token') return f(*args, **kwargs) return decorated_func
java中,自定義註解攔截器來實現,在須要的攔截的方法上面加上一個註解@AccessRequiredjson
spring mvc Controller中的使用實例flask
/** * 註解攔截器方法 * @return */ @RequestMapping(value="/urlinter",method=RequestMethod.GET) @AccessRequired public @ResponseBody String urlInterceptorTest() { return "經過攔截器:user"+request.getAttribute("currUser"); }
如何實現以上實例呢?api
定義一個註解:session
import java.lang.annotation.ElementType; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.annotation.Retention; @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface AccessRequired { }
搞一個攔截器:mvc
/** * 攔截url中的access_token * @author Nob * */ public class UserAccessApiInterceptor extends HandlerInterceptorAdapter { public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { HandlerMethod handlerMethod = (HandlerMethod) handler; Method method = handlerMethod.getMethod(); AccessRequired annotation = method.getAnnotation(AccessRequired.class); if (annotation != null) { System.out.println("你遇到了:@AccessRequired"); String accessToken = request.getParameter("access_token"); /** * Do something */ response.getWriter().write("沒有經過攔截,accessToken的值爲:" + accessToken); } // 沒有註解經過攔截 return true; } }
在spring mvc配置文件中:app
<!-- 攔截器 --> <mvc:interceptors> <mvc:interceptor> <!-- 對全部的請求攔截使用/** ,對某個模塊下的請求攔截使用:/myPath/* --> <mvc:mapping path="/api/**" /> <ref bean="userAccessInterceptor" /> </mvc:interceptor> </mvc:interceptors> <bean id="userAccessInterceptor" class="com.banmacoffee.web.interceptor.UserAccessApiInterceptor"> </bean>
注意問題:
若是你使用了<mvc:resources mapping="/resources/**" location="/resources/" />來配置靜態資源,那麼配置如上攔截器的時候就要使用使用了全局攔截/**,不然會攔截靜態資源拋出ResourceHttpRequestHandler cannot be cast to HandlerMethod異常
辦法一:加上攔截路徑前綴
<mvc:mapping path="/path/**" />
<!-- 這裏使用一個path前置,如api,不然會攔截靜態資源 -->
辦法二:在自定義攔截器中使用instanceof 過濾ResourceHttpRequestHandler 類型
大功告成,你能夠在攔截器裏隨心所欲,而且把它加載任何你想的Controller 請求的方法上