質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Spring Security

Spring Securityは、Springのサブプロジェクトの一つでWebアプリケーションに必要な機能を追加します。正規ユーザーであるかを確認するための「認証機能」と、ユーザーのアクセスを制御する「認可機能」を簡単に追加することが可能です。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Spring

Spring Framework は、Javaプラットフォーム向けのオープンソースアプリケーションフレームワークです。 Java Platform上に、 Web ベースのアプリケーションを設計するための拡張機能が数多く用意されています。

Spring Boot

Spring Bootは、Javaのフレームワークの一つ。Springプロジェクトが提供する様々なフレームワークを統合した、アプリケーションを高速で開発するために設計されたフレームワークです。

Q&A

解決済

1回答

7417閲覧

Spring securityでログイン認証の機能を使うと@PutMappingのアノテーションが反応しなくなる

spring_boot

総合スコア12

Spring Security

Spring Securityは、Springのサブプロジェクトの一つでWebアプリケーションに必要な機能を追加します。正規ユーザーであるかを確認するための「認証機能」と、ユーザーのアクセスを制御する「認可機能」を簡単に追加することが可能です。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Spring

Spring Framework は、Javaプラットフォーム向けのオープンソースアプリケーションフレームワークです。 Java Platform上に、 Web ベースのアプリケーションを設計するための拡張機能が数多く用意されています。

Spring Boot

Spring Bootは、Javaのフレームワークの一つ。Springプロジェクトが提供する様々なフレームワークを統合した、アプリケーションを高速で開発するために設計されたフレームワークです。

1グッド

1クリップ

投稿2018/09/24 08:24

編集2018/09/24 08:26

SpringでCRUD機能を作り、Spring securityのデフォルト機能を使ってログイン認証機能を取り付けていました。すると、それまでは@PutMappingにきっちりと分岐していたのに急にエラーを発生するようになりました。

エラー内容:

There was an unexpected error (type=Method Not Allowed, status=405).
Request method 'POST' not supported

@PutMappingをつけたメソッドを通っていないです。アノテーションを@PostMappingに変えると反応します。
hiddenタグで

html

1<input type="hidden" name="_method" value="PUT">

を持たせておけば@PutMappingへ分岐されると書籍には書かれていますが違うのでしょうか。
それともSpringSecurityをフィルターに通すことで条件が変わるのでしょうか。
ドキュメントを読み漁りましたがそもそも@PutMappingの使用法すら書かれておりませんでした。

以下、該当するファイルです。
DemoSecurityConfig.java

java

1package com.example.demo.config; 2 3import org.springframework.context.annotation.Configuration; 4import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 5import org.springframework.security.config.annotation.web.builders.HttpSecurity; 6import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 7import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 8 9@Configuration 10@EnableWebSecurity 11public class DemoSecurityConfig extends WebSecurityConfigurerAdapter { 12 13 @Override 14 protected void configure(AuthenticationManagerBuilder auth) throws Exception { 15 auth.inMemoryAuthentication().withUser("john").password("{noop}test123").roles("EMPLOYEE"); 16 auth.inMemoryAuthentication().withUser("mary").password("{noop}test123").roles("MANAGER"); 17 auth.inMemoryAuthentication().withUser("susan").password("{noop}test123").roles("ADMIN"); 18 } 19 20 @Override 21 protected void configure(HttpSecurity http) throws Exception { 22 23 http.authorizeRequests() 24 .anyRequest().authenticated() 25 .and() 26 .formLogin() 27 .loginPage("/showMyLoginPage") 28 .loginProcessingUrl("/authenticateTheUser") 29 .permitAll() 30 .and() 31 .logout().permitAll(); 32 33 } 34 35} 36

ログインは成功します。POSTで新規インサートも行えます。

TestController.java

java

