ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 스프링부트 스프링시큐리티 연동하기(1) Gradle/Mybatis/Oracle
    Spring Security 2019. 6. 15. 23:27
    반응형

    스프링부트로 스프링시큐리티 연동하는 예제가 별로 없어서 포스팅을 하게 되었다. (일반 xml로 하는 연동과 별반 차이는 없다..)

    개발 사양은 다음과 같다.

    SpringBoot 버전 2.x / Gradle 버전 3.x / jdk 1.8 / Srping 버전 5.x  / Spring Security 버전 5.x / 오라클11g xe

    나도 스프링 시큐리티를 잘 모르지만 복습차원에서 비교적 간단하게 스프링시큐리티를 구현하겠다.

    1. 스프링부트 프로젝트를 Gradle 빌드 타입으로 생성한다.

    2. 프로젝트가 생성되면 build.gradle파일에 필요한 dependencies를 추가해야 한다.

    (build.gradle)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    repositories {
        mavenCentral()
        maven { url "https://code.lds.org/nexus/content/groups/main-repo"}  /* oracle ref url*/
    }
     
    dependencies {
     
        implementation 'org.projectlombok:lombok'
        compile group: 'org.springframework.security', name: 'spring-security-taglibs', version: '5.0.6.RELEASE'
        compile('javax.servlet:jstl')
        
        
        /*lombok*/
        implementation 'org.projectlombok:lombok'
        
        /*devtools*/
        
         /* oracle jdbc driver */
            
        /*mybais*/
        
        /* log */   
        
    }
     

    시큐리티 포스팅 작업에 필요한 dependencies가 모두 등록되있다.

    등록 후 프로젝트 우클릭 > Gradle > Refresh Gradle Project

     

    3. 부트는 설정파일이 src/main/resources/application.properties 경로에 파일이 생성된다. 이 프로퍼티에 

    각종 설정 값을 선언해야 한다.

    (application.properties)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    # View
     
    # sql log driver
     
    # 데이터베이스 정보 입력
    spring.datasource.username=devmk
    spring.datasource.password=1234
     
    # vo의 패키지 경로 
     
    # 쿼리를 작성한 xml 의 경로
     
    # devtools
    spring.devtools.livereload.enabled=true
     
    #Encoding UTF-8
     
    #Messages
    spring.messages.basename=messages/message

    나는 위와 같이 설정을 하였다. 앞으로 이 설정 기준으로 디렉토리를 만들겠다.

    나의 디렉토리 구조

    4. 시큐리티 작업에 필요한 회원테이블을 생성한다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
      CREATE TABLE "DEVMG"."SECURITY_MEMBER" 
       (    "ID" VARCHAR2(255 BYTE),  --아이디
        "PASSWORD" VARCHAR2(255 BYTE), --비밀번호
        "SEQ" NUMBER, -- 시퀀스
        "MEMBER_NAME" VARCHAR2(255 BYTE), --이름
        "USER_ROLE" NVARCHAR2(25), -- 권한
        "EMAIL" VARCHAR2(255 BYTE), -- 이메일
        "PASSWORD_LOCK" VARCHAR2(255 BYTE), -- 비밀번호 틀린 횟수
        "PASSWORD_CHG_DATE" VARCHAR2(16 BYTE), -- 비밀번호 변경일자
        "REG_DATE" VARCHAR2(16 BYTE), -- 등록일
        "MOD_DATE" VARCHAR2(16 BYTE), -- 수정일
        "STATUS" VARCHAR2(2 BYTE) -- 회원상태
       )

    위와 같이 테이블을 생성했다.

    권한 USER_ROLE 컬럼은 필수이다. 이곳에 시큐리티 권한값이 들어가게 된다. 

    다른 스프링 시큐리티 포스팅에는 유저권한 테이블을 나눴지만 나는 회원테이블에 넣었다.

    비밀번호가 틀릴 시 카운트를 누적해야 하기 때문에 PASSWORD_LOCK 컬럼을 만들었다.

    1
    2
    3
    4
    5
    6
    Insert into DEVMG.SECURITY_MEMBER (
        ID,PASSWORD,SEQ,MEMBER_NAME,USER_ROLE,EMAIL,PASSWORD_LOCK,PASSWORD_CHG_DATE,REG_DATE,MOD_DATE,STATUS
    values (
        'user','1234',null,'유저','ROLE_USER',null,'0',null,null,null,null
    );

    샘플데이터를 1건 넣어주자

    5. lombok으로 회원 vo를 만들어 주자. (Member.java)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
     
     
     
     
    import lombok.Data;
     
    @Data
    public class Member implements UserDetails {
     
        private static final long serialVersionUID = 1L;
        
        private String id;
        private String password;
        private String memberName;
        private String email;
        private String userRole;
        private int passwordLock;
        private String regDate;
        private String modDate;
        private String passwordChgDate;
        private String status;
        
        /*UserDetails 기본 상속 변수 */
        private Collection<extends GrantedAuthority> authorities;
        private boolean isEnabled = true;
        private String username;
        private boolean isCredentialsNonExpired = true;
        private boolean isAccountNonExpired = true;
        private boolean isAccountNonLocked = true;
     
    }
     

    스프링 시큐리티의 인증정보를 담기 위해선 스프링시큐리티에서 제공하는 UserDetails의 인터페이스를

    상속받고 기본 vo를 반드시 정의해야지만 빨간줄이 사라진다;

    +추가로 로그인할때 로그를 남기기 위하여 로그용 vo도 만들었다.

    (LoginLog.java)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    import lombok.Data;
     
    @Data
    public class LoginLog extends Member {
        private String loginIp;
        private String loginDate;
     
    }r

    6. SQL파일을 작성 한다. (login.xml)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    <?xml version="1.0" encoding="UTF-8"?>
     
     
     
         <select id="getSelectMeberInfo" parameterType="String" resultType="com.devmk.test.vo.Member">
            /* 회원정보조회 */
            SELECT 
                ID as id
                , ID as username
                , PASSWORD as password
                , MEMBER_NAME as memberName
                , USER_ROLE as userRole
            FROM SECURITY_MEMBER
               WHERE ID = #{id}
        </select>
        
        <update id="setUpdatePasswordLockCnt" parameterType="String">
             /*비밀번호 틀린 횟수 증가*/
             UPDATE SECURITY_MEMBER 
            SET
                  PASSWORD_LOCK = NVL(PASSWORD_LOCK, 0) + 1
            WHERE
                  id = #{id}
        </update>
     
        <update id="setUpdatePasswordLockCntReset" parameterType="String">
             /*비밀번호 틀린 횟수 초기화*/
             UPDATE SECURITY_MEMBER 
            SET
                  PASSWORD_LOCK = 0
            WHERE
                  id = #{id}
        </update>
     
        <insert id="setInsertLoginLog" parameterType="com.devmk.test.vo.LoginLog">
            /* 로그인 로그 */
            INSERT INTO SECURITY_MEMBER_LOG
                (
                    SEQ /* 테이블 키 */
                    , ID /* 아이디 */
                    , LOGIN_IP /* 로그인 아이피 */
                    , LOGIN_DATE /* 로그인 날짜 */
                    , STATUS /*성공여부*/
                )
            VALUES
                (
                       SEQ_SECURITY.nextval
                    , #{id}
                    , #{loginIp}
                    , TO_CHAR(SYSDATE,'YYYYMMDDHH24MISS')
                    , #{status}
                )
        </insert>
        
    </mapper>

    위의 마이바티스 태그에서 mapper namespace=는 dao의 경로를 넣었고 resultType은 vo가 있는 패키지 경로를 넣어야 한다.

    parameterType=은 아이디만 받기 때문에 String형으로 정의 하였다.

    + 추가로 회원가입을 위해 join.xml을 새로 만들고 SQL을 작성한다. (join.xml)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    <?xml version="1.0" encoding="UTF-8"?>
     
     
     
        <insert id="setInsertMember" parameterType="com.devmk.test.vo.Member">
            /*회원 가입*/
            INSERT INTO SECURITY_MEMBER
                (
                    SEQ /* 테이블 키 */
                    , ID /* 아이디 */
                    , PASSWORD /* 비밀번호 */
                    , MEMBER_NAME /* 이름 */
                    , USER_ROLE /* 권한 */
                      , EMAIL /* 이메일 */ 
                    , PASSWORD_LOCK /* 비밀번호 틀린 횟수 */
                    , PASSWORD_CHG_DATE /* 비밀번호 변경일자 */
                    , REG_DATE /* 등록일 */
                    , MOD_DATE /* 수정일 */
                    , STATUS /* 회원상태 */
                )
            VALUES
                (
                    SEQ_SECURITY.nextval
                    , #{id}
                    , #{password}
                    , #{memberName}
                    , #{userRole}
                    , #{email}
                    , 0
                    , TO_CHAR(SYSDATE,'YYYYMMDDHH24MISS')
                    , TO_CHAR(SYSDATE,'YYYYMMDDHH24MISS')
                    , TO_CHAR(SYSDATE,'YYYYMMDDHH24MISS')
                    , 'O'
                )
        </insert>
     
    </mapper>

    7. Dao를 만들어준다. (Mapper라고도 한다;)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
     
     
     
     
    @Mapper
    public interface LoginMapper{
     
        //메소드 앞에 public 생략해도 기본적으로 public가 붙는다.
        
        /* 회원정보조회 */
        Member getSelectMeberInfo(String id);
        /* 회원가입 */
        public int setInsertMember(Member member);
        /* 로그인 로그 */
        public int setInsertLoginLog(LoginLog loginLog);
        /* 비밀번호 틀린 횟수 증 */
        public int setUpdatePasswordLockCnt(String id);
        /* 비밀번호 틀린횟수 초기화 */
        public int setUpdatePasswordLockCntReset(String id);
         
    }
     

    이 Dao안에 로그인에 필요한 CRUD를 넣으면 된다. 회원정보가 조회되어야 하기 때문에 리턴타입은 Member vo다.

    이번 포스팅은 기본적인 프로젝트 셋팅, 테이블 생성 , VO, DAO를 작성하였다.

    다음 포스팅은 스프링시큐리티에서 제공하는  UserDetailsService 인터페이스를 상속받아서 실제 인증하는 작업을 해보겠다~

     

    반응형

    댓글

Designed by Tistory.