基于AOP的ajax的referrer判断

网页中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 "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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值