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

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

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

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

Java

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

Spring Boot

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

Q&A

解決済

3回答

21459閲覧

SpringBootで作ったログイン機能でログイン後にユーザー情報を取得したい

yys949

総合スコア9

Spring Security

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

Java

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

Spring Boot

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

0グッド

1クリップ

投稿2020/05/24 16:22

編集2020/05/25 12:21

前提・実現したいこと

SpringBootをつかってログイン機能を勉強として作っています。
認証はSpringSecurityを使っています。

ログインボタンを押したらユーザーの名前とログインに使用したIDをログイン後の画面に表示したいのですが、Controllerの処理の書き方がよくわからずにいます。
principalを使ったらユーザー名だけは取得できたのですが、ユーザーの全情報を取得できるようにしたいです。

DBにはユーザー情報が1レコード登録してありそれを取り出してControllerで受け渡しをしたいです。

該当のソースコード

LoginController.java

1@Controller 2public class LoginController { 3 4 @Autowired 5 UserForm userForm; 6 7 @Autowired 8 UserService userService; 9 10 @GetMapping({"/", "/login"}) 11 public String loginForm(UserForm userForm, Model model) { 12 13 return "/login"; 14 } 15 16 /* 17 * ログイン認証処理 18 */ 19 @PostMapping("/index") 20 public String loginFormSubmit(@Valid @ModelAttribute UserForm loginUser, 21 BindingResult result, Model model) { 22 23 if(result.hasErrors()) { 24 return "/login"; 25 } 26 27 UserEntity userInfo = userService.loginCheck(loginUser.getUserId(), loginUser.getPassword()); 28 29 if(userInfo == null) { 30 model.addAttribute("error", "error"); 31 32 return "/login"; 33 } 34 setLoginInfo(userInfo); 35 model.addAttribute(loginUser); 36 37 38 return "redirect:/index"; 39 } 40 41 private void setLoginInfo(UserEntity userEntityResult) { 42 43 this.userForm.setUserId(userEntityResult.getUserId()); 44 this.userForm.setPassword(userEntityResult.getPassword()); 45 this.userForm.setUserName(userEntityResult.getUserName()); 46 47 } 48 49 @GetMapping("/index") 50 public String afterLogin(@ModelAttribute UserForm loginUser, Model model) { 51 52 model.addAttribute("loginUser", loginUser); 53 54 return "/index"; 55 } 56 57 58} 59

UserService.java

1@Service 2@Transactional 3public class UserService { 4 5 @Autowired 6 private UserRepository userRepository; 7 8 @Autowired 9 LoginUserDao loginUserDao; 10 11 @Autowired 12 private BCryptPasswordEncoder passwordEncoder; 13 14 public UserEntity create(UserEntity account, String rawPassword) { 15 String encodePassword = passwordEncoder.encode(rawPassword); 16 account.setPassword(encodePassword); 17 18 return userRepository.save(account); 19 } 20 21 public UserEntity loginCheck(String userId, String password) { 22 return loginUserDao.findUser(userId); 23 } 24 25}

LoginUserDao.java

1@Repository 2public class LoginUserDao { 3 4 @Autowired 5 EntityManager em; 6 7 public UserEntity findUser(String userId) { 8 String query = ""; 9 query += "SELECT * "; 10 query += "FROM USERS "; 11 query += "WHERE USER_ID = :userId "; 12 13 return (UserEntity)em.createNativeQuery(query, UserEntity.class).setParameter("userId", userId) 14 .getSingleResult(); 15 } 16} 17

login.html

index.html

1<!DOCTYPE html> 2<html xmlns:th="http://thymeleaf.org"> 3<head> 4 <meta charset="UTF-8"> 5 <title>ログイン後の画面</title> 6</head> 7<body> 8<div th:object="${loginUser}"> 9 <p>ログインユーザーID:<span th:text="*{userId}"></span></p> 10 <p>ログインユーザー名:<span th:text="*{userName}"></span></p> 11</div> 12</body> 13</html>

UserEntity.java

