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

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

新規登録して質問してみよう
ただいま回答率
85.48%
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

解決済

2回答

2426閲覧

【Spring Security】 LoginUserDetailsのコンストラクターでエラーが発生する

1998Ttf

総合スコア6

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グッド

0クリップ

投稿2021/09/13 07:34

編集2021/09/13 07:37

###実現したいこと

現在、【はじめてのSpringBoot[改訂版]】を使用し、ログイン機能を作成しようとしています。

DBマイグレーションはFlywayを使用しています。

しかし、SpringBootのバージョンアップに伴い、リポジトリのfindOneメソッドが、

findByIdメソッドに代わり、Optional<※※※>をつけて使用しているのですが、

LoginUserDetailsのコンストラクターでエラーが発生してしまい、うまく動作ができない状況です。

Spring Boot初学者です。

###使用環境

ー Mac OS
ー Java11
ー SpringBoot 2.5.4
ー SpringToolSuite 4.0

###コード

LoginUserDetails

1import com.example.hajibootthymeleaf.domain.User; 2import lombok.Data; 3 4import java.util.Optional; 5 6import org.springframework.security.core.authority.AuthorityUtils; 7 8@Data 9public class LoginUserDetails extends org.springframework.security.core.userdetails.User { 10 private final Optional<User> user; 11 12 public LoginUserDetails(Optional<User> user) { 13 super(user.getUsername(), user.getEncodedPassword(), 14 ⬆︎エラー                                ⬆︎エラー 15AuthorityUtils.createAuthorityList("ROLE_USER")); 16 this.user = user; 17 } 18} 19

error

1The method getEncodedPassword() is undefined for the type Optional<User>

LoginUserDetailsService

1import com.example.hajibootthymeleaf.domain.User; 2import com.example.hajibootthymeleaf.repository.UserRepository; 3 4import java.util.List; 5import java.util.Optional; 6 7import org.springframework.beans.factory.annotation.Autowired; 8import org.springframework.security.core.userdetails.UserDetails; 9import org.springframework.security.core.userdetails.UserDetailsService; 10import org.springframework.security.core.userdetails.UsernameNotFoundException; 11import org.springframework.stereotype.Service; 12 13public class LoginUserDetailsService implements UserDetailsService { 14 @Autowired 15 UserRepository userRepository; 16 17 @Override 18 public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 19 Optional<User> user = userRepository.findById(username); 20 if (user == null) { 21 throw new UsernameNotFoundException("The requested user is not found."); 22 } 23 return new LoginUserDetails(user); 24 } 25} 26

userRepository

1import com.example.hajibootthymeleaf.domain.User; 2 3import org.springframework.data.jpa.repository.JpaRepository; 4 5public interface UserRepository extends JpaRepository<User, String> { 6} 7

user

1import com.fasterxml.jackson.annotation.JsonIgnore; 2import lombok.AllArgsConstructor; 3import lombok.Data; 4import lombok.NoArgsConstructor; 5import lombok.ToString; 6 7import javax.persistence.*; 8import java.util.List; 9 10@Data 11@NoArgsConstructor 12@AllArgsConstructor 13@Entity 14@Table(name = "users") 15@ToString(exclude = "customers") 16public class User { 17 @Id 18 private String username; 19 @JsonIgnore 20 private String encodedPassword; 21 @JsonIgnore 22 @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "user") 23 private List<Customer> customers; 24}

aprication_properties

1spring.datasource.driver-class-name=net.sf.log4jdbc.DriverSpy 2spring.datasource.url=jdbc:log4jdbc:h2:file:./target/db/customer 3logging.level.jdbc=OFF 4logging.level.jdbc.sqltiming=DEBUG 5spring.jpa.hibernate.ddl-auto=validate 6 7security.basic.enabled=false

かなり詰まっていまして、どうにも解決できません。

ご教授いただければ幸いです。

どうぞよろしくお願い致します。

退会済みユーザー👍を押しています

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

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

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

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

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

guest

回答2

0

自己解決

SpringBoot2.5.4では「findOne()」メソッドは使用できず、代わりに「findById()」が使用できます。しかし、Optionalでラップする必要があり、そのOptionalのラップが、今回の「getusername(), getEncodedPassword()」メソッドの妨げとなっていました。
よって、Optionalでラップしないよう「getById」メソッドを使用したところ、うまく動作しました。

