欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

基于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;
	}
相关标签: java ajax