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

时间:2018-05-23 10:41:59

标签: spring rest maven spring-boot

我是春季休息服务的新手。我使用maven项目在spring boot中开发了一些rest api。

我已成功开发获取发布 Api。我的 GET 方法在邮递员和移动设备中正常运行。 当我试图从邮递员发布post方法时它正常工作但是从手机上它给出了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

请建议我如何解决错误。

enter image description here

5 个答案:

答案 0 :(得分:15)

您必须禁用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;
    }

}

答案 1 :(得分:1)

可能的原因:

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

答案 2 :(得分:1)

在 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();
        }
}

答案 3 :(得分:0)

以接受的答案为基础

许多HTTP客户端库(例如Axios)为POST请求隐式设置了Content-Type: JSON头。就我而言,我忘记了允许该标头仅导致POSTS失败。

@Bean
CorsConfigurationSource corsConfigurationSource() {
    ...
    configuration.addAllowedHeader("Content-Type"); // <- ALLOW THIS HEADER 
    ...
}

答案 4 :(得分:0)

在 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 的工作示例可能是:

HTML

<head>
    <meta name="_csrf" th:content="${_csrf.token}"/>
    <meta name="_csrf_header" th:content="${_csrf.headerName}"/>
</head>

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))
}