findとgetの違いについての参考記事はこちらをご覧ください([findとgetの違いについて])(https://www.fixes.pub/program/245101.html)

修正点として

・上記、質問した際のコードの「Optional<クラス名>」のところを全て「クラス名」に変更します。
・以下のように再度修正する

LoginUserDetailsService

1package com.example.hajibootthymeleaf.service; 2 3import com.example.hajibootthymeleaf.domain.User; 4import com.example.hajibootthymeleaf.repository.UserRepository; 5 6 7import org.springframework.beans.factory.annotation.Autowired; 8import org.springframework.security.core.userdetails.UserDetails; 9import org.springframework.security.core.userdetails.UserDetailsService; 10import org.springframework.security.core.userdetails.UsernameNotFoundException; 11import org.springframework.stereotype.Service; 12import org.springframework.transaction.annotation.Transactional;  // ←追加しました 13 14@Service //←つけ忘れていました。すみません。 15 16@Transactional //←追加しました(こちらがないと、セッションエラーになります。下記にエラー詳細のURL貼ります。) 17// ※[セッションエラーについて](https://qiita.com/zakki/items/2f4dd7768313a3f855f7) 18 19public class LoginUserDetailsService implements UserDetailsService { 20 @Autowired 21 UserRepository userRepository; 22 23 @Override 24 public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 25 User user = userRepository.getById(username); // ←変更しました 26 if (user == null) { 27 throw new UsernameNotFoundException("The requested user is not found."); 28 } 29 return new LoginUserDetails(user); 30 } 31}

その他、ご指摘等ございましたら、どうぞよろしくお願い致します。

投稿2021/09/14 01:03

1998Ttf

総合スコア6

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

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

0

Optional<User> user 変数から、getEncodedPassword() というメソッドを呼び出そうとしていると思うのですが、
変数 user は Optional クラスのインスタンスで、
java.util.Optional には getEncodedPassword() というメソッドは存在しておらず、そのため(コンパイル)エラーになっています。
https://docs.oracle.com/javase/jp/8/docs/api/java/util/Optional.html

(おそらく)User クラスの getUsername(), getEncodedPassword() を呼びだしたいのかなと思ったのですが、
その場合はいったん Optional<User> user から、Userクラスの変数を取り出して、
取り出したものに対してメソッドを呼び出す必要があります

// username, encodePassword が null の場合は空文字にしてますが、 // 初期値が設定したいのであれば適宜変更が必要 String name = user.map(User::getUsername).orElse(""); String encodePass = user.map(User::getEncodedPassword).orElse(""); super(name , encodePass);

他には以下など

// User が存在する場合だけ親のコンストラクタを呼び出せばよい場合 user.ifPresent(u -> super(u.getUsername(), u.getEncodedPassword())); // User がない場合も親のコンストラクタを呼び出す必要がある場合 user.ifPresentOrElse(u -> super(u.getUsername(), u.getEncodedPassword()), () -> super("", "")); // User がある場合はコンストラクタを呼び出して、ない場合は別の処理(例外を出すとか)をしたい場合 if (user.isPresent()) { User u = user.get(); super(u.getUsername(), u.getEncodedPassword()); } else { throw new Exception("not exist user"); }

投稿2021/09/13 16:28

kiino

総合スコア539

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

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

1998Ttf

2021/09/14 00:51

ご回答ありがとうございます!! ご指摘の 「変数 user は Optional クラスのインスタンスで、java.util.Optional にはgetEncodedPassword()というメソッドは存在しておらず、そのため(コンパイル)エラーになっている」 の通りでした! いただいたコードは付け加えず、再度自身で考えた結果、 SpringBoot2.5.4では「findOne」が使えず、Optionalをつけないと実装できないので、「そもそもOptionalでラップしなければいいんじゃないか?」と考え、「getById」メソッドを使用し、実装したところ、動きました! しかし、まだ初心者ですので、至らない点があるかと思います。下記に修正したコードを記載させていただきますので、どうぞご査収のほどよろしくお願い致します! ```LoginUserDetailsService import org.springframework.transaction.annotation.Transactional;  ←追加しました @Service @Transactional  ←追加しました public class LoginUserDetailsService implements UserDetailsService { @Autowired UserRepository userRepository; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { User user = userRepository.getById(username);  ←変更部分 if (user == null) { throw new UsernameNotFoundException("The requested user is not found."); } return new LoginUserDetails(user); } } ```
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問