欢迎光临
我们一直在努力

SpringBoot中如何利用JSONP解决前端跨域问题?小结来啦!

SpringBoot JSONP解决前端跨域问题小结

SpringBoot中如何利用JSONP解决前端跨域问题?小结来啦!

一、背景与概念

跨域问题概述

在Web开发中,跨域问题是指浏览器阻止来自不同源的请求,同源策略是浏览器的一种安全机制,它要求协议、域名和端口必须一致,否则会阻止请求,这种限制是为了保护用户免受CSRF(跨站请求伪造)等攻击。

JSONP原理

JSONP(JSON with Padding)是一种通过动态创建<script>标签来实现跨域数据访问的方法,其基本原理是利用<script>标签不受同源策略限制的特性,将回调函数名作为参数传递给服务器,服务器返回一段JavaScript代码,这段代码调用指定的回调函数并传递数据。

Spring Boot简介

Spring Boot是一个基于Spring框架的开源项目,旨在简化新Spring应用程序的初始搭建和开发过程,它提供了默认配置和自动化设置,使开发者能够快速构建生产级的Spring应用。

二、服务端配置

CORS配置

CORS(CrossOrigin Resource Sharing)是一种允许服务器声明哪些来源有权限访问资源的机制,Spring Boot通过配置CORS来允许跨域请求。

1.1 添加依赖

需要在项目的pom.xml文件中添加CORS相关的依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>springbootstarterweb</artifactId>
</dependency>

1.2 配置类实现

创建一个配置类,实现WebMvcConfigurer接口,并在其中配置CORS:

SpringBoot中如何利用JSONP解决前端跨域问题?小结来啦!

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.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*") // 允许所有来源
                .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") // 允许的HTTP方法
                .allowedHeaders("*") // 允许的头部信息
                .allowCredentials(true) // 是否允许发送Cookie信息
                .maxAge(3600); // 预检请求的缓存时间
    }
}

JSONP配置

为了支持JSONP,需要自定义一个过滤器或使用现有的解决方案,下面是一个自定义过滤器的示例:

2.1 创建JSONP过滤器

创建一个过滤器类,用于处理JSONP请求:

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class JsonpFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {}
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        String callback = httpRequest.getParameter("callback");
        if (callback != null) {
            // 设置内容类型为JavaScript
            httpResponse.setContentType("application/javascript");
            // 处理请求并生成响应
            chain.doFilter(request, response);
            // 包装JSON数据到回调函数中
            httpResponse.getWriter().write(callback + "(" + httpResponse.getContentWriter().toString() + ");");
        } else {
            chain.doFilter(request, response);
        }
    }
    @Override
    public void destroy() {}
}

2.2 注册过滤器

在配置类中注册该过滤器:

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FilterConfig {
    @Bean
    public FilterRegistrationBean<JsonpFilter> jsonpFilter() {
        FilterRegistrationBean<JsonpFilter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(new JsonpFilter());
        registrationBean.addUrlPatterns("/*");
        return registrationBean;
    }
}

三、客户端实现

AJAX请求示例

在前端页面中,可以使用jQuery或其他AJAX库发送JSONP请求,以下是使用jQuery发送JSONP请求的示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF8">
    <title>JSONP Example</title>
    <script src="https://code.jquery.com/jquery3.6.0.min.js"></script>
    <script type="text/javascript">
        $(document).ready(function() {
            $.ajax({
                url: "http://localhost:8080/jsonp/testJsonp",
                dataType: "jsonp", // 指定返回的数据类型为jsonp
                jsonpCallback: "localHandler", // 指定回调函数名
                success: function(data) {
                    console.log("Success:", data);
                },
                error: function() {
                    console.error("Error in JSONP request");
                }
            });
        });
        function localHandler(data) {
            console.log("Callback called with data:", data);
        }
    </script>
</head>
<body>
    <h1>JSONP Example</h1>
</body>
</html>

JSONP请求处理流程

1、客户端发起请求:客户端通过<script>标签发起跨域请求,并将回调函数名作为参数传递给服务器。

2、服务器处理请求:服务器接收到请求后,根据回调函数名生成相应的JavaScript代码,并将数据包裹在该代码中返回给客户端。

3、客户端执行回调:客户端接收到服务器返回的JavaScript代码后,执行其中的回调函数,从而获取到所需的数据。

SpringBoot中如何利用JSONP解决前端跨域问题?小结来啦!

4、数据处理:客户端在回调函数中处理从服务器获取的数据。

四、相关问题与解答

JSONP与CORS的区别是什么?

解答:JSONP和CORS都是解决跨域问题的常见方法,但它们有不同的工作原理和适用场景。

JSONP:主要通过动态创建<script>标签来实现跨域请求,适用于GET请求,由于其依赖于<script>标签的特性,存在一定的安全隐患(如被恶意网站利用)。

CORS:是一种更为现代和安全的解决方案,通过设置HTTP响应头来允许或限制特定来源的跨域请求,支持多种HTTP方法(GET、POST、PUT、DELETE等),并且可以通过预检请求来确保安全性。

2. Spring Boot如何同时支持JSON和JSONP?

解答:在Spring Boot中,可以通过配置不同的URL路径或请求参数来区分JSON和JSONP请求,可以定义两个不同的控制器方法,一个处理JSON请求,另一个处理JSONP请求:

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.beans.factory.annotation.Autowired;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/api")
public class ApiController {
    @GetMapping(value = "/json", produces = MediaType.APPLICATION_JSON_VALUE)
    public Map<String, Object> getJson() {
        Map<String, Object> response = new HashMap<>();
        response.put("message", "This is a JSON response");
        return response;
    }
    @RequestMapping(value = "/jsonp", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<String> getJsonp(@RequestParam("callback") String callback) {
        ObjectMapper mapper = new ObjectMapper();
        ObjectNode response = mapper.createObjectNode();
        response.put("message", "This is a JSONP response");
        String jsonResponse = mapper.writeValueAsString(response);
        return ResponseEntity.ok(callback + "(" + jsonResponse + ");");
    }
}

上述代码中,/api/json路径返回普通的JSON响应,而/api/jsonp路径则返回JSONP响应,客户端可以根据需要选择不同的路径进行请求。

小伙伴们,上文介绍了“springboot jsonp解决前端跨域问题小结”的内容,你了解清楚吗?希望对你有所帮助,任何问题可以给我留言,让我们下期再见吧。

赞(0)
版权声明:本文采用知识共享 署名4.0国际许可协议 [BY-NC-SA] 进行授权
文章名称:《SpringBoot中如何利用JSONP解决前端跨域问题?小结来啦!》
文章链接:https://yuyunkj.com/article/9578.html
本站资源仅供个人学习交流,请于下载后24小时内删除,不允许用于商业用途,否则法律问题自行承担。

评论 抢沙发