Spring MVC

springmvc.egloos.com


포토로그


2012/03/03 08:29

5장 스프링 시큐리티에서의 비밀번호 암호화 Spring Security

만약 당신이 만들고 있는 웹사이트가 영리를 목적으로 하고 있다면 반드시 비밀번호를 암호화해야 한다. 비단 비밀번호에만 해당하는 것은 아니지만 고객의 중요정보를 암호화하지 않는 기업은 사용자의 정보를 크래커들에게 무단으로 제공하려는 기업이나 다름이 없다. 현대의 발달된 IT기술에는 이런 악의적인 공격자들을 방어하는 많은 암호화 기술들이 있으며 스프링 시큐리티에도 대략 4가지 정도의 기본 암호화 클래스를 제공하고 있다.


암호화에 있어서 개발자들이 지켜야할 규칙들이 몇가지 있다.

1. 복호화(디코딩)가 불가능한 단방향 암호코드로 만들어져야 한다.
2. 암호는 개발자나 관리자도 알 수 없어야 하며 이용자 이외에는 누구도 접근할 수 없는 형태여야 한다.
3. 공격자가 예측할 수 없도록 솔트 처리를 해주어야 한다.

이러한 규칙은 개발자들이 반드시 준수해야 할 사항이며 비영리의 목적이라 하더라도 사용자의 개인정보는 영리 웹사이트와 똑같은 가치가 있으므로 암호화를 게을리 해선 안된다.


데이터베이스에서 제공하는 암호화

많은 개발자들이 데이터베이스에서 제공하는 간단한 암호화 기술을 이용하고 있으며 필자가 사용하는 MySql에서는 CRC32(), MD4~5(), SHA(), password()와 같은 암호화 함수들이 제공되고 있다. 근데 곰곰히 생각해보면 데이터베이스에서 제공하는 암호화 함수로 사용자의 정보를 암호화 해도 되는 것인지는 조금 생각해볼 여지가 있다.

select sha('비밀번호');

당신 회사의 수석 프로그래머가 보다 빠른 개발을 위해 따로 암호화 단계를 자바에서 생략하고 위와 쿼리문을 통해 MySQL에서 제공하는 암호화 함수를 이용한다고 생각해보자. 이런 방식이라면 암호화가 매우 간편하고 사용이 용이해진다는 장점을 얻을 수 있지만 극명하게 드러나는 단점은 당신이 스프링을 이용함으로써 얻는 개방 폐쇄 원칙(Open-Close Principle)을 철저히 파괴한다는 점이다.

만약 이런 방식으로 비밀번호를 암호화하여 서비스 개발을 완료한 뒤 당신의 서비스가 매우 성공적인 성과를 올렸다 생각해보자. 자사는 서비스의 확장을 꾀하고 있으며 곧 비싸고 기술지원 서비스까지 해주는 유료 소프트웨어들을 도입하고자 한다. 그 중에는 10g과 같은 오라클 데이터베이스도 포함되어 있다.

만약 이러한 상황이 닥친다면 당신이 사전에 구현해 놓은 서비스는 매우 치명적인 단점을 지니게 된다. 왜냐하면 데이터 이전 중에 가장 중요한 비밀번호를 MySQL에서 암호화하였으므로 오라클에서는 이 암호화된 비밀번호를 풀 수 없게 되기 때문이다. 더욱이 서로 다른 형태의 데이터베이스를 이용하고 있다면 당신은 매우 복잡한 로직으로 서로 다른 데이터베이스에서 다른 암호화 방식을 사용하게끔 설계해야만 할 것이다.

그러므로 당신이 OCP의 원칙에 따라 설계하고자 한다면 데이터베이스의 암호화 기능에 크게 의존하는 방식을 택해서는 절대로 안될 것이다. 데이터베이스의 기능을 의존하더라도 모든 데이터베이스에서 지원하는 공통요소를 이용해야지 특정 데이터베이스에서 제공하는 서비스를 이용했다간 본의 아니게 서비스 확장에 큰 장애를 만들게 될지도 모른다.

물론 많은 중소 웹사이트들이 위와 같이 데이터베이스 단계에서 암호화를 많이 활용하고 있다. 그 이유는 우리가 일전에 트랜잭션을 설명하면서 했던 것과 동일하게 코드 상의 복잡함을 줄이기 위한 불가피한 선택이었을 것이다. 허나 스프링 시큐리티를 이용한다면 이런 복잡한 암호화 단계를 개발영역으로 끌어들임과 동시에 코드 상의 복잡함도 대부분 축소할 수 있게 된다. 더욱이 스프링 시큐리티는 암호화 클래스를 빈으로 설정한 뒤 따로 주입받아 사용하기 때문에 기능의 확장에 있어서도 매우 자유롭다.

<authentication-manager>
<authentication-provider user-service-ref="securityService">
<password-encoder ref="passwordEncoder" />
</authentication-provider>
</authentication-manager>

<beans:bean id="passwordEncoder" class="org.springframework.security.authentication.encoding.ShaPasswordEncoder" />

securityService는 우리가 전장에서 만들었던 CrcJdbcDaoImpl 클래스를 주입한 것이며 스프링 시큐리티에서 기본으로 제공하는 Sha 인코더로 텍스트를 인코딩해보자. 먼저 패스워드를 인코딩하는 빈을 설정하고 위와 같이 <password-encoder> 요소에 주입시키면 앞으로 로그인 시에 시큐리티 필터가 자동으로 해당 패스워드를 암호화하여 서버로 전송시킬 것이다.

물론 여기서 끝이 아니다. 지금과 같은 상황이라면 저장 시에는 일반 텍스트로 저장되고 로그인 시에는 인코딩한 패스워드가 비교되므로 기능이 정상적으로 작동하지 않는다. 제대로 기능을 동작시키려면 우리가 암호화한 코드를 전송시킨 것과 똑같이 DB에 입력할 비밀번호도 같은 빈으로 암호화시켜 저장시켜야만 한다.

여기서 비밀번호를 저장시키는 클래스는 사용자가 직접 작성한 코드 일수도 있고 시큐리티에서 제공하는 JdbcUserDetailsManager 클래스일 수도 있다. 여하튼 방식은 동일하게 위의 passwordEncoder 빈을 주입받아 다음과 같은 메서드로 인코딩한 값을 저장시켜주면 된다.

@Autowired PasswordEncoder passwordEncoder;

passwordEncoder.encodePassword("패스워드", null);



핑백

  • 스프링 시큐리티 | StyleWear 2015-12-06 12:55:18 #

    ... &#8211; http://springmvc.egloos.com/518902 2012/03/03 08:29 5장 스프링 시큐리티에서의 비밀번호 암호화 만약 당신이 만들고 있는 웹사이트가 영리를 목적으로 하고 있다면 반드시 비밀번호를 암호화해야 한다. 비단 비밀번호 ... more