1package com.example.demo.controllers; 2 3import java.util.List; 4import java.util.Optional; 5 6import org.springframework.beans.factory.annotation.Autowired; 7import org.springframework.http.HttpStatus; 8import org.springframework.stereotype.Controller; 9import org.springframework.transaction.annotation.Transactional; 10import org.springframework.validation.BindingResult; 11import org.springframework.validation.annotation.Validated; 12import org.springframework.web.bind.annotation.DeleteMapping; 13import org.springframework.web.bind.annotation.GetMapping; 14import org.springframework.web.bind.annotation.ModelAttribute; 15import org.springframework.web.bind.annotation.PathVariable; 16import org.springframework.web.bind.annotation.PostMapping; 17import org.springframework.web.bind.annotation.PutMapping; 18import org.springframework.web.bind.annotation.RequestMapping; 19import org.springframework.web.bind.annotation.ResponseStatus; 20import org.springframework.web.servlet.ModelAndView; 21 22import com.example.demo.Instructor; 23import com.example.demo.InstructorDetail; 24import com.example.demo.InstructorForm; 25import com.example.demo.service.InstructorService; 26 27@Controller 28@RequestMapping("/test") 29public class TestController { 30 31 @Autowired 32 InstructorService service; 33 34 //INDEX 35 @GetMapping 36 public ModelAndView test( 37 //@ModelAttributeでInstructorFormは自動的にインスタンス化される  38 //htmlに反映させるにはmav.addObjectが必須 39 @ModelAttribute("InstructorForm") InstructorForm instructorForm, 40 ModelAndView mav) { 41 42 instructorForm.setNewInstructor(true); 43 mav.addObject("instructorForm", instructorForm); 44 List<Instructor> list = service.findAll(); 45 mav.addObject("list", list); 46 mav.addObject("title", "メンバー一覧"); 47 48 mav.setViewName("test"); 49 return mav; 50 } 51 52 //Before UPDATE 53 @GetMapping(value = "/{id}")//編集ページ 54 public ModelAndView showUpdate( 55 @ModelAttribute("InstructorForm") InstructorForm instructorForm, 56 @PathVariable Integer id, 57 ModelAndView mav) { 58 Optional<InstructorForm> form = service.getInstructorForm(id); 59 60 if(!form.isPresent()) { 61 mav.setViewName("redirect:/test"); 62 return mav; 63 //return new ModelAndView("redirect:/test") 64 } 65 66 mav.addObject("instructorId", id); 67 mav.addObject("instructorForm", form.get()); 68 List<Instructor> list = service.findAll(); 69 mav.addObject("list", list); 70 mav.addObject("title", "更新フォーム"); 71 72 mav.setViewName("test"); 73 return mav; 74 } 75 76 77 //INSERT 78 @PostMapping 79 @Transactional(readOnly = false) 80 public ModelAndView insert2( 81 @Validated InstructorForm instructorForm,//ヴァリデーションはフォームクラスに対して行う 82 BindingResult result, 83 ModelAndView mav) { 84 Instructor instructor = makeInstructor(instructorForm); 85 //redirect、失敗したらそのままHTML表示 86 if(!result.hasErrors()) { 87 service.save(instructor); 88 mav.setViewName("redirect:/test"); 89 }else { 90 instructorForm.setNewInstructor(true); 91 mav.addObject("instructorForm", instructorForm); 92 List<Instructor> list = service.findAll(); 93 mav.addObject("list", list); 94 mav.addObject("title", "メンバー一覧2"); 95 mav.setViewName("test"); 96 } 97 return mav; 98 } 99 100 //UPDATE 101 @PutMapping("/{id}") 102 @Transactional(readOnly = false) 103 public ModelAndView update( 104 @PathVariable Integer id, 105 @ModelAttribute("InstructorForm") InstructorForm instructorForm, 106 ModelAndView mav) { 107 Instructor instructor = makeInstructor(id, instructorForm); 108 System.out.println(instructor); 109 service.save(instructor); 110 mav.setViewName("redirect:/test" + "/" + id); 111 return mav; 112 } 113 114 //DELETE 115 @DeleteMapping("/{id}") 116 @ResponseStatus(HttpStatus.NO_CONTENT) 117 @Transactional(readOnly = false)//削除の場合必須 118 public ModelAndView delete( 119 @PathVariable Integer id, 120 ModelAndView mav) { 121 System.out.println("けすよ"); 122 service.deleteById(id); 123 mav.setViewName("redirect:/test"); 124 return mav; 125 } 126 127 128 private Instructor makeInstructor(InstructorForm iForm) { 129 InstructorDetail iD = new InstructorDetail(iForm.getYoutubeChannel(), iForm.getHobby()); 130 Instructor i = new Instructor(iForm.getFirstName(), iForm.getLastName(), iForm.getEmail()); 131 i.setInstructorDetail(iD); 132 return i; 133 } 134 135 private Instructor makeInstructor(int id,InstructorForm iForm) { 136 InstructorDetail iD = new InstructorDetail(iForm.getYoutubeChannel(), iForm.getHobby()); 137 Instructor i = new Instructor(id, iForm.getFirstName(), iForm.getLastName(), iForm.getEmail()); 138 i.setInstructorDetail(iD); 139 return i; 140 } 141 142 143}

PutMappingとDeleteMappingが反応しません。
There was an unexpected error (type=Method Not Allowed, status=405).
Request method 'POST' not supported
上記エラーを返します。これはSpring Securityを取り付ける前は動作してました。

Test.html

html

1<!DOCTYPE html> 2<html xmlns:th="http://www.thymeleaf.org"> 3<head> 4<meta charset="UTF-8"> 5<title>Insert title here</title> 6</head> 7<body> 8<h1 th:text="${title}">ようこそ</h1> 9<ul> 10 <li th:each="error : ${#fields.detailedErrors()}" 11 th:text="${error.message}" /> 12</ul> 13<form method="post" action="#" th:action="@{/test}" th:if="${instructorForm.isNewInstructor}" th:object="${instructorForm}"> 14 <label>FirstName</label> 15 <input type="text" name="firstName" th:value="*{firstName}" /> 16 <label>LastName</label> 17 <input type="text" name="lastName" th:value="*{lastName}" /> 18 <label>Email</label> 19 <div th:if="${#fields.hasErrors('email')}" 20 th:errors="*{email}"></div> 21 <div th:if="${#fields.hasErrors('validEmail')}" 22 th:errors="*{validEmail}"></div> 23 <input type="text" name="email" th:value="*{email}" /> 24 <div th:if="${#fields.hasErrors('youtubeChannel')}" 25 th:errors="*{youtubeChannel}"></div> 26 <label>YoutubeChannel</label> 27 <input type="text" name="youtubeChannel" th:value="*{youtubeChannel}" /> 28 <label>Hobby</label> 29 <input type="text" name="hobby" th:value="*{hobby}" /> 30 <input type="submit" value="送信"> 31</form> 32<form method="POST" th:action="@{/test/{id}(id=${instructorId})}" th:unless="${instructorForm.isNewInstructor}" th:object="${instructorForm}"> 33 <label>FirstName</label> 34 <input type="text" name="firstName" th:value="*{firstName}" /> 35 <label>LastName</label> 36 <input type="text" name="lastName" th:value="*{lastName}" /> 37 <label>Email</label> 38 <input type="text" name="email" th:value="*{email}" /> 39 <label>YoutubeChannel</label> 40 <input type="text" name="youtubeChannel" th:value="*{youtubeChannel}" /> 41 <label>Hobby</label> 42 <input type="text" name="hobby" th:value="*{hobby}" /> 43 <input type="hidden" name="_method" value="PUT"> 44 <input type="submit" value="変更"> 45</form> 46<table> 47<tr th:each="obj : ${list}"> 48 <td th:text=${obj.id}></td> 49 <td th:text=${obj.firstName}></td> 50 <td th:text=${obj.email}></td> 51 <td th:text=${obj.instructorDetail.hobby}></td> 52 <td><a type="button" th:href="@{/test/{id}(id=${obj.id})}">編集</a></td> 53 <td><form method="POST" th:action="@{/test/{id}(id=${obj.id})}"> 54 <input type="hidden" name="_method" value="DELETE"> 55 <input type="submit" value="削除"> 56 </form> 57</tr> 58</table> 59<form action="#" th:action="@{/logout}" method="POST"> 60 <input type="submit" value="Logout" /> 61</form> 62</body> 63</html>

このエラーから抜け出せずに困っています。
どなたかわかる方はいらっしゃいますでしょうか。
また、該当のドキュメント(@PutMapping)時にhtmlから送信するhiddenの内容などが記載されたドキュメントの場所をご存じであればそれも知りたいです。どこを探しても見つかりませんでした。
よろしくお願いいたします

euledge👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

CORSにより、PUT,DELETEのメソッドが許可されていないためではないでしょうか?

【参考】

直接は関係ないですが @PostMapping,@PutMapping,@DeleteMappingをつけるメソッドは、呼び出し側をAJAX呼び出しにして、APIにするほうがviewの呼び出しやそれに伴うModelへの値セットが少なくなって良い気がします。(もちろん仕様によるものなので、APIが正解ということはないですが)

//INSERT @PostMapping @ResponseBody @Transactional(readOnly = false) public List<Instructor> insert2(@Validated InstructorForm instructorForm, BindingResult result) { // ... 省略 return service.findAll(); } //UPDATE @PutMapping("/{id}") @ResponseBody @Transactional(readOnly = false) public Instructor update(@PathVariable Integer id, @ModelAttribute("InstructorForm") InstructorForm instructorForm) { // ... 省略 return service.save(instructor); } //DELETE @DeleteMapping("/{id}") @ResponseBody @ResponseStatus(HttpStatus.NO_CONTENT) @Transactional(readOnly = false)//削除の場合必須 public void delete(@PathVariable Integer id) { // ... 省略 service.deleteById(id); }

投稿2018/09/24 14:09

euledge

総合スコア2404

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

spring_boot

2018/09/24 14:22

なんと! 大変貴重なご指摘ありがとうございます! 〉呼び出し側をAJAX呼び出しにして、APIにする そうなんですね。参考書やDBpressの記事を基準にしていたので自身ではたどり着けませんでした。ありがとうございました!
spring_boot

2018/09/25 00:19

確認しました。ありがとうございます。 知り合いのエンジニアがWebAPIとしてSpringを使ったと言っていたので このことかと納得しました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問