SpringMVC 註解式攔截器實現

Huluwa-Notify系統在接收合作方的通知內容時,需要進行訪問控制,即需要對訪問的IP進行限制,防止惡意用戶篡改消息通知我們。
爲了實現方法的通用性,並降低對系統的侵入性,我選擇使用SpringMVC的註解式攔截器實現對訪問IP進行控制,只允許系統配置的IP
訪問我們的Notify系統,而其他IP返回的消息不予處理,並報警提示。

一.首先介紹一下攔截器接口:

HandlerInterceptor是Spring MVC爲我們提供的攔截器接口,來讓我們實現自己的處理邏輯,如下:

public interface HandlerInterceptor {  
    boolean preHandle(  
            HttpServletRequest request, HttpServletResponse response,   
            Object handler)   
            throws Exception;  

    void postHandle(  
            HttpServletRequest request, HttpServletResponse response,   
            Object handler, ModelAndView modelAndView)   
            throws Exception;  

    void afterCompletion(  
            HttpServletRequest request, HttpServletResponse response,   
            Object handler, Exception ex)  
            throws Exception;  
}
  • preHandle:在執行action裏面的處理邏輯之前執行,它返回的是boolean,如果返回true再接着執行action中的內容,如果返回false則中斷返回。
  • postHandle:在執行action裏面的邏輯後,返回結果之前執行。
  • afterCompletion:在action返回結果之後執行。
    另外,Spring MVC爲了方便我們使用HandlerInterceptor還爲我們提供了默認實現:HandlerInterceptorAdapter。我們也可以繼承HandlerInterceptorAdapter,
    實現3個方法中我們需要的方法,而不再需要3個方法全部實現。
    藉助於HandlerInterceptor我們可以實現很多功能,比如日誌記錄、請求處理時間分析等,只要是action中具有通用性質的邏輯都建議採用攔截器來處理。

二.下面就來一步一步實現註解式IP限制的功能。

首先,自定義註解AuthorityIP

@Documented
@Target(
{ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface AuthorityIP
{
    String name();
}

@Target 選擇Method和Type則表明,這個註解既可以放在controller類上,對整個controller的所有接口生效。也可以放在方法上,只對controller的一個接口生效。
@Retention 選擇Runtime,則保證了能在運行時被JVM或其他使用反射機制的代碼所讀取和使用。

然後,添加自己的攔截器實現AuthorityIPInterceptor繼承自HandlerInterceptorAdapter:

public class AuthorityIPInterceptor extends HandlerInterceptorAdapter
{
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception
    {
        if (handler instanceof HandlerMethod)
        {
            AuthorityIP authorityIP = ((HandlerMethod) handler).getMethodAnnotation(AuthorityIP.class);

            //controller沒有添加AuthorityIP註解
            if (authorityIP == null)
            {
                return true;
            }
            String requestIp = NetUtil.getCurrentLoginUserIp(request);
            if (StringUtils.isEmpty(requestIp))
            {
                log.fatal("NetUtil.getCurrentLoginUserIp get a null Ip");
                return true;
            }
            log.info("platform:" + authorityIP.name() + ",notify Ip is:" + requestIp);
            return containsIps(requestIp, ",", authorityIP);
        }
        return true;
    }

在攔截器的preHandle方法中實現我們需要的IP限制功能。

在Spring的配置文件Spring-notify中配置攔截器

<!-- 攔截器配置 -->
    <mvc:interceptors>
        <!-- 如果不定義 mvc:mapping path 將攔截所有的URL請求 -->
        <bean class="com.notify.Interceptor.AuthorityIPInterceptor"></bean>
    </mvc:interceptors>

最後,在需要進行IP限制的接口上,添加AuthorityIP註解。

    @ResponseBody
    @RequestMapping(value = "/notify.html")
    @AuthorityIP(name = "notify")
    public String acceptNotify(HttpServletRequest request, HttpServletResponse response)
    {
        log.info("acceptNotify!");
    }

這樣,在訪問添加@AuthorityIP註解的接口時,就會校驗訪問IP是否符合要求,只有符合要求的IP才能進一步執行action中的處理邏輯。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章