最新要闻

广告

手机

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

家电

环球热点!springboot通过Referer防止跨站点请求伪造

来源:博客园

原文链接:https://blog.csdn.net/qq_44154912/article/details/127439461

防止跨站点请求伪造验证“Referer”头的值,并对每个提交的表单使用 one-time-nonce

在application.yml 中添加配置


【资料图】

# 防止 跨站点请求伪造, RefererFilter.javasecurity: csrf: # 开启过滤 enable: true # 白名单接口 每个接口用 , 分隔 excludes: 1234567我使用的是若依框架, 在common的filter包下添加 RefererFilter 类

package com.vxdata.common.filter;

import com.vxdata.common.utils.StringUtils;import lombok.Data;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Value;import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;import org.springframework.context.annotation.Configuration;import org.springframework.http.HttpStatus;

import javax.servlet.*;import javax.servlet.annotation.WebFilter;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.util.Arrays;import java.util.List;import java.util.regex.Matcher;import java.util.regex.Pattern;

//@Configuration@ConditionalOnProperty(prefix = "security.csrf", name = "enable", havingValue = "true")@Configuration@WebFilter(filterName = "refererFilter", urlPatterns = "/*")@Datapublic class RefererFilter implements Filter { public static final Logger logger = LoggerFactory.getLogger(RefererFilter.class);

/** * 过滤器配置对象 */ FilterConfig filterConfig = null;

/** * 是否启用 */ @Value("${security.csrf.enable:false}") private boolean enable = true;

/** * 忽略的URL */ @Value("${security.csrf.excludes:}") private String excludes;

@Override public void init(FilterConfig filterConfig) throws ServletException { this.filterConfig = filterConfig; }

@Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) servletRequest; // 不启用或者已忽略的URL不拦截 if (!enable || isExcludeUrl(request.getServletPath())) { filterChain.doFilter(servletRequest, servletResponse); return; }

String referer = request.getHeader("Referer"); String serverName = request.getServerName();

// 判断是否存在外链请求本站 if (referer == null || !referer.contains(serverName)) { logger.error("Referer过滤器 服务器:{} 当前域名:{}", serverName, referer); HttpServletResponse resp = (HttpServletResponse) servletResponse; resp.setStatus(HttpStatus.NOT_FOUND.value()); return; } else { filterChain.doFilter(servletRequest, servletResponse); } }

@Override public void destroy() { this.filterConfig = null; }

/** * 判断是否为忽略的URL *

*

* URL路径 * * @return true-忽略,false-过滤 */ private boolean isExcludeUrl(String url) { if (StringUtils.isBlank(excludes)) { return false; } List urls = Arrays.asList(excludes.trim().split(","));// return urls.stream().filter(StringUtils::isNotBlank).map(pattern -> Pattern.compile("^" + pattern.trim()))// .map(p -> p.matcher(url)).anyMatch(Matcher::find); for (String uri : urls) { // 正则验证 Pattern p = Pattern.compile("^" + uri); if (p.matcher(url).find()) { return true; } } return false; }}123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106获取 referer 为null, 无法获取 referer 导致过滤失败正常情况前端请求接口的时候, 请求表头中会有一个 referer 属性, 会携带当前前端页面路由信息我们根据这个路由信息判断是不是我们的前端来访问接口的

如果前端访问时候没有这个referer 信息

浏览器打开检查, 查看页面元素, 看head标签中是否配置了 no-referrer我这里删掉 < meta name=“referrer” content=“no-referrer”> 后就有 referer 了

关键词: 使用的是 正常情况