프로그래밍/Spring Framework

스프링 시큐리티를 이용한 보안 - 1부 인증

모지사바하 2015. 4. 22. 18:35


현재 맡고 있는 프로젝트의 Rest Api 가 보안이 전혀 돼 있지 않아서,


보안을 강화하는 작업을 시작했다.


보안이 전혀 돼 있지 않기 때문에, 사용자 아이디/비밀번호 정보가 없어도, 


Rest Api 를 호출하면 비밀정보를 쉽게 볼 수 있는 상황이였다.



보안을 위해 Spring Security 를 적용하였다.


보안 적용을 하면서 Spring Security 에 대해서 좀 더 자세히 알게 되었고, 그 내용에 대해 포스팅 하고자 한다





위 사진은 웹 기반 인증 요청을 처리하는 기본 프로세스이다.


굉장히 이해하기 쉽게 잘 도식화돼있고, 스프링 시큐리티 인증 처리의 기본 동장 방식 이기 때문에,


스프링 시큐리티를 이해하려면 반드시 위 인증 처리 과정을 이해하고 있는 것이 좋다.


설명에 앞서, 설정 파일을 JAVA CONFIG 로 구성하였음을 미리 알려둔다.


1) 인증요청에 해당하는 URL 을 감지하면,


최초로 AbstractAuthenticationProcessingFilter 를 구현한 클래스가 요청을 가로챈다.



JAVA CONFIG 에서는 

protected void configure(HttpSecurity http) throws Exception 메소드를 오버라이드하여 http 전반적인 보안정책을 설정하는데,


http.formLogin() 을 이용하면 기본적으로 AbstractAuthenticationProcessingFilter 를 구현한 UsernamePasswordAuthenticationFilter 를 이용하게 된다.


2) UsernamePasswordAuthenticationFilter 에서는 인증(로그인) 요청에 대해서 기본적으로 GET PARAMETER 로 인증 정보가 들어오는 것을 허용하지 않고 있다.Http Method 를 POST 만 지원하도록 되어있다. 


REQUEST 로 들어온 USRNAME 과 PASSWORD 에 해당하는 파라미터의 정보를 UsernamePasswordAuthenticationToken 에 담는다. 이 토큰은 그냥 사용자명 과 비밀번호를 담는 단순 도메인객체이다.


3) UsernamePasswordAuthenticationFilter가 주입 받은 AuthenticationManager 의 authenticate 메소드를 호출한다. 이때, 인자로 UsernamePasswordAuthenticationToken를 준다.


 AuthenticationManager 는 인터페이스 이며 이 인터페이스를 구현한 ProviderManager 를 기본으로 사용한다.


4) AuthenticationManager는 사용자명/비밀번호를 실질적으로 인증한다.


JAVA CONFIG 에서는 protected void configure(HttpSecurity http) throws Exception 메소드와 별개로 AuthenticationManager 에 대한 설정을 해줘야한다.


왜냐하면, protected void configure(HttpSecurity http) throws Exception 메소드는 어떤 url 은 어떤 권한을 가진 사용자에게 어떤 url 을 인가 해줄지, 어떤 url 을 로그인으로 인식하고 감지할지 등, 권한에 대한 인가 정책을 설정하는 곧이고,


AuthenticationManager는 실제 사용자명/비밀번호를 인증작업을 위한 설정이다. 



JAVA CONFIG에서는 

@Autowired 

public void configureGlobal(AuthenticationManagerBuilder auth) 로 설정한다.

여기서 @Autowired 는 configureGlobal 내의 AuthenticationManagerBuilder 인자를 주입받겠다는 것이다.



auth 를 이용하여 AuthenticationManager 를 설정하면 된다.

AuthenticationManager 는 AuthenticationManager에 연결된 Provider 를 이용하여 인증 작업을 진행한다.


보통 일반적으로 데이터베이스에 저장된 사용자 정보로 인증을 많이 한다.


이때, auth.UserDetailsService(userDetailsService) 를 이용하면, 


자동으로 AuthenticationManager에 DaoAuthenticationProvider 가 연결된다.


DaoAuthenticationProvider 는 이름에서도 알수 있듯이 데이터베이스 인증 용 Provider 이다.


DaoAuthenticationProvider를 설정할 때, 위에서 적혀있듯이 인자로 userDetailsService 를 받는다.


UserDetailsService 로 username 을 이용하여 사용자 정보를 디비에서 조회하고, UserDetails 객체를 리턴한다.


5) DaoAuthenticationProvider 는 

protected void additionalAuthenticationChecks(UserDetails userDetails,

UsernamePasswordAuthenticationToken authentication)

throws AuthenticationException


위 메소드를 이용하여 검증을 진행하는데 위 메소드는 ProviderManager 의 authenticate 메소드 내부에서 Provider 의 authenticate를 호출해주고 DaoAuthenticationProvider의 상위 클래스인 AbstractUserDetailsAuthenticationProvider에서 additionalAuthenticationChecks 를 호출한다.


아무튼,


additionalAuthenticationChecks메소드는 UserDetails와 UsernamePasswordAuthenticationToken을 인자로 받는데, UserDetails 는 UserDetailsService 에서 디비 조회후, 결과값이고,


UsernamePasswordAuthenticationToken 은 로그인 폼에서 넘긴 사용자가 입력한 유저 아이디와 비밀번호이다.


additionalAuthenticationChecks 메소드 내부에서 UserDetails 내용과 UsernamePasswordAuthenticationToken 의 내용을 비교하고, 값이 동일하다면 인증 성공이다.


글로 풀어쓰려니, 복잡한 느낌도 없지않아 있는데, 사실 위 사진이 아주 간략하고, 정확하게 이 과정을 도식화 한 것이다.



인증 성공 후에는 또다시 protected void configure(HttpSecurity http) throws Exception 에서 설정한 사용자 권한 및 요청 url 에 따른 인가 정책에 따라 또 다른 작업이 수행된다. 



사실, 이 포스팅을 한 이유는 REST API 인증/보안에 대해 작성하려고 하였는데, 


REST API 인증/보안을 하기 위해선 FILTER , PROVIDER , TOKEN 을 사용자가 새롭게 구현하여야한다.


그러기 위해서 인증의 기본 절차에 대한 포스팅을 한 것이고,



다음 포스팅에서는, 


REST API를 위한 Filter, Provider, Token 커스텀 구현에 대하여 작성하겠다.