source

Spring Boot Post Request에서의 403 오류 해결 방법

manycodes 2023. 3. 17. 21:45
반응형

Spring Boot Post Request에서의 403 오류 해결 방법

저는 봄 부츠레스트 서비스 초보입니다.maven 프로젝트를 이용하여 봄 부츠에서 rest api를 개발하였습니다.

Get API와 Post API를 성공적으로 개발했습니다.우편배달원 및 모바일에서 정상적으로 동작하는 My GET Method.우체부로부터 우편물을 치려고 하면 정상적으로 작동하지만 모바일에서는 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

오류 해결 방법을 알려주세요.

여기에 이미지 설명 입력

csrf 보호는 스프링 보안에서는 기본적으로 활성화되어 있기 때문에 비활성화해야 합니다.여기서 cors origin을 허용하는 코드를 볼 수 있습니다.

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

}

Spring Security Cross-Site Check는 기본적으로 활성화되어 있습니다.크로스 체크를 정지하기 위해 별도의 클래스를 생성하여 비활성화해야 합니다.

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

생각할 수 있는 원인:

  1. 우체부로부터의 요구는 모바일로부터의 요구와 다르다(uri, 메서드, 헤더).
  2. 유효하지 않은 토큰
  3. CORS(Google은 기사들로 가득합니다)는 컨트롤러에 @CrossOrigin 주석을 추가합니다.
  4. 모바일 앱이 POST를 수행하기 전에 OPTION 요청을 실행 중이고 OPTION 요청을 차단합니다.OPTION 요구도 우체국으로부터 차단되어 있는 경우는, spring.mvc.spring-mvc-syslog-request=true 속성을 추가합니다.또한 스프링 보안을 사용하는 경우 OPTION 요청도 명시적으로 허용해야 합니다.

다음을 사용하여 이 문제를 해결할 수 있었습니다.

<form th:action="@{url}" method="post">

대신:

<form action="url" method="post">

th:action 태그는 csrf 검증을 활성화하기 위해 URL을 다시 쓰는 것으로 보입니다.

CSRF는 Spring Security 디폴트로 이니블로 되어 있습니다.이것을 유효하게 하면, (오브젝트) 상태를 변경하는 HTTP 요구의 403 에러가 보증됩니다.상세한 것에 대하여는, https://docs.spring.io/spring-security/site/docs/3.2.x/reference/htmlsingle/html5/ #http://https://docs.spring.io/spring-security/site/docs/3.2.x/reference/htmlsingle/html5/ 를 참조해 주세요.

스프링 보안에서는 CSRF를 디세블로 할 수 있습니다.다만, 디폴트에서는(설정상의 컨벤션)이 유효하게 되어 있습니다.이는 Spring's Security 링크에도 설명되어 있습니다.

Tymeleaf를 사용하는 작업 예는 다음과 같습니다.

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

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

또는 보다 직접적인 컨트롤러:

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

class Data {
    public String username;
    public String ...etc
}

인정된 답변을 바탕으로 하다

많은 HTTP 클라이언트 라이브러리(Axios 등)는 암묵적으로Content-Type: JSONPOST 청용 post 。저 같은 경우에는 헤더를 방치하는 것을 잊어버려서 POST만 실패합니다.

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

이 답변은 Open/WAS Liberty 서버에 배포하는 경우 이 질문과 관련이 있습니다.

이 경우 Spring 부팅과 함께 제공되는 임베디드 Tomcat에 배포하면 코드가 정상적으로 작동하더라도 403 오류가 발생할 수 있습니다.

자유는 당신의 것을 읽지 않는다(또는 고려하지 않는다)

server.servlet.context-path=/myapi/v1

어떤 이유로 application.properties 또는 application.yml 파일에 설정한 것입니다.아니면 그냥 덮어쓰거나, 확실하지 않아요.그래서 위의 것은context-pathSpring Boot(스프링 부트)의 Tomcat(톰캣).

단, OpenLiberty/WASLiberty에 전개하면 엔드포인트가 동작을 정지하고 403 및/또는 404 오류가 발생할 수 있습니다.

예에서는 api를 ./authWeb Security Configuration:

//Customize the /login url to overwrite the Spring default provided /login url.
private AuthenticationFilter authenticationFilter() throws Exception {
    final AuthenticationFilter filter = new AuthenticationFilter(authenticationManager());
    // This works fine on embedded tomcat, but not in Liberty where it returns 403.  
    // To fix, in server.xml <appllication> block, add 
    // <application context-root="/myapi/v1" ... and then both
    // auth and other endpoints will work fine in Liberty.
    filter.setFilterProcessesUrl("/auth"); 
    // This is temporary "fix" that creates rather more issues, as it 
    // works fine with Tomcat but fails in Liberty and all other
    // endpoints still return 404
    //filter.setFilterProcessesUrl("/v1/auth"); 
    return filter;
}

의 「 」에 근거하고 .context-path ", "Domcat ", "Domcat "이 /myapi/v1/auth리버티에서 일하는 동안, 결국엔 그냥/myapi/auth 일은 만 가져와서 는 무시됩니다.Liberty가 하는 일은 api의 이름을 가져와서 엔드포인트를 추가하는 것뿐입니다.따라서 버전 관리는 무시됩니다.

, 그결은AntPathRequestMatcher ★★★matches()는 non-mon-mon-mon-man-man-man-man-man-man-man-man-man-man-man-man-/auth 에러가납니다.403 에러가 .그리고 다른 엔드포인트에서는 404 에러가 발생합니다.

솔루션

application.properties에서 그대로 둡니다.

server.servlet.context-path=/myapi/v1

임베디드 Tomcat에 의해 선택되며 앱은 예상대로 계속 작동합니다.

Open/WAS Liberty의 server.xml 설정에서 다음과 같은 섹션에 일치하는 context-root를 추가합니다.

<application context-root="/myapi/v1" id="myapi" location="location\of\your\myapi-0.0.1.war" name="myapi" type="war">

Open/WASLiberty에 의해 선택되며 Liberty 컨테이너에서도 앱이 정상적으로 작동합니다.

언급URL : https://stackoverflow.com/questions/50486314/how-to-solve-403-error-in-spring-boot-post-request

반응형