Spring Security拦截器引起Java CORS跨域失败的问题及解决

Spring Security拦截器引起Java CORS跨域失败的问题及解决

在使用Spring Security进行接口保护的时候,经常会遇到因为跨域问题导致前端无法访问服务器接口的问题。本文将详细介绍Spring Security拦截器引起Java CORS跨域失败的问题及解决。

什么是CORS跨域

CORS(Cross-Origin Resource Sharing)即跨域资源共享,是一种用于跨域访问资源的机制。当一个域的JavaScript代码向另外一个域发送请求时,就会触发跨域。由于JavaScript的同源策略限制,这时的请求会被终止。

Spring Security拦截器引起Java CORS跨域失败的问题

Spring Security使用拦截器来保护接口,如果没有正确配置,就会导致跨域请求失败。具体表现为前端向服务器发送请求时,收到错误提示:

Access to XMLHttpRequest at 'http://example.com/api/someapi' from origin 'http://localhost:8080' 
has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested 
resource.

这是因为服务器拦截器不允许来自不同域的请求。具体来说,是因为在服务器端请求头缺少Access-Control-Allow-Origin字段。如果在前端代码中添加这个字段,就可以通过CORS跨域访问接口。但是由于拦截器的存在,这并不是一个解决办法。

解决Spring Security拦截器引起Java CORS跨域失败的问题

要解决Spring Security拦截器引起Java CORS跨域失败的问题,可以采用以下步骤。

步骤1:添加Filter

在Server端添加一个过滤器,如下所示:

import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CorsFilter implements Filter {

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {

        HttpServletResponse response = (HttpServletResponse) res;

        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
        response.setHeader("Access-Control-Allow-Headers",
                "Authorization, Content-Type, Accept, X-Requested-With, Origin, Access-Control-Request-Method, Access-Control-Request-Headers");
        response.setHeader("Access-Control-Expose-Headers", "Access-Control-Allow-Origin,Access-Control-Allow-Credentials");

        chain.doFilter(req, res);
    }

    @Override
    public void destroy() {}

    @Override
    public void init(FilterConfig config) throws ServletException {}
}

这个过滤器会在请求进入拦截器前执行,并添加CORS信息。

步骤2:配置Spring Security

在SecurityConfig类中添加以下代码:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
            .antMatchers("/api/**").permitAll()
            .anyRequest().authenticated()
            .and().csrf().disable();
    http.addFilterBefore(corsFilter, ChannelProcessingFilter.class);
}

