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中的处理逻辑。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享