csrf漏洞修复

文章介绍了如何通过SpringMVC的CsrfFilterConfig和CsrfFilterInterceptor防止恶意篡改Referer头进行接口访问,确保接口安全。使用CORS配置限制了某些路径对特定来源的访问。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

漏洞说明:通过篡改请求头中的Referer值依旧能够访问到接口。
通过http请求头里面的Referer随意访问接口
在这里插入图片描述

通过下面两个代码类程序来实现你的程序不会被攻击,里面有两个实体,如果你感觉这个程序对你有用,联系我,我私发你,代码就不做过多的解释,原理不难

package com.datalook.manage.filter;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * @description:
 * @author: guoyunlong
 * @create: 2023-11-23 13:08
 **/
@Configuration
public class CsrfFilterConfig implements WebMvcConfigurer{

    @Bean
    public CsrfFilterInterceptor myCsrfInterceptor(){
        return  new CsrfFilterInterceptor();
    }
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //这里可以添加多个拦截器
        registry.addInterceptor(myCsrfInterceptor())
                .addPathPatterns("/**")
                //img和resources为静态资源
                .excludePathPatterns("/img/**")
                .excludePathPatterns("/images/**")
                .excludePathPatterns("/resources/**")
                .excludePathPatterns("/actuator/**")
                .excludePathPatterns("/actuator/prometheus/**")
                .excludePathPatterns("/permission/**");

    }

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/login")
                .allowedOrigins("*")
                .allowCredentials(true)
                .allowedMethods("GET", "POST", "DELETE", "PUT")
                .maxAge(3600);
    }

}
package com.datalook.manage.filter;

import com.datalook.util.common.ComponentProperties;
import com.datalook.util.common.StringUtils;
import com.datalook.util.log.LogUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @description:
 * @author: guoyunlong
 * @create: 2023-11-23 13:08
 **/
@Component
public class CsrfFilterInterceptor implements HandlerInterceptor {


    @Autowired
    private ComponentProperties security;


    public boolean preHandle(HttpServletRequest request, HttpServletResponse httpServletResponse, Object o) throws Exception {
        String referer = request.getHeader("Referer");
        String serverName = request.getServerName();
        //如果 referer 为空放行
        if (!StringUtils.hasText(referer)) {
            return true;
        }
        URL url = null;
        try {
            url = new URL(referer);
        } catch (MalformedURLException e) {
            httpServletResponse.setContentType("application/json; charset=UTF-8");
            httpServletResponse.getWriter().write("系统不支持当前域名的访问!");
            LogUtil.error("域名:{}解析异常", url);
        }
        referer = url.getHost();
        if (StringUtils.hasText(referer)) {
            // 不启用或者已忽略的domain不拦截
            if (!security.getCsrf().isEnable() || isExcludesDomain(referer)) {
                return true;
            }
        }
        // 判断是否存在外链请求本站
        if (StringUtils.hasText(referer) && referer.indexOf(serverName) < 0) {
            LogUtil.error("拦截到非法请求:=> 服务器域名:{} => 非法访问域名:{}", serverName, referer);
            httpServletResponse.setContentType("application/json; charset=UTF-8");
            httpServletResponse.getWriter().write("系统不支持当前域名的访问!");
            return false;
        } else {
            return true;
        }
    }


    /**
     * 判断是否为忽略的域名
     *
     * @param urlPath URL路径
     * @return true-忽略,false-过滤
     */
    private boolean isExcludesDomain(String urlPath) {
        if (security.getCsrf().getExcludesDomain() == null || security.getCsrf().getExcludesDomain().isEmpty()) {
            return false;
        }
        return security.getCsrf().getExcludesDomain().stream().map(pattern -> Pattern.compile("^" + pattern)).map(p -> p.matcher(urlPath))
                .anyMatch(Matcher::find);
    }
}

使用postman来测试修复后的结果,如果别人使用随意一个域名是可以访问你的接口或者页面的
在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

郭优秀的笔记

你的支持就是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值