FreeCMS商业版

功能强大、开源、代码通俗易懂、注释详细、面向二次开发友好!

承接网站建设、软件开发、微信开发项目,价格从优,欢迎咨询合作!

FreeCMS商业版V2.8已发布!购买请联系客服QQ 124812878 查看更新日志



在线演示 立即购买 下载免费版 下载商业版用户手册
客服QQ: 124812878 联系电话: 18339991503 Email: freeteam@foxmail.com

基于AOP的ajax的referrer判断 - - ITeye博客

加入收藏夹】     【打印】     【关闭】 来源: 日期:2018-03-20 22:00:04 点击量: 收藏

网页中ajax请求的referrer的值是当前域名。
所以对于一些简单的安全验证可以通过这样的方式来做。
下面是我的实现。

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在后
 * @author zhongjun.huang
 *
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface AjaxReferrerAuthentication {

	String hostString() default "hstong.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;
	}



上一条

下一条

相关新闻
自定义表单
本例固定链接: 分享到:
更多