Spring Security에서 DB 인증 및 BCrypt로 해시

개요


  • Spring Security에 필요한 최소한의 로그인 기능을 구현한다. (권한 주위는 만지지 않습니다.)
  • 로그인 폼 등은 Spring Security로 준비되어 있는 것을 사용한다.
  • 구조는 별로 이해할 수 없기 때문에, 또 따로 정리합니다.
  • 이 투고는 우선, 움직이게 되었다고 하는 곳까지!


  • 개발 환경


  • OS:Windows10
  • IDE: eclipse 2019-12
  • Java: 13
  • Spring boot:2.2.5(Gradle)
  • DB: Oracle 12c


  • Spring Security 도입



    종속성으로 다음 네 가지 선택


  • Spring Security
  • Spring Web
  • Spring Data JPA
  • Oracle Driver ← 사용할 DB 드라이버를 선택하십시오.



  • 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();
        }
    
    }
    


    컨트롤러 작성


  • 성공시 로그인 사용자의 정보를 표시합니다

  • 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 방문





    로그인 성공





    로그인 실패





    끝에


  • 표면적인 것 밖에 쓰고 있지 않습니다만, 실수·부족점등이 있으면, 꼭 교시해 주셨으면 합니다. 아무쪼록!
  • 좋은 웹페이지 즐겨찾기