概要
- Spring Securityで必要最低限のログイン機能を実装する。(権限周りは触れません。)
- ログインフォームなどはSpring Securityで用意されているものを使う。
- 仕組みはあまり理解できていないので、また別でまとめます。
- この投稿はとりあえず、動くようになったというところまで!
開発環境
- OS:Windows10
- IDE:eclipse 2019-12
- Java:13
- Spring boot:2.2.5(Gradle)
- DB:Oracle 12c
Spring Securityの導入
依存関係で下記の4つを選択
DB接続情報をプロパティファイルに記述
- それぞれのDBに合った内容にしてください。
application.properties
spring.datasource.url=jdbc:oracle:thin:@//localhost:1521/[データベース名]
spring.datasource.username=[DBユーザー名]
spring.datasource.password=[パスワード]
spring.datasource.driver-class-name=oracle.jdbc.OracleDriver
ユーザー情報のテーブルを作成
create table USER_TABLE (
USER_ID VARCHAR2(30 char)
, FAMILY_NAME VARCHAR2(10 char) not null
, FIRST_NAME VARCHAR2(10 char) not null
, PASSWORD VARCHAR2(255) not null
, constraint USER_TABLE_PKC primary key (USER_ID)
) ;
データ登録
下記のパスワードは「pass」をハッシュ化したものです。
この記事を参考にしました。
INSERT INTO
USER_TABLE
VALUES(
'0001'
,'テスト'
,'太郎'
,'$2a$10$w0C4tFU.SLFATC1Y6Y4uy.vMYsLXhlfvgnFP4dLbRjEa6/Ag1csKS'
);
Entityクラスを作成
UserTable.java
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "USER_TABLE")
public class UserTable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "USER_ID")
private String userId;
@Column(name = "FAMILY_NAME")
private String familyName;
@Column(name = "FIRST_NAME")
private String firstName;
@Column(name = "PASSWORD")
private String password;
// Getter,Setterは省略
リポジトリを作成
UserTableRepository.java
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.azkz.entity.UserTable;
@Repository
public interface UserTableRepository extends JpaRepository<UserTable, String> {
public UserTable findByUserId(String userId);
}
SecurityConfigを作成
DemoSecurityConfig.java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
@EnableWebSecurity
public class DemoSecurityConfig extends WebSecurityConfigurerAdapter {
//アクセス可能なURLの制限とログイン成功時の遷移先の指定をするメソッド
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.authorizeRequests()
.mvcMatchers("/").permitAll() // 「/」は誰でもアクセスできる
.anyRequest().authenticated() // それ以外はログインが必要
.and()
.formLogin()
.defaultSuccessUrl("/success"); // ログイン成功時には「/success」にGetリクエストをする
}
//入力されたパスワードをBCrypt方式でハッシュ化するメソッド
@Bean
protected PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
UserDetailsServiceを作成
- DBからユーザ情報を取得し、DemoUserDetailsをインスタンス化する。
DemoUserDetailsService.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import com.azkz.entity.UserTable;
import com.azkz.repository.UserTableRepository;
@Service
public class DemoUserDetailsService implements UserDetailsService {
@Autowired
UserTableRepository userTableRepository;
@Override
public UserDetails loadUserByUsername(String userId) throws UsernameNotFoundException {
//入力されたUserIDを条件にDBからデータを取得する
UserTable userTable = userTableRepository.findByUserId(userId);
// 入力値(ユーザーID、パスワード)とインスタンス化したDemoUserDetailsクラスを
// SpringSecurityの内部で比較することで、ログインチェックを行っている。
return new DemoUserDetails(userTable);
}
}
UserDetailsを作成
- このクラスが入力情報(ユーザID、パスワード)と比較されることになる(?)
- ログイン後のセッション情報もこれ
DemoUserDetails.java
import java.util.Collections;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.User;
import com.azkz.entity.UserTable;
public class DemoUserDetails extends User {
@Autowired
UserTable userTable;
public DemoUserDetails(UserTable userTable) {
// 「Collections.emptySet()」は本来は権限名のコレクションとなる。今回は空。
super(userTable.getUserId(), userTable.getPassword(),Collections.emptySet());
this.userTable = userTable;
}
// セッション情報から独自の項目を取得するためのGetter
public String getFirstName() {
return this.userTable.getFirstName();
}
public String getFamilyName() {
return this.userTable.getFamilyName();
}
}
Controllerを作成
- 成功時にログインユーザの情報を表示する
DemoController.java
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import com.azkz.security.DemoUserDetails;
@RestController
public class DemoController {
@GetMapping("/success")
public DemoUserDetails loginSuccess() {
// ログイン中のユーザ情報を取得
DemoUserDetails demoUserDetails =
(DemoUserDetails) SecurityContextHolder
.getContext().getAuthentication().getPrincipal();
return demoUserDetails;
}
}
画面確認
http://localhost:8080/login にアクセス
ログイン成功
ログイン失敗
終わりに
- 表面的なことしか書いておりませんが、間違い・不足点等がございましたら、ぜひご教示いただきたく存じます。何卒!