스프링 5부터는 반드시 비밀번호를 암호화해야 하므로 만일 password() 메서드를 호출하여 암호화하지 않으면 접근 거부(HTTP 403) 또는 Internal Server Error(HTTP 500)가 발생된다.
JDBC 기반의 사용자 스토어
사용자 정보는 관계형 데이터베이스로 유지,관리되는 경우가 많으므로 JDBC 기반의 사용자 스토어가 적합해 보인다.
@Overrideprotectedvoidconfigure(AuthenticationManagerBuilder auth) throws Exception { auth.jdbcAuthentication().dataSource(dataSource).usersByUsernameQuery("select username, password, enabled from Users "+"where username=?").authoritiesByUsernameQuery("select username, authority from UserAuthorities "+"where username=?").passwordEncoder(newStandardPasswordEncoder("53cr3t");}
usersByUsernameQuery()와 authoriesByUsernameQuery() 메서드를 사용하여 사용자 정보와 권한 쿼리를 대체하였다. passwordEncoder() 메서드는 스프링 시큐리티의 PasswordEncoder 인터페이스를 구현하는 어떤 객체도 인자로 받을 수 있다. 암호화 알고리즘을 구현한 스프링 시큐리티의 모듈에는 다음과 같은 구현 클래스가 포함되어 있다.
BCryptPasswordEncoder : bcrypt를 해싱 암호화한다.
NoOpPasswordEncoder : 암호화하지 않는다.
Pbkd2PasswordEncoder : PBKDF2를 암호화한다.
SCryptPasswordEncoder : scrypt를 해싱 암호화한다.
StandardPasswordEncoder : SHA-256을 해싱 암호화한다.
만약에 암호화 알고리즘을 커스터마이징 하고 싶다면 PasswordEncoder 인터페이스를 직접 구현 하면 된다.
LDAP의 기본 인증 전략은 사용자가 직접 LDAP 서버에서 인증받도록 하는 것이다. 그러나 비밀번호를 비교하는 방법도 있다. 이 방법에서는 입력된 비밀번호를 LDAP 디렉터리에 전송한 후, 이 비밀번호를 사용자의 비밀번호 속성 값과 비교하도록 LDAP 서버에 요청한다.
여기서는 전달된 비밀번호롸 userPasscode 속성 값이 비교되어야 한다는 것을 지정하였으며 비밀번호를 암호화하는 인코더도 지정하였다.
이처럼 서버 측에서 비밀번호가 비교될 때는 실제 비밀번호가 서버에 유지된다는 것이 장점이다. 그러나 비교되는 비밀번호는 여전히 LDAP 서버에 전달되어야하므로 해커가 가로챌 수 있다. 따라서 이것을 방지하기 위해 passwordEncoder() 메서드를 호출하여 암호화에 사용할 인코더를 지정할 수 있다.
LDAP 기반 사용자 스토어
LDAP 기반 인증으로 스프링 시큐리티를 고성하기 위해서 ldapAuthentication() 메서드를 사용할 수 있다.
authorizeRequests()는 ExpressionInterceptUrlRegistry 객체를 반환한다. 이 객체를 사용하면 URL 경로와 패턴 및 해당 경로의 보안 요구사항을 구성할 수 있다. 여기서는 두 가지 보안 규칙을 지정하였다.
/design과 /orders의 요청은 ROLE_USER의 권한을 갖는 사용자에게만 허용된다.
이외의 모든 요청은 모든 사용자에게 허용된다.
hasRole()과 permitAll()은 요청 경로의 보안 요구를 선언하는 메서드다. 이때 사용 가능한 메서드는 다음과 같다.
요청 경로가 보안 처리되는 방법을 정의하는 구성 메서드
대부분의 메서드는 요청 처리의 기본적인 보안 규칙을 제공한다. 그러나 각 메서드에 정의된 보안 규칙만 사용된다는 제약이 있다. 따라서 이의 대안으로 access() 메서드를 사용하면 더 풍부한 보안 규칙을 선언하기 위해 SpEl을 사용할 수 있다.
스프링 시큐리티에서 확장된 SpEL
CSRF 공격 방어하기
CSRF는 많이 알려진 보안 공격이다. 즉, 사용자가 웹사이트에 로그인한 상태에서 악의적인 코드가 삽입된 페이지를 열면 공격 대상이 되는 웹사이트에 자동으로 폼이 제출되고 이 사이트는 위조된 공격 명령이 믿을 수 있는 사용자로부터 제출된 것으로 판단하게 되어 공격에 노출된다.