You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring+JS前后端交互遇415/403错误,求解决方案

问题:Spring后端+JS前端应用的415与403错误处理

问题描述

开发了一个Spring后端+JS前端的应用,遇到两个核心问题:

  1. 前端通过jQuery发送POST请求提交用户数据,Postman中请求正常,但Spring后端返回HttpMediaTypeNotSupportedException,提示不支持Content-Type 'text/plain;charset=UTF-8',前端报415错误;
  2. 添加Spring Security配置后出现403错误,推测是拦截导致,不清楚新版本(WebSecurityConfigurerAdapter已废弃)中如何正确配置或临时禁用Spring Security。

相关代码如下:

前端JS请求代码

function addUserToDB() {
    origin='*';
    let user = {
        "telephone": "+375296534488",
        "name": "Potemin",
        "password": ["p", "a", "s"],
        "passwordRetry": ["p", "a", "s"],
        "address": {
            "city": "New York",
            "street": "State",
            "houseNumber": 22
        }
    };
    $.post('http://localhost:8080/registration', user, data => {console.log(data)})
}

前端HTML代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Sign Up</title>
    <script src="js/registration.js"></script>
    <script
            src="https://code.jquery.com/jquery-3.7.0.js"
            integrity="sha256-JlqSTELeR4TLqP0OG9dxM7yDPqX1ox/HfgiSLBj8+kM="
            crossorigin="anonymous"></script>
</head>
<body>
    <button onclick="addUserToDB()" id="b">button</button>
</body>
</html>

Spring Controller代码

package com.project.sushipizzabar.users.controllers;

import com.project.sushipizzabar.users.UserService;
import com.project.sushipizzabar.users.dto.userDto.UserCreateRequest;
import com.project.sushipizzabar.users.dto.userDto.UserDto;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Arrays;

@RestController
@RequestMapping("/registration")
@RequiredArgsConstructor
public class RegistrationController {

    private final UserService service;

    @PostMapping
    public ResponseEntity<UserDto> addUser(@RequestBody UserCreateRequest userCreateRequest) {
        if (!Arrays.equals(userCreateRequest.getPassword(), userCreateRequest.getPasswordRetry())) {
            throw new IllegalArgumentException();
        }
        return ResponseEntity.ok(service.findById(service.create(userCreateRequest)));
    }
}

Spring Security配置代码

package com.project.sushipizzabar.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig implements WebMvcConfigurer {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.csrf(Customizer.withDefaults())
                .cors(Customizer.withDefaults())
                .anonymous(Customizer.withDefaults())
                .authorizeHttpRequests((authz) -> authz
                        .requestMatchers("ttp://localhost:63342/").permitAll()
                );
        return http.build();
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(List.of("http://localhost:63342/"));
        configuration.setAllowedMethods(List.of("*"));
        configuration.setAllowedHeaders(List.of("*"));
        configuration.setAllowCredentials(true);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/registration")
                .allowedOrigins("http://localhost:63342/")
                .allowedMethods("GET", "POST")
                .allowedHeaders("*")
                .allowCredentials(true);
    }
}

解决方案

一、解决415错误(Content-Type不支持)

原因:jQuery的$.post默认会将数据以application/x-www-form-urlencoded格式发送,但后端用@RequestBody接收的是JSON格式数据,导致无法解析。

修改前端代码:改用$.ajax明确设置请求头为application/json,并将对象转为JSON字符串:

function addUserToDB() {
    let user = {
        "telephone": "+375296534488",
        "name": "Potemin",
        "password": ["p", "a", "s"],
        "passwordRetry": ["p", "a", "s"],
        "address": {
            "city": "New York",
            "street": "State",
            "houseNumber": 22
        }
    };

    $.ajax({
        url: 'http://localhost:8080/registration',
        type: 'POST',
        contentType: 'application/json', // 指定请求内容类型为JSON
        data: JSON.stringify(user), // 将JS对象转为JSON字符串
        success: data => console.log(data),
        error: err => console.error(err)
    });
}

二、解决403错误(Spring Security拦截)

配置问题分析:

  1. requestMatchers中的URL写错(少了h),且不应匹配完整URL,需直接放行目标接口路径;
  2. 同时配置WebMvc和Spring Security的CORS,易导致冲突;
  3. 默认CSRF保护会拦截跨域POST请求,开发阶段可临时禁用。

修改Spring Security配置:

package com.project.sushipizzabar.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.util.List;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                .csrf(csrf -> csrf.disable()) // 开发阶段临时禁用CSRF,生产环境需配置令牌
                .cors(Customizer.withDefaults())
                .authorizeHttpRequests(authz -> authz
                        .requestMatchers("/registration").permitAll() // 放行注册接口
                        .anyRequest().authenticated() // 其他接口需认证
                );
        return http.build();
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(List.of("http://localhost:63342")); // 移除末尾斜杠,避免匹配问题
        configuration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE"));
        configuration.setAllowedHeaders(List.of("*"));
        configuration.setAllowCredentials(true);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
}

关键改动:

  • 移除WebMvcConfigurer的CORS配置,统一使用Spring Security的CORS设置;
  • 修正requestMatchers路径,直接放行/registration;
  • 禁用CSRF(开发环境),解决跨域POST拦截问题;
  • 调整allowedOrigins去掉末尾斜杠,避免匹配异常。

内容的提问来源于stack exchange,提问作者Gvinder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 16:44:53