csrf漏洞修复

漏洞说明:通过篡改请求头中的Referer值依旧能够访问到接口。
通过http请求头里面的Referer随意访问接口
csrf漏洞修复_第1张图片

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

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来测试修复后的结果,如果别人使用随意一个域名是可以访问你的接口或者页面的
csrf漏洞修复_第2张图片

你可能感兴趣的:(csrf,前端,java)