前→https://qiita.com/19960417akiho/items/2aa16ce876c4937b0cc3
以下の動画を参考に、ハンズオン形式でSpring BootでWebアプリを制作していきます。
今回はPart10。
パスワードのハッシュ化をSpringSecurityを用いて実装します。
まず、SpringSecurityを使うには、pom.xmlに情報を追加しなければなりません。
pom.xml
<!-- PasswordEncoder(Spring Security)-->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
</dependency>
これでSpringSecurityの機能を用いることができます。
つぎに、configパッケージを作って、そのなかにBeanDifine.javaクラスを作っていきます。
正直Beanってなに?って感じですが、とりあえず動画の通りに実装してみて、疑問点をChatGPTに聞いてみます。
BeanDifine.java
package com.example.demo.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
public class BeanDifine {
@Bean
PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
まず@Configurationですが、これは@Beanとセットで付与するアノテーションだそうです。
クラスには@Configuration、その中のメソッドには@Beanって感じです。
動画の中では、
「@Beanを付与したメソッドはDIコンテナに登録され、DI注入(@RequiredArgsConstructor配下でprivate finalしてインスタンス化)することができます」
と説明されています
頑張って調べてもいまいち理解できなかったので、以下は自分なりの理解です。
まず、@Beanとアノテーションがつけられたメソッドは特別扱いされます。
どう特別扱いされるかというと、そのメソッドの戻り値をキーとして、@RequiredArgsConstructorが付与されたクラスでも使うことができます。
今回で言うと、PasswordEncoderという型をキーとして、LoginControllerクラスでも使うことができるようになります。
LoginControllerクラスを見てみましょう
LoginController.java
@Controller
@RequiredArgsConstructor
public class LoginController {
/** PasswordEncoder*/
private final PasswordEncoder passwordEncoder;
@PostMapping("/login")
public String login(Model model, LoginForm form) {
var userInfo = service.searchUserById(form.getLoginId());
var isCorrectUserAuth = userInfo.isPresent()
&& passwordEncoder.matches(form.getPassword(), userInfo.get().getPassword());
if(isCorrectUserAuth) {
return "redirect:/menu";
}else {
// TODO エラーメッセージはプロパティファイルで一元管理する
model.addAttribute("errorMsg","IDとPASSの組み合わせが間違っています。");
return "login";
}
}
}
今回の実装に関係がある部分だけを記載しています。
まず、PasswordEncoder型のpasswordEncoderをフィールド化しています。
さっきの@Beanアノテーションがつけられていたのは、PasswordEncoderを戻り値にもつメソッドでした。
なので、passwordEncoderというフィールド内にpasswordEncoder()が装備されるというわけです。
また、psswrodEncoderにはprivate finalが修飾子としてついているので、@RequiredArgsConstructorによってLoginControllerの引数として組み込まれます。
つまり、LoginControllerがインスタンス化されるときに、引数のPasswordEncoder passwordEncoderもインスタンス化され、passwordEncoder()で実装したBCryptPasswordEncoderもインスタンス化されます。
これで、LoginControllerクラスの中でもBCryptPasswordEncoderが実装されたpasswordEncoderというインスタンスを利用することができます。
これでBCryptPasswordEncoderクラスがもっているハッシュ化に関するメソッドが使えます。
DBの方のパスワードは事前にハッシュ化しているので、単純に入力された生のパスワードとDBのパスワードを比較してもfalseが返ってきます。
&& passwordEncoder.matches(form.getPassword(), userInfo.get().getPassword());
上記のコードが生のパスワードとハッシュ化されたパスワードの比較です。
一つめの引数はformインスタンスが持っている生のパスワードを引っ張ってきて、二つ目の引数にはuserInfoインスタンスの情報からハッシュ化されたパスワードのみを引っ張ってきています。
次→https://qiita.com/19960417akiho/items/9bfc85a6c790a1fe9e22