1@Entity 2@Table(name = "USERS") 3public class UserEntity implements UserDetails{ 4 5 /** 6 * 7 */ 8 private static final long serialVersionUID = 1L; 9 10 @Id 11 @Column(name = "USER_ID") 12 @NotEmpty 13 private String userId; 14 15 @Column(name = "USER_NAME") 16 @NotEmpty 17 private String userName; 18 19 @Column(name = "ADMIN_FLG") 20 private int adminFlg; 21 22 @Column(name = "PASSWORD") 23 @NotEmpty 24 private String password; 25 26 public String getUserId() { 27 return userId; 28 } 29 30 public void setUserId(String userId) { 31 this.userId = userId; 32 } 33 34 public String getUserName() { 35 return userName; 36 } 37 38 public void setUserName(String userName) { 39 this.userName = userName; 40 } 41 42 public int getAdminFlg() { 43 return adminFlg; 44 } 45 46 public void setAdminFlg(int adminFlg) { 47 this.adminFlg = adminFlg; 48 } 49 50 public String getPassword() { 51 return password; 52 } 53 54 public void setPassword(String password) { 55 this.password = password; 56 } 57 58 @Override 59 public Collection<? extends GrantedAuthority> getAuthorities() { 60 // TODO 自動生成されたメソッド・スタブ 61 return null; 62 } 63 64 @Override 65 public String getUsername() { 66 // TODO 自動生成されたメソッド・スタブ 67 return null; 68 } 69 70 @Override 71 public boolean isAccountNonExpired() { 72 // TODO 自動生成されたメソッド・スタブ 73 return false; 74 } 75 76 @Override 77 public boolean isAccountNonLocked() { 78 // TODO 自動生成されたメソッド・スタブ 79 return false; 80 } 81 82 @Override 83 public boolean isCredentialsNonExpired() { 84 // TODO 自動生成されたメソッド・スタブ 85 return false; 86 } 87 88 @Override 89 public boolean isEnabled() { 90 // TODO 自動生成されたメソッド・スタブ 91 return false; 92 } 93 94} 95

JpaUserDetailsServiceImpl.java

1@Component 2@Service 3public class JpaUserDetailsServiceImpl implements UserDetailsService { 4 5 //DBからユーザ情報を検索するメソッドを実装したクラス 6 @Autowired 7 private LoginUserDao userDao; 8 9 @Override 10 public UserDetails loadUserByUsername(String userId) throws UsernameNotFoundException { 11 12 UserEntity user = userDao.findUser(userId); 13 14 if (user == null) { 15 throw new UsernameNotFoundException("User" + userId + "was not found in the database"); 16 } 17 List<GrantedAuthority> grantList = new ArrayList<GrantedAuthority>(); 18 GrantedAuthority authority = new SimpleGrantedAuthority("USERS"); 19 grantList.add(authority); 20 21 //rawDataのパスワードは渡すことができないので、暗号化 22 BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); 23 24 UserDetails userDetails = (UserDetails)new User(user.getUserName(), encoder.encode(user.getPassword()),grantList); 25 26 return userDetails; 27 } 28}

試したこと

上述した通り、Principalを使うとユーザー名だけは取得できました。
ただそれだけでなく、UserFormにある情報(ユーザーIDとユーザー名の両方)を取得したいです。

@PostMappingだけで完結させればいいかと思ってloginFormSubmit()にいろいろ書いていたのですが、それだとログイン後の画面URLに遷移したときGETがないといけないといったエラーがでてしまったため@GetMappingの処理も書きました。
@ModelAttributeを両方に書けばいくかと思って書いたのですがデバッグするとUserFormがnullになっていました。

上記のような感じで書いてあります。
ログイン先の画面への移行はできたのですが、そもそものuserInfoとしたところがユーザー情報をすべて返すように作ったと思ったのにnullが返ってきています。
dao内の書き方が悪いのでしょうか。

全然わからなくなってしまったため教えていただきたいです。
お手数おかけしますがよろしくお願いします。

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

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

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

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

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

guest

回答3

0

  1. UserDetailsService の実装を自前でしましょう。
  2. 自前のユーザー情報テーブルの エンティティは UserDetails を継承しましょう

そうすることでユーザー情報が認証情報として取得できます。

細かい内部実装は公式ドキュメントにもかいてあるので宣言部だけ

@Service public class UserService implements UserDetailsService {
@Entity @Table(name = "users") public class User implements UserDetails {
public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder a) throws Exception { a.userDetailsService(userService).passwordEncoder(passwordEncoder());

投稿2020/05/25 12:13

編集2020/05/25 12:24
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

yys949

2020/05/25 12:22

ありがとうございます。 教えていただいた1,2は上記追記した内容でしょうか。こちらに書いてなかっただけでプロジェクト内にはあるため追記しました。
guest

0

自己解決

こちらそもそもの認識が間違っていました。
SpringSecurityを使って認証処理をしているためそもそも自分でごちゃごちゃ書く必要がありませんでした。
@PostMappingの部分の処理は消しました。
UserDetailsServiceを継承したJpaUserDetailsServiceImplでHttpSessionを@AutowiredしJpaUserDetailsServiceImplのloadUserByUsername()内でsetAttributeをつかい属性にloadUserByUsernameの引数をセットすればセッションが保存されました。
Controller側でも同じようにHttpSessionを@Autowiredしセッションから先ほどの属性をgetAttributeでとってきてString型にキャストしてStringの変数に格納、それを使いDaoでユーザー検索をするだけでよかったようです。

投稿2020/05/31 11:41

yys949

総合スコア9

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

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

yys949

2020/06/01 03:24

全然わかっていませんでした。 お時間割いていただいたのに申し訳ありません。 参考ありがとうございます。 読み勉強させていただきます。
guest

0

userService.loginCheck()で何を返しているか次第ですが、ユーザー情報そのままなのであれば、
!=nullのときにセッションに入れれば良いのではないでしょうか。

いずれにしても認可必要なページではセッションで持っておかないとアクセス時にチェックできないと思います。

投稿2020/05/24 18:14

編集2020/05/24 20:43
m.ts10806

総合スコア80875

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

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

yys949

2020/05/25 12:08 編集

セッションについての知識もあいまいでしたが追記してみましたが結果は変わりませんでした。 ただ修正して書いたようにそもそものユーザー情報がとれていないことがわかりました。 ですがdaoのどこが間違えててユーザー情報がとれていないのかわからないです...
m.ts10806

2020/05/25 12:12

デバッグしてみては。daoだけとは限りませんよ。 SQLは正しく通るのか、結果は想定どおりか、分岐はどこを通っているか など
yys949

2020/05/25 12:26

デバッグすると@PostMappingのほうの処理を通っていませんでした。 そのため@PostMappingを@GetMappingにしてみたところuserInfoはnullになっていました。 chromeの開発者ツールのネットワークで見ると、遷移先の/indexがgetとpost両方あり@GetMappingがないとエラーがでてしまうため@GetMappingの処理を書いていたのですが、そもそもデバッグして通っていないということは@PostMappingの方の処理は書いている意味がなく、すべて@GetMappingのほうの処理に書くべきだったのでしょうか...
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問