복붙노트

[SPRING] 스프링 MVC PUT 요청이 405 메소드를 허용하지 않음을 반환합니다.

SPRING

스프링 MVC PUT 요청이 405 메소드를 허용하지 않음을 반환합니다.

나는 봄 API를 사용하여 나머지 API를 설정하고 대부분의 구성은 스프링 부트 프로젝트를 통해 자동으로 설정됩니다. 프런트 엔드에서 나는 리소스에 대한 서버에 대한 ajax 요청을 만들기 위해 angularjs와 $ http 모듈을 사용하고 있습니다. 리소스 URL은 컨트롤러 클래스에 정의되어 있지만 GET URL 만 일치합니다. 나는 PUT과 POST를 시도했으나 405 메소드는 허용되지 않았고 403은 각각 금지되었습니다.

내 컨트롤러는 다음과 같이 보입니다.

@Controller
@RequestMapping("/api/users")
public class UserController {

    @Inject
    UserService svc;

    @RequestMapping(method = RequestMethod.GET)
    @ResponseBody
    public List<User> home() {
        return svc.findAll();
    }

    @RequestMapping(method = RequestMethod.GET, value = "/{id}")
    @ResponseBody
    public User findById(@PathVariable long id){
        return svc.findById(id);
    }

    @RequestMapping(method = RequestMethod.PUT, value="/{id}")
    @ResponseBody
    public User updateUser(@PathVariable long id, @RequestBody User user){
        Assert.isTrue(user.getId().equals(id), "User Id must match Url Id");
        return svc.updateUser(id, user);
    }

}

url과 일치하지 않는 서버에 대한 요청은 다음과 같습니다

$http({
            url: BASE_API + 'users/' + user.id,
            method: 'PUT',
            data:user
        })

localhost : 8080 / api / users / 1에 대한 PUT 요청이 생성되고 서버는 405 Method Not Allowed 응답 코드로 응답합니다.

서버가 localhost : 8080 / api / users / 1에 HTTP GET 요청을 수신하면 RequestMethod.GET과 동일한 요청 매핑이 올바르게 처리됩니다.

모든 통찰력이 도움이 될 것입니다.

PS가 필요한 경우 포함 된 스프링 부트 종속성은 다음과 같습니다.

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
        <scope>provided</scope>
    </dependency>

감사

