基于AOP的ajax的referrer判断
程序员文章站
2022-07-10 19:10:56
...
网页中ajax请求的referrer的值是当前域名。(其实这个工作nginx来做最好)
所以对于一些简单的安全验证可以通过这样的方式来做。
下面是我的实现。
所以对于一些简单的安全验证可以通过这样的方式来做。
下面是我的实现。
import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * 用于ajax请求时,通过referrer对请求合法性做验证的注解 * 注解的controller方法中必须包含HttpServletRequest和HttpServletResponse参数且参数被放置与参数列表最后request在前response在后 * */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited public @interface AjaxReferrerAuthentication { String hostString() default "xxxxxx.com"; }
import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.stream.Collectors; import java.util.stream.Stream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang3.StringUtils; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import com.xxx.h5.support.annotation.AjaxReferrerAuthentication; import com.xxx.h5.vo.MessageEntity; @Aspect @Component public class AjaxReferrerAspect { private final Logger logger = LoggerFactory.getLogger(getClass()); @Around(value = "execution(public * com.xxx.h5.controller..*(..)) && args(..,request,response) && @annotation(ajaxReferrer)") public MessageEntity authenticationReferrer(ProceedingJoinPoint jp, HttpServletRequest request, HttpServletResponse response, AjaxReferrerAuthentication ajaxReferrer) { // 由于Http规范以前对referrer写错,所以对两种写法都兼容下 String referrer = StringUtils.isNotEmpty(request.getHeader("referer")) ? request.getHeader("referer") : request.getHeader("referrer"), errMsg = ""; URL referrerURL = null; MessageEntity me = null; try { referrerURL = new URL(referrer); } catch (MalformedURLException e) { logger.info("验证referrer时,解析referrer地址异常"); logger.info(jp.getClass() + "=>方法=>" + jp.getSignature() + "参数=>" + Stream.of(jp.getArgs()) .map(String::valueOf) .collect(Collectors.joining(","))); logger.error(e.getMessage()); return me; } // 使用AjaxReferrerAuthentication注解的controller方法只给ajax请求,所以如果是从我们自己的页面过来的ajax请求一定是带上referrer的 if (StringUtils.isEmpty(referrer)) { errMsg = "非法请求"; } else if (!referrerURL.getHost().endsWith(ajaxReferrer.hostString())) { errMsg = "非法请求"; } if (StringUtils.isNotEmpty(errMsg)) { try { response.sendError(HttpServletResponse.SC_FORBIDDEN); } catch (IOException e) { logger.info("验证referrer时,返回Http状态时异常(IO异常)"); logger.info(jp.getClass() + "=>方法=>" + jp.getSignature() + "参数=>" + Stream.of(jp.getArgs()) .map(String::valueOf) .collect(Collectors.joining(","))); logger.error(e.getMessage()); } return me; } try { me = (MessageEntity) jp.proceed(); } catch (Throwable e) { logger.info("验证referrer后,执行切点方法时异常"); logger.info(jp.getClass() + "=>方法=>" + jp.getSignature() + "参数=>" + Stream.of(jp.getArgs()) .map(String::valueOf) .collect(Collectors.joining(","))); logger.error(e.getMessage()); } return me; }
下一篇: 从栈帧看字节码是如何在JVM中进行流转的