스프링부트 스프링시큐리티 연동하기(1) Gradle/Mybatis/Oracle
스프링부트로 스프링시큐리티 연동하는 예제가 별로 없어서 포스팅을 하게 되었다. (일반 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.springframework.boot:spring-boot-starter-web'
providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
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 */
compile 'com.oracle:ojdbc6:11.2.0.3'
/*mybais*/
/* log */
compile group: 'org.bgee.log4jdbc-log4j2', name: 'log4jdbc-log4j2-jdbc4', version: '1.16' /* sql easy 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
|
package com.devmk.test.vo;
import java.util.Collection;
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
|
package com.devmk.test.vo;
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"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
/* 회원정보조회 */
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 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"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
/*회원 가입*/
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
|
package com.devmk.test.login.dao;
import java.util.List;
import java.util.Map;
import com.devmk.test.vo.LoginLog;
import com.devmk.test.vo.Member;
@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 인터페이스를 상속받아서 실제 인증하는 작업을 해보겠다~