해결법

  1. ==============================

    1.로그를 살펴보고 (DEBUG의 보안 기능 사용) 문제를 발견 할 수 있습니다. 대부분 csrf 보호를 비활성화하지 않았으므로 클라이언트가 csrf 토큰을 보내지 않습니다. (스프링 보안이 아닌 표준 스프링 보안. 부트 보안 자동 구성을 사용하는 경우 외부 설정을 사용하여 csrf를 끌 수 있습니다.)

    로그를 살펴보고 (DEBUG의 보안 기능 사용) 문제를 발견 할 수 있습니다. 대부분 csrf 보호를 비활성화하지 않았으므로 클라이언트가 csrf 토큰을 보내지 않습니다. (스프링 보안이 아닌 표준 스프링 보안. 부트 보안 자동 구성을 사용하는 경우 외부 설정을 사용하여 csrf를 끌 수 있습니다.)

  2. ==============================

    2.csrf 보호 때문에 같은 오류가 발생했습니다. csrf 보호가 활성화되면 요청 헤더에 csrf 매개 변수를 보내야합니다.

    csrf 보호 때문에 같은 오류가 발생했습니다. csrf 보호가 활성화되면 요청 헤더에 csrf 매개 변수를 보내야합니다.

    여기 Spring 문서를 확인할 수도 있습니다.

    내 JSP 파일에이 매개 변수를 추가했습니다.

    <input type="hidden" id="csrfToken" value="${_csrf.token}"/>
    <input type="hidden" id="csrfHeader" value="${_csrf.headerName}"/>
    

    그리고 아래처럼 내 아약스 호출을 수정했습니다.

    var token = $('#csrfToken').val();
    var header = $('#csrfHeader').val();
    
    $.ajax({
        type : 'POST',
        url : contextPath + "/qd/translate",
        data: JSON.stringify(json),
        dataType : 'json',
        beforeSend: function(xhr) {
            xhr.setRequestHeader("Accept", "application/json");
            xhr.setRequestHeader("Content-Type", "application/json");
            xhr.setRequestHeader(header, token);
        },
        success : function(result) {
            if (result.status === 'ok') {
                $('#translationModal').modal('hide');
                alert('Error when translating: ' + result.resultMessages.succeess);
            } else {
                alert('Error when translating: ' + result.resultMessages.error);
            }
    
        },
        error : function(jqXHR, textStatus, errorThrown) {
            alert(jqXHR.status + " " + jqXHR.responseText);
        }
    });
    
  3. ==============================

    3.우선 Spring 4에서 나머지 컨트롤러 클래스에 @RestController 주석을 사용할 수 있습니다.이 메소드를 사용하면 메서드에서 @RequestBody 주석을 제거 할 수 있습니다. 더 깨끗하게 해줍니다.

    우선 Spring 4에서 나머지 컨트롤러 클래스에 @RestController 주석을 사용할 수 있습니다.이 메소드를 사용하면 메서드에서 @RequestBody 주석을 제거 할 수 있습니다. 더 깨끗하게 해줍니다.

    두 번째로, 더 많은 각도 코드를 보여 주시겠습니까? 백엔드 요청을하기 위해 공장 서비스 사용을 고려해야한다고 생각합니다. 예를 들어, 서비스를 받으십시오 (이 서비스는 기본적으로 게시, 가져 오기, 삭제를 제공합니다).

    app.factory('User', function ($resource) {
        return $resource("/api/users/:id", {
            update: {
                method: "PUT"
            }
        });
    });
    

    이제 Angular 컨트롤러에서이 서비스 메서드를 호출하는 데 사용하는 새 User 개체를 만듭니다.

    모두 쿼리 (GET) : User.query ();

    쿼리 하나 (GET) : User.get ({id : userId});

    삽입 (POST) : 사용자 $ save ();

    업데이트 (PUT) : 사용자. $ update ();

    삭제 (삭제) : User.delete ({id : userId}

    필자는 Spring Boot를 사용하여 앵귤러 응용 프로그램을 작성하여 잘 작동합니다.

  4. ==============================

    4.동일한 문제가 있었고 컨트롤러에서 "일반"@Controller 주석 대신 @RestController 주석을 사용하여 해결했습니다.

    동일한 문제가 있었고 컨트롤러에서 "일반"@Controller 주석 대신 @RestController 주석을 사용하여 해결했습니다.

  5. ==============================

    5.Spring MVC의 코드가 나에게 잘 어울려서 AngularJS의 구문이 올바른 것으로 의심된다. AngularJS에 익숙하지 않지만 $ http 함수에 관한 온라인 자습서를 발견했습니다.

    Spring MVC의 코드가 나에게 잘 어울려서 AngularJS의 구문이 올바른 것으로 의심된다. AngularJS에 익숙하지 않지만 $ http 함수에 관한 온라인 자습서를 발견했습니다.

    $http.get(url, config)
    $http.post(url, data, config)
    $http.put(url, data, config)
    $http.delete(url, config)
    $http.head(url, config)
    

    이 링크에서 http://tutorials.jenkov.com/angularjs/ajax.html

    희망이 도움이 될 것입니다.

  6. ==============================

    6.문제는 findById 및 updateUser의 끝점이 api / users / {id}와 같고 GET 메서드가있는 메서드가 먼저 오므로 PUT 요청을 보낼 때 먼저 평가되므로 봄까지 거부됩니다.

    문제는 findById 및 updateUser의 끝점이 api / users / {id}와 같고 GET 메서드가있는 메서드가 먼저 오므로 PUT 요청을 보낼 때 먼저 평가되므로 봄까지 거부됩니다.

    사용자 업데이트를위한 끝점을 아래와 같이 api / users / update / {id}로 변경하는 것이 좋습니다.

    @Controller
    @RequestMapping("/api/users")
    public class UserController {
    
        @Inject
        UserService svc;
    
        @RequestMapping(method = RequestMethod.GET)
        @ResponseBody
        public List<User> home() {
            return svc.findAll();
        }
    
        @RequestMapping(method = RequestMethod.GET, value = "/{id}")
        @ResponseBody
        public User findById(@PathVariable long id){
            return svc.findById(id);
        }
    
        @RequestMapping(method = RequestMethod.PUT, value="/update/{id}")
        @ResponseBody
        public User updateUser(@PathVariable long id, @RequestBody User user){
            Assert.isTrue(user.getId().equals(id), "User Id must match Url Id");
            return svc.updateUser(id, user);
        }
    
    }
    
  7. from https://stackoverflow.com/questions/24719823/spring-mvc-put-request-returns-405-method-not-allowed by cc-by-sa and MIT license