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

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

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

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

Java

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

REST

REST(Representational State Transfer)はwebアプリケーションの構築スタイルの一種です。HTTP GET/POSTによってリクエストを送信し、レスポンスはXMLで返されます。SOAPのようなRPCの構築と比べるとサーバからクライアントを分離することが出来る為、人気です。

Spring Boot

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

Q&A

解決済

1回答

4525閲覧

Javaを使ってRESTの実装【エラー:403】

takuyaK.

総合スコア5

Spring Security

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

Java

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

REST

REST(Representational State Transfer)はwebアプリケーションの構築スタイルの一種です。HTTP GET/POSTによってリクエストを送信し、レスポンスはXMLで返されます。SOAPのようなRPCの構築と比べるとサーバからクライアントを分離することが出来る為、人気です。

Spring Boot

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

0グッド

1クリップ

投稿2021/08/23 12:28

編集2021/08/24 11:08

Javaを使ってRESTの実装

JavaでRESTを実装しようとしていて403のエラーが出ております。
今開発しているWebサイトにはPUTとDELETEの機能を追加しており、PUTのみ正常に処理されない状態です。

発生している問題・エラーメッセージ

PUT http://localhost:8080/user/update 403
Infomation メソッド開始:ResponseEntity org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.error(HttpServletRequest) メソッド終了:ResponseEntity org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.error(HttpServletRequest)

