Spring legacy

Spring Security - 기존 테이블을 이용하는 인증방법

voider 2020. 9. 13. 19:33

기존의 테이블을 이용한 시큐리티 인증 방법

1. 테이블 설계

회원 테이블과 권한 테이블

-- 회원 테이블
create table tbl_member(
    userid varchar(50) not null primary key,
        userpw varchar(100) not null,
    username varchar(100) not null,
    regdate timestamp default now(),
    moddate timestamp default now(),
    enabled char(1) default '1'
);


-- 권한 테이블
create table tbl_member_auth(
    userid varchar(50) not null,
    auth varchar(50) not null,
        constraint fk_member_auth foreign key (userid) references tbl_member(userid)
);

2. BCryptPasswordEncoder를 이용한 패스워드 보호

BCrypetPasswordEncdoer는 해시 함수로 문자열을 암호화한다. 체크하는 쪽에서는 암호화된 패스워드가 가능한 패스워드인지만 확인하고 다시 원문으로 돌릴 수 없다.

3.security-context.xml

...생략
    <security:authentication-manager>
        <security:authentication-provider>

            <security:jdbc-user-service data-source-ref="dataSource"/>
            <security:password-encoder ref="bcryptPasswordEncoder"/>

        </security:authentication-provider>
    </security:authentication-manager>

#. 4 TEST

    @Autowired
    private PasswordEncoder pwEncoder;

    @Autowired
    private DataSource dataSource;

    @Test
    public void testInsertMember() {
        String sql = "INSERT INTO tbl_member(userid, userpw, username)"
                + "values(?,?,?)";

        for (int i=0; i < 30; i++) {

            try (    Connection conn = dataSource.getConnection();
                    PreparedStatement pstmt= conn.prepareStatement(sql);
                    ){
                //모든 비밀번호는 1234
                pstmt.setString(2, pwEncoder.encode("1234"));

                if(i < 10) {
                    pstmt.setString(1, "user"+i);
                    pstmt.setString(3, "사용자"+i);
                } else if(i < 20) {
                    pstmt.setString(1, "manager"+i);
                    pstmt.setString(3, "매니저"+i);
                } else if(i<30) {
                    pstmt.setString(1, "admin"+i);
                    pstmt.setString(3, "관리자"+i);
                }

                int result = pstmt.executeUpdate();

                log.info("result : " + result);

                assertTrue(result == 1);

            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

tbl_member조회

권한 부여

    //권한 부여
    @Test
    public void testInsertAuth() {

        String sql = "INSERT INTO tbl_member_auth(userid, auth)"
                +"VALUES(?,?)";
        for (int i=0; i < 30; i++) {

            try (    Connection conn = dataSource.getConnection();
                    PreparedStatement pstmt= conn.prepareStatement(sql);
                    ){

                if(i < 10) { //유저 권한
                    pstmt.setString(1, "user"+i);
                    pstmt.setString(2, "ROLE_USER");
                } else if(i < 20) {    //매니저 권한
                    pstmt.setString(1, "manager"+i);
                    pstmt.setString(2, "ROLE_MANAGER");
                } else if(i<30) {    //관리자 권한
                    pstmt.setString(1, "admin"+i);
                    pstmt.setString(2, "ROLE_ADMIN");
                }

                int result = pstmt.executeUpdate();

                log.info("result : " + result);

                assertTrue(result == 1);

            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

tbl_member_auth 조회

쿼리를 이용하는 인증 방식

지정된 방식(JDBC를 이용한 인증)이 아닌, 테이블 구조를 이용하는 경우, 인증 쿼리(users-by-username-query)와 권한을 확인하는 쿼리(authorities-by-username-query)를 이용해서 처리한다.

-- 인증 쿼리
SELECT userid, userpw as password, enabled
FROM tbl_member
WHERE userid='아이디';

-- 권한을 확인하는 쿼리
SELECT userid as username, auth as authority
FROM tbl_member_auth
WHERE userid = '아이디';

위의 쿼리를 PrepareStatement에서 사용하는 구문으로 바꾼다. (WHERE userid=?)

security-context.xml

<security:authentication-manager>
    <security:authentication-provider>
        <security:jdbc-user-service data-source-ref="dataSource"
            users-by-username-query=
            "SELECT userid, userpw as password, enabled
            FROM tbl_member
            WHERE userid = ? "
            authorities-by-username-query=
            "SELECT userid as username, auth as authority
            FROM tbl_member_auth
            WHERE userid = ? " />

        <security:password-encoder ref="bcryptPasswordEncoder"/>
    </security:authentication-provider>
</security:authentication-manager>

이제 member테이블에 있는 계정으로 로그인 시,
각 계정이 가진 권한으로 열람할 수 있는 페이지에 접속할 수 있다.