这里的api/**是需要允许跨域访问的接口路径,.antMatchers("/api/**").permitAll()的意思是对这些接口不进行权限验证。

这样就可以解决Spring Security拦截器引起Java CORS跨域失败的问题了。

示例1:允许所有的请求跨域

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CorsFilter implements Filter {

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {

        HttpServletResponse response = (HttpServletResponse) res;

        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
        response.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type, Accept");
        response.setHeader("Access-Control-Expose-Headers", "Access-Control-Allow-Origin,Access-Control-Allow-Credentials");

        chain.doFilter(req, res);
    }

    @Override
    public void destroy() {}

    @Override
    public void init(FilterConfig config) throws ServletException {}
}

以上代码的作用是允许所有的请求跨域,通常不建议使用,因为这会导致服务器存在安全风险。

示例2:只允许指定域名的请求跨域

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CorsFilter implements Filter {

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;

        String origin = request.getHeader("Origin");
        if (origin != null && (origin.contains("example.com") || origin.contains("example.cn"))) {
            response.setHeader("Access-Control-Allow-Origin", origin);
        }

        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
        response.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type, Accept");
        response.setHeader("Access-Control-Expose-Headers", "Access-Control-Allow-Origin,Access-Control-Allow-Credentials");

        chain.doFilter(req, res);
    }

    @Override
    public void destroy() {}

    @Override
    public void init(FilterConfig config) throws ServletException {}
}

以上代码的作用是只允许来自example.comexample.cn的域名请求跨域。如果请求的域名不在白名单中,服务器会拒绝该请求。这样做可以有效地防止跨站点伪造请求(CSRF)。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Spring Security拦截器引起Java CORS跨域失败的问题及解决 - Python技术站

(0)
上一篇 2023年5月20日
下一篇 2023年5月20日

相关文章

  • Java项目开发中实现分页的三种方式总结

    Java项目开发中实现分页的三种方式总结 在Java项目的开发过程中,经常需要对列表数据进行分页显示。本篇文章将总结Java项目开发中实现分页的三种方式,以供参考。 第一种方式:使用分页插件 分页插件是一种在MyBatis框架中常用的解决方案,它可以方便地实现分页功能。下面是使用MyBatis的一个示例: <!– 配置分页插件 –> <…

    Java 2023年6月16日
    00
  • java实现文件保存到本地的方法

    Java 实现文件保存到本地的方法可以通过以下步骤来实现。 第一步:准备保存文件的本地目录 在 Java 代码中,我们需要提前准备好一个本地保存文件的目录,可以使用 File 类来生成目录,示例代码如下: File directory = new File("D:/files"); if(!directory.exists()){ dir…

    Java 2023年5月20日
    00
  • web.xml SpringBoot打包可执行Jar运行SpringMVC加载流程

    web.xml SpringBoot打包可执行Jar运行SpringMVC加载流程 在 SpringBoot 中,我们可以使用可执行 Jar 包来运行我们的应用程序。本文将详细讲解如何使用 web.xml 文件来配置 SpringMVC,并将其打包为可执行 Jar 包。 1. 创建 SpringBoot 项目 首先,我们需要创建一个 SpringBoot 项…

    Java 2023年5月18日
    00
  • Spring4整合Hibernate5详细步骤

    下面是“Spring4整合Hibernate5详细步骤”的攻略,分别针对Spring和Hibernate进行详细讲解。 Spring配置 在pom.xml文件中添加Spring和Hibernate的依赖: <dependency> <groupId>org.springframework</groupId> <art…

    Java 2023年5月19日
    00
  • Java如何设置系统参数和运行参数

    设置系统参数和运行参数可以帮助Java应用程序更好地运行。以下是Java如何设置系统参数和运行参数的完整攻略: 设置系统参数 可以使用System.setProperty()方法设置系统参数。这个方法接受两个String类型的参数,第一个参数是属性名,第二个参数是属性值。例如,下面的代码段将JVM的代理服务器设置为127.0.0.1: System.setP…

    Java 2023年5月23日
    00
  • Java线程休眠的5种方法

    Java线程休眠的5种方法 Java中的线程可以通过休眠来暂停一段时间。线程的休眠有5种方法,本文将详细介绍这5种方法,并给出代码示例。 方法一:使用Thread.sleep() Thread.sleep()是Java中比较常用的线程休眠方法。它可以将当前正在执行的线程休眠指定的时间,单位是毫秒。下面是使用Thread.sleep()方法的示例: publi…

    Java 2023年5月19日
    00
  • Java中List的使用方法简单介绍

    让我根据题目的要求给大家介绍一下Java中List的使用方法。 什么是List List是Java中一个常用的接口,它继承于Collection接口,表示一个有序(即列表)、可重复的元素集合。List中的每个元素都有其唯一的索引值,能够通过索引值来访问和修改元素。 List接口是一个泛型接口,可以定义存储不同类型元素的List集合。常见的List实现类有Ar…

    Java 2023年5月26日
    00
  • 基于StringUtils工具类的常用方法介绍(必看篇)

    基于StringUtils工具类的常用方法介绍 StringUtils是Apache Commons Lang组件库中提供的一个字符串工具类,它提供了很多方便的字符串操作方法,大大简化了Java程序中字符串处理的难度。本篇攻略将逐一介绍StringUtils工具类的常用方法,分类讲解它们的使用方法。 1. 字符串判空 1.1 isBlank方法 isBlan…

    Java 2023年5月27日
    00
合作推广
合作推广
分享本页
返回顶部