如何解决Spring Boot Post请求中的403错误

Har*_*ukh 20 rest spring maven spring-boot

我是Spring Boot Rest服务的新手。我已经使用maven项目在Spring Boot中开发了一些Rest API。

我已经成功开发了Get and Post Api。我的GET方法可以在邮递员和手机上正常工作。当我尝试从邮递员那里访问邮局方法时,它的工作正常,但从移动设备中给它403禁止错误

这是我的配置:

spring.datasource.url = jdbc:mysql://localhost/sampledb?useSSL=false
spring.datasource.username = te
spring.datasource.password = test
spring.jpa.properties.hibernate.dialect= org.hibernate.dialect.MySQL5InnoDBDialect
Hibernate ddl auto (create, create-drop, validate, update)
spring.jpa.hibernate.ddl-auto = update
Run Code Online (Sandbox Code Playgroud)

请建议我如何解决错误。

在此处输入图片说明

小智 44

您必须禁用csrf保护,因为它在spring security中是默认启用的:在这里您可以看到允许cors起源的代码。

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

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{

    @Override
    protected void configure(HttpSecurity http) throws Exception{
        http.cors().and().csrf().disable();
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("*"));
        configuration.setAllowedMethods(Arrays.asList("*"));
        configuration.setAllowedHeaders(Arrays.asList("*"));
        configuration.setAllowCredentials(true);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

}
Run Code Online (Sandbox Code Playgroud)

  • 禁用 csrf 使我的 POST 请求成功!终于解脱了。 (12认同)
  • 为什么要禁用 csrf 允许的 post 方法? (3认同)
  • @Ezzat Eissa - 禁用“csrf”当然有效。但这也让我们的 API 容易受到攻击,不是吗?如果是这样,如何确保从服务器端和客户端都配置了 csrf 令牌? (3认同)
  • 这个答案应该带有一些警告。保持 csrf 启用有一些充分的理由。要使用启用的 csrf:https://docs.spring.io/spring-security/site/docs/3.2.x/reference/htmlsingle/html5/#csrf (2认同)

小智 12

在Spring Security中,跨站检查默认是启用的,我们需要通过创建一个单独的类来停止交叉检查来禁用它。

package com.baba.jaxws;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter{

     @Override
    //we have stopped the csrf to make post method work
        protected void configure(HttpSecurity http) throws Exception{
            http.cors().and().csrf().disable();
        }
}
Run Code Online (Sandbox Code Playgroud)


des*_*oss 7

可能的原因:

  1. 从邮递员完成的请求与从移动设备完成的请求不同(uri、方法、标题)
  2. 令牌无效
  3. CORS(阅读有关它的内容,google 上满是文章)将 @CrossOrigin 注释添加到您的控制器。
  4. 移动应用程序在执行 POST 之前正在执行 OPTION 请求,而您阻止了 OPTION 请求。如果同样来自邮递员的 OPTION 请求被阻止,请添加属性spring.mvc.dispatch-options-request=true。此外,如果您使用的是 spring security,您还必须明确允许 OPTION 请求。


Kha*_*een 7

Spring Security 中默认启用 CSRF。启用此功能可确保在更改(对象)状态的 HTTP 请求上出现 403 错误。欲了解更多信息,请访问:https://docs.spring.io/spring-security/site/docs/3.2.x/reference/htmlsingle/html5/#csrf

可以在 Spring Security 中禁用 CSRF。然而,它是默认启用的(约定优于配置)并且有充分的理由。Spring 安全性的链接中也对此进行了解释。

使用 Thymeleaf 的一个有效示例可能是:

超文本标记语言

<head>
    <meta name="_csrf" th:content="${_csrf.token}"/>
    <meta name="_csrf_header" th:content="${_csrf.headerName}"/>
</head>
Run Code Online (Sandbox Code Playgroud)

JS

function postExample() {
    let token = $("meta[name='_csrf']").attr("content");
    let header = $("meta[name='_csrf_header']").attr("content");

    let data = {username: "", password: "", firstname: "", lastname: ""};

    // Object key string interpolation by {[header]:token} works with ES6
    fetch(window.location+"/addnote", {
        method:"POST",
        headers: {
            [header]: token,
            "charset": "UTF-8",
            "Content-Type": "application/json"
        },
        body: JSON.stringify(data)
    }).then(res => console.log(res)).catch(err => console.log(err))
}
Run Code Online (Sandbox Code Playgroud)

根据 @mahmoud-magdy 的要求控制器

@PostMapping("/addnote")
public Long addNote(@RequestBody() String data) {
    Gson gson = new Gson();
    JSONAddNote json = gson.fromJson(data, JSONAddNote.class);
    return <service>.addNote(json.username, json....);
}

class JSONAddNote {
    public String username;
    public String ...etc
}
Run Code Online (Sandbox Code Playgroud)

或者更直接的CONTROLLER

@PostMapping("/addnote")
public Long addNote(@RequestBody Data data) {
    return <service>.addNote(data);
}

class Data {
    public String username;
    public String ...etc
}
Run Code Online (Sandbox Code Playgroud)


小智 5

我能够通过使用来解决这个问题:

<form th:action="@{url}" method="post">
Run Code Online (Sandbox Code Playgroud)

代替:

<form action="url" method="post">
Run Code Online (Sandbox Code Playgroud)

th:action 标签似乎进行了 url 重写以启用 csrf 验证。