![イメージ説明

該当のソースコード

UserRestController.java package com.example.rest; @RestController @RequestMapping("/user") public class UserRestController { @Autowired private UserService userService; // ユーザーを更新 @PutMapping("/update") public int updateUser(UserDetailForm form) { userService.updateUserOne(form.getUserId(), form.getPassword(), form.getUserName()); return 0; } // ユーザーを削除 @DeleteMapping("/delete") public int deleteUser(UserDetailForm form) { userService.deleteUserOne(form.getUserId()); return 0; } }
detail.js 'use strict'; //画面ロード時の処理 jQuery(function($) { // 更新ボタンを押した時の処理 $('#btn-update').click(function(event) { //ユーザー更新 updateUser(); }); // 削除ボタンを押した時の処理 $('#btn-delete').click(function(event) { //ユーザー更新 deleteUser(); }); }); // ユーザー更新処理 function updateUser() { //フォームの値を取得 var formData = $('#user-form').serializeArray(); //ajax通信 $.ajax({ type:"PUT", cache:false, url:'/user/update', data:formData, dataType: 'json', }).done(function(data) { //ajax成功時の処理 alert('ユーザーを更新しました'); //ユーザー一覧画面にリダイレクト window.location.href='/user/list'; }).fail(function(jqXHR, textStatus, errorThrown) { alert('ユーザー更新に失敗しました'); }).always(function() { //常に実行する処理 }); } // ユーザー削除処理 function deleteUser() { //フォームの値を取得 const formData = $('#user-detail-form').serializeArray(); //ajax通信 $.ajax({ type:"DELETE", cache:false, url:'/user/delete', data:formData, dataType: 'json', }).done(function(data) { //ajax成功時の処理 alert('ユーザーを削除しました'); //ユーザー一覧画面にリダイレクト window.location.href='/user/list'; }).fail(function(jqXHR, textStatus, errorThrown) { alert('ユーザー削除に失敗しました'); }).always(function() { //常に実行する処理 }); }
SecurityConfig.java package com.example.config; @EnableWebSecurity @Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter{ @Autowired private UserDetailsService userDetailsService; @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } // セキュリティの対象外を設定 @Override public void configure(WebSecurity web) throws Exception { // セキュリティを適応しない web .ignoring() .antMatchers("/webjars/**") .antMatchers("/css/**") .antMatchers("/js/**") .antMatchers("/h2-console/**"); } // セキュリティの各種設定 @Override public void configure(HttpSecurity http) throws Exception { // ログイン不要のページ設定 http .authorizeRequests() .antMatchers("/login").permitAll() //直リンクOK .antMatchers("/user/signup").permitAll() //直リンクOK .antMatchers("/admin").hasAuthority("ROLE_ADMIN") //権限制御 .anyRequest().authenticated(); //それ以外は直リンクNG // ログイン処理 http .formLogin() .loginProcessingUrl("/login") //ログイン処理のパス .loginPage("/login") //ログインページの指定 .failureUrl("/login?error") //ログイン失敗時の遷移先 .usernameParameter("userId") //ログインページのユーザーID .passwordParameter("password")//ログインページのパスワード .defaultSuccessUrl("/user/list", true);//成功後の遷移先 // ログアウト処理 http .logout() .logoutRequestMatcher(new AntPathRequestMatcher("/logout")) .logoutUrl("/logout") .logoutSuccessUrl("/login?logout"); // CSRF対策を向こうに設定(一時的) //http.csrf().disable(); } // 認証の設定 @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { PasswordEncoder encoder = passwordEncoder(); // インメモリ認証 // auth // .inMemoryAuthentication() // .withUser("user") //userを追加 // .password(encoder.encode("user")) // .roles("GENERAL") // .and() // .withUser("admin") //adminを追加 // .password(encoder.encode("admin")) // ユーザーデータで認証 auth .userDetailsService(userDetailsService) .passwordEncoder(encoder); } }
UserDetailsService.java package com.example.domain.user.service.impl; @Service public class UserDetailsServiceImpl implements UserDetailsService{ @Autowired private UserService service; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { // ユーザー情報取得 MUser loginUser = service.getLoginUser(username); // ユーザーが存在しない場合 if(loginUser == null) { throw new UsernameNotFoundException("user not found"); } // 権限リスト作成 GrantedAuthority authority = new SimpleGrantedAuthority(loginUser.getRole()); List<GrantedAuthority> authorities = new ArrayList<>(); authorities.add(authority); // UserDetaild生成 UserDetails userDetails = (UserDetails)new User(loginUser.getUserId(), loginUser.getPassword(), authorities); return userDetails; } }
detail.java <!DOCTYPE html> <html xmlns:th="http:/www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout/layout}"> <head> <meta charset="UTF-8"> <title>ユーザー詳細</title> <link rel="stylesheet" th:href="@{/css/user/list.css}"> <!-- js読み込み --> <script th:src="@{/js/user/detail.js}" defer></script> </head> <body> <div layout:fragment="content"> <div class="header border-bottom"> <h1 class="h2">ユーザー詳細</h1> </div> <form id="user-detail-form" method="post" th:action="@{/user/detail}" class="form-signup" th:object="${userDetailForm}"> <input type="hidden" th:field="*{userId}"> <table class="table table-striped table-hover table-bordered"> <tbody> <tr> <th class="w-25">ユーザーID</th> <td th:text=*{userId}></td> </tr> <tr> <th>パスワード</th> <td><input type="text" class="form-control" th:field=*{password}></td> </tr> <tr> <th>ユーザー名</th> <td><input type="text" class="form-control" th:field=*{userName}></td> </tr> <tr> <th>誕生日</th> <td th:text="*{#dates.format(birthday, 'YYYY/MM/dd')}"></td> </tr> <tr> <th>年齢</th> <td th:text="*{age}"></td> </tr> <tr> <th>性別</th> <td th:text="*{gender} == 1 ? '男性':'女性'"></td> </tr> <tr> <th>部署</th> <td> <span th:text="*{department.departmentName}"></span> </td> </tr> </tbody> </table> <div class="text-center"> <button class="btn btn-danger" type="submit" name="delete">削除</button> <button class="btn btn-primary" type="submit" name="update">更新</button> </div> <!-- RESTボタンエリア --> <div class="text-center mt-2"> <!-- 削除ボタン --> <button id="btn-delete" class="btn btn-danger" type="button">削除(REST)</button> <button id="btn-update" class="btn btn-primary" type="button">更新(REST)</button> </div> <!-- 給料情報 --> <th:block th:if="*{salaryList != null and salaryList.size() > 0}"> <div class="header border-bottom"> <h1 class="h2">給料</h1> </div> <table class="table table-striped table-border table-hover"> <thead> <tr> <th class=w-25>年月</th> <th>給料</th> </tr> </thead> <tr th:each="item:*{salaryList}"> <td th:text="${item.yearMonth}"></td> <td th:text="${#numbers.formatInteger(item.salary,3,'COMMA')}"></td> </tr> <tbody> </tbody> </table> </th:block> </form> </div> </body> </html>

試したこと

403エラーが出力されることからSecurity関連に問題があると思い、以下2点確認しましたが解決しませんでした。

①CSRFを無効化して再度PUTを実施しましたが相変わらず403エラーが発生しております。
http.csrf().disable();

②以下コードより.anyRequest().authenticatedを削除する。
http
.authorizeRequests()
.antMatchers("/login").permitAll() //直リンクOK
.antMatchers("/user/signup").permitAll() //直リンクOK
.antMatchers("/admin").hasAuthority("ROLE_ADMIN") //権限制御
.anyRequest().authenticated();

補足情報(FW/ツールのバージョンなど)

開発はSpringBootにて行っております。

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

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

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

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

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

mather

2021/08/23 14:20

実装にあたり参考にしたサイトなどあれば教えて下さい。
takuyaK.

2021/08/23 14:37

以下の書籍(12章)を参考にしました。 後悔しないためのSpring Boot 入門書:Spring 解体新書(第2版): Spring Bootが丸分かり Spring解体新書
m.ts10806

2021/08/23 20:41

書籍のバージョンと自身の環境のバージョンは全く同じでしょうか?
takuyaK.

2021/08/24 01:26

バージョンは同じにしております。
m.ts10806

2021/08/24 11:12

手元に本がないので書籍名と各バージョン追記いただけますか?
m.ts10806

2021/08/24 11:13

あとDELETEではなくPOSTやGETにして確かめてみてください(アノテーションも変更してくださいね。)
guest

回答1

0

自己解決

こちら解決いたしました。

処理が上手くいかなかった理由は以下記載の通りです。

送信用のformのidを"user-detail-form"のように設定しているにも関わらず
受け取るときのidを'#user-form'と記載していることが原因でした。

投稿2021/08/24 11:12

takuyaK.

総合スコア5

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問