Spring-웹 애플리케이션 개발

업데이트:

스프링 시큐리티

스프링 시큐리티 활성화 하기

스프링 애플리케이션의 보안에서 맨 먼저 할 일은스프링 부트 보안 스타터 의존성을 빌드 명세에 추가하는것이다.

보안 스터타를 프로젝트 빌드 파일에 추가만 했을때는 다음의 보안 구성이 제공된다.

  • 모든 HTTP 요청 겨로는 인증 되어야 한다.
  • 어떤 특정 역할이나 권환이 없다.
  • 로그인 페이지가 따로 없다.
  • 스프링 시큐리티의 HTTP 기본 인증을 사용해서 인증된다.
  • 사용자는 하나만 있으며, 이름은 user다. 비밀번호는 암호화해 준다.
스프링 시큐리티 구성하기

SecurityCOnfig 클래스 사용자의 HTTP 요청 경로에 대해 접근 제한과 같은 보안 관련 처리를 우리가 원하는 대로 할 수 있게 해준다.

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http
		.authorizeRequests()
		.antMatchers("/design", "/orders")
		.access("hasRole('ROLE_USER')")
		.antMatchers("/", "/**").access("permitAll")
		.and()
		.httpBasic();

	}
	@Override
	public void configure(AuthenticationManagerBuilder auth) throws Exception{
		auth.inMemoryAuthentication()
		.withUser("user1")
		.password("{noop}password1")
		.authorities("ROLE_USER")
		.and()
		.withUser("user2")
		.password("{noop}password2")
		.authorities("ROLE_USER");
	}
}

한 명 이상의 사용자를 처리할 수 있도록 사용자 정보를 유지, 관리하는사용자 스토어를 구성해야 한다.
스프링 시큐리티에서는 여러가지 사용자 스토어 구성 방법을 제공한다.

  • 인메머리 사용자 스토어
  • JDBC 기반 사용자 스토어
  • LDAP 기반 사용자 스토어
  • 커스텀 사용자 명세 서비스

SecurityConfig 클래스는 보안 구성 클래스인 WebSecurity ConfigurerAdapter의 서브 클래스다.
두개의 configure() 메서드를 오버라라이딩을하고 있다.

  • configure(HttpSecurity) : HTTP 보안을 구성하는 메서드
  • configure(AuthenticationManagerbuilder) : 사용자 인증 정보를 구성하는 메서드
인메모리 사용자 스토어

사용자의 정보를 유지.관리할 수 잇는 곳중 하난가 메모리다. 만일 변경이 필요 없는 사용자만 미리 정해 놓고 애플리케이션을 사용한다면 아예 보안 구성 코드 내부에 정의할 수 있다.

user1과 user2라는 사용자를 인메모리 사용자 스토어에 구성하는 방법이다.

	@Override
	public void configure(AuthenticationManagerBuilder auth) throws Exception{
		auth.inMemoryAuthentication()
		.withUser("user1")
		.password("{noop}password1")
		.authorities("ROLE_USER")
		.and()
		.withUser("user2")
		.password("{noop}password2")
		.authorities("ROLE_USER");
	}

withUser()를 호출하면 해당 사용자의 구성이 시작되며, 사용자 이름을 인자로 전달한다.
반면에 비밀번호와 부여 권한은 각각 password()와 authorities() 메서드의 인자로 전달하여 호출한다.

  • 스프링 5 부터는 반드시 비밀번호를 암호화 해야 하므로 password() 메서드를 호출하여 암호화 하지 않으면 403, 500 이 발생한다.
  • 위 예제는 {noop}를 지정하여 비밀번호를 암호화 하지 않았다.
JDBC 기반의 사용자 스토어

사용자 정보눈 관계형 데이터베이스로 유지.관리되는 경우가 많으므로 JDBC 기반의 사용자 스토어가 적합해 보인다.

JDBC 기반의사용자 스토어로 인증하기
@Autowired로 DataSource가 자동으로 주입된다.

@Autowired
DataSource dataSource;

@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception{    
	auth
	.jdbcAuthentication()
	.dataSource(dataSource);
}

스프링 시큐리티의 것과 다른 데이터베이스(테이블이나 열의 이름이 다를때)를 사용한다면, 스프링 시큐리티의 SQL 쿼리를 우리의 SQL 쿼리로 대체할 수 있다.

@Autowired
DataSource dataSource;

@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception{    
	auth
	.jdbcAuthentication()
	.dataSource(dataSource)usersByUsernameQuery(
			"select username, password, enabled from users " +
			"where username=?")
		.authoritiesByUsernameQuery(
			"select username, authority from authorities " +
			"where username=?");
}

위 쿼리에서 사용하는 테이블의 이름은 스프링 시큐리티의 기본 데이터베이스 테이블과 달라도 된다(위에는 동일함).
그러나 테이블이 갖는 열의 데이터 타입과 길이는 일치해야하고 다음 사항을 지켜야 한다.

  • 매개변수(where절에 사용)는 하나이며, username이어야 한다.
  • 사용자 정보 인증 쿼리에서는 username, password, enabled 열의 값을 반환해야 한다.

암호화된 비밀번호 사용
비밀번호를암호화 할때는 passwordencoder() 메서드를호출하여 비밀번호 인코더를 지정한다.

@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception{    
	auth
	.jdbcAuthentication()
	.dataSource(dataSource)usersByUsernameQuery(
			"select username, password, enabled from users " +
			"where username=?")
		.authoritiesByUsernameQuery(
			"select username, authority from authorities " +
			"where username=?")
		.passwordEncoder(new BCryptPasswordEncoder());
}

passwordencoder() 메서드는 스플이 시큐리티의 PasswordEncoder 인터페이스를 구현하는 어떤 객체도 인자로 받을 수있다.
암호화 알고리즘을 구현한 스프링 시큐리티의 모듈에는 다음과 같은 구현 클래스가 포함되어 있다.

  • BCryptPasswordEncoder : bcrypt를 해싱 암호화 한다.
  • NoOpPasswordEncoder: 암호화 하지 않는다.
  • Pbkdf2PasswordEncoder : PBKDF2를 암호화 한다.
  • SCryptPasswordEncoder : scrypt를 해싱 암호화 한다.
  • standardPasswordEncoder : SHA-256을 해싱 암호화한다.

댓글남기기