java, spring

[Spring] JDBC를 이용하는 간편 인증/권한 처리

isaac.kim 2021. 9. 30.
728x90
반응형

[Spring] JDBC를 이용하는 간편 인증/권한 처리

 

인증과 권한에 대한 처리는 Authentication Manager를 통해 처리됩니다. 이때 인증이나 권한 정보를 제공하는 존재(Provider)가 필요하고, 다시 이를 위해서 UserDetailsService라는 인터페이스를 구현한 존재를 활용하게 됩니다.

 

UserDetailsService는 스프링 시큐리티 API 내에 이미 CachingUserDetailsService, InMemoryUserDetailsManager, JdbcDaoImpl, JdbcUserDetailsManager, LdapUserDetailsManager, LdapUserDetailsService와 같은 구현 클래스들을 제공하고 있습니다.

 

security-context.xml에는 기존의 <security:user-service>는 jdbc-user-service로 변경할 것이고, jdbc-user-service는 기본적으로 DataSource가 필요하므로 root-context.xml에 있는 설정을 추가합니다.

 

JDBC를 이용하기 위한 테이블 설정

JDBC를 이용해 인증/권한을 체크하는 방식 두 가지 입니다.

 

1) 지정된 형식으로 테이블을 생성해 사용하는 방식

2) 기존에 작성된 DB를 이용하는 방식

 

 

//스프링 시큐리티가 JDBC를 이용하는 경우 사용하는 클래스는 JdbcUserDetailsManager 클래스입니다.

 

스프링 시큐리티에서 지정된 SQL을 사용한다면 지정된 형식으로 테이블을 생성해 주기만 하면 됩니다.

create table users (
	username varchar(50) not null primary key,
    password varchar(50) not null,
    enable char(1) default '1'
);

create table authorities (
	username varchar(50) not null,
    authority varchar(50) not null,
    constraint fk_authorities_users foreign key(username) references users(username)
);

// 권한(authority)에 ROLE_USER, ROLE_MANAGER, ROLE_ADMIN 값을 넣습니다.

 

테이블에 값을 넣었습니다.

 

왼쪽 users, 오른쪽 authorities

 

security-context.xml의 <security:authentication-manager> 내용은 다음과 같이 작성됩니다.

(root-context.xml에 'dataSource' 라는 이름의 빈(Bean)이 등록되어 있어야 합니다.)

 

security-context.xml

데이터베이스에 없는 계정으로 로그인을 시도해보면 오른쪽 이미지와 같이 계정확인 메시지가 나타납니다.

서버의 로그를 확인해보면 입력한 계정에 대해서 sql 처리 후 응답해줍니다.

제대로 값을 입력하면 해당 users 테이블을 조회하겠지만,

아쉽게도 패스워드가 평문으로 처리되었기 때문에 마지막 결과는 예외가 발생합니다.

PasswordEncoder 문제 해결

스프링 시큐리티 5부터는 기본적으로 PasswordEncoder를 지정해야만 합니다. 기존의 InMemoryUserDetailsmanager 이용한 고정 유저 정보를 사용한 예제에서는 임시로 '{noop}' 접두어를 이용해 잠시 피해서 진행되었지만, 데이터베이스 등을 이용하는 경우에는 PasswordEncoder라는 것을 이용해야만 합니다.

 

문제는 패스워드 인코딩을 처리하게 되면, 인코딩 작업이 추가되어야 하기 때문에 할 일이 많다는 점입니다. 스프링 시큐리티의 PasswordEncoder는 인터페이스로 설계되어 있고, 이미 여러 종류의 구현 클래스가 존재합니다.

 

com.project.security 패키지에 CustomNoOpPasswordEncoder 클래스를 생성합니다. 

 

CustomNoOpPasswordEncoder 클래스

PasswordEncoder 인터페이스에는 encode( )와 matches( ) 메서드가 존재하므로 위와 같이 직접 처리합니다.

 

security-context.xml에는 작성된 CustomNoOpPasswordEncoder 클래스를 빈으로 등록합니다.

 

security-context.xml의 일부 1

security-context.xml의 일부 2

WAS를 실행해서 로그인을 확인해보면 정상적으로 로그인 처리가 JDBC를 이용해서 처리되는 것을 볼 수 있습니다.


스프링 시큐리티와 시큐리티에서 사용하는 table 정보를 활용하여 간단하게 로그인하는 방법을 알아보았습니다.

728x90
반응형