티스토리 뷰

728x90

1. 이젠 xml 설정 같은 건 사용하지 않는다.

 

Spring WebMVC with Java Config(no XML)

2. web.xml을 사용하지 않으려면 maven pom에 maven-war-plugin이 있어야 한다.

  2-1 org.apache.maven.archetype webapp 1.4를 사용하면 기본적으로 포함되어 있어 설정이 불필요하다.

  2-2 지난 번에도 언급했지만 .settings 폴더의 xml파일에 sevlet 버전을 servlet버전과 맞추는 건 필요하다.

 

3. Web MVC에 Java Config 사용하기

  3-1 Spring Dispatcher Servlet Initializer는 web.xml의 기능을 대체한다.

    3-1-1 스프링의 Web MVC 초기화를 위한 클래스이다.

    3-1-2 이 클래스는 자동적으로 spring에서 로딩되고

    3-1-3 servlet container를 초기화하기 위해 @Configuration이 설정된 클래스를 지정하여 사용한다. 

    3-1-4 AbstractAnnotationConfigDispatcherServletInitializer 클래스를 확장해서 정의하는 것으로 충분하다.

 

// 이 클래스는 web.xml을 대체하는 기능을 가진다.
package pe.pilseong.springsecurity.config;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

// 이름이 존나 길다. 추상 클래스를 상속하면 자동으로 Spring이 읽어서 기동한다.
public class SpringMvcAnnotationConfigDispatcherServletInitializer
    extends AbstractAnnotationConfigDispatcherServletInitializer {

  @Override
  protected Class<?>[] getRootConfigClasses() {
    return null;
  }

// bean 설정과 spring container 설정을 위한 Config 클래스를 등록한다.
// Config 클래스는 web.xml의 dispatcher servlet 초기화에 사용된 xml과 같은 기능을 한다.
  @Override
  protected Class<?>[] getServletConfigClasses() {
    return new Class[] { WebConfig.class };
  }

// web.xml의 servlet mapping 부분을 대체한다.
  @Override
  protected String[] getServletMappings() {
    return new String[] { "/" };
  }
}

 

    3-1-5 위의 Java Config과 비교를 위한 web.xml 주요 부분

 

// 위의 servlet dispatcher initalizer와 비교를 위해 붙인다.

// web.xml의 dispatcher servlet을 초기화 하는 부분이다.
<servlet>
  <servlet-name>dispatcher</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  <init-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring-security-servlet.xml</param-value>
  </init-param>
  <load-on-startup>1</load-on-startup>
</servlet>

// web.xml의 servlet mapping 부분이다.
<servlet-mapping>
  <servlet-name>dispatcher</servlet-name>
  <url-pattern>/</url-pattern>
</servlet-mapping>

 

  3-2 @Configuration을 수식한 설정 클래스를 사용하여 기존 servlet container 설정 xml 파일을 대체한다.

    3-2-1 위의 web.xml 경우 servlet container 설정 xml이름을 spring-security-servlet.xml 지정하였다.

 

package pe.pilseong.springsecurity.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "pe.pilseong.springsecurity")
public class WebConfig {

  @Bean
  public ViewResolver viewResolver() {
    InternalResourceViewResolver resolver = new InternalResourceViewResolver();
    
    resolver.setPrefix("/WEB-INF/view/");
    resolver.setSuffix(".jsp");
    
    return resolver;
  }
}

 

    3-2-2 비교를 위한 spring-security-servlet.xml 파일의 주요 부분

 

// @ComponentScan annotation이 대체하는 코드
<context:component-scan base-package="pe.pilseong.springsecurity" />

// @EnableWebMvc annotation이 대체하는 코드
<mvc:annotation-driven/>

// @bean annotation이 대체하는 코드
<bean
  class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  <property name="prefix" value="/WEB-INF/view/" />
  <property name="suffix" value=".jsp" />
</bean>

 

    3-2-2 @EnableWebMvc는 <mvn:annotation-driven>을 대체한다.

      3-2-2-1 conversion, formatting, validation을 지원한다.

      3-2-2-2 @Controller, @RequestMapping 등 annotation을 지원한다.

 


Spring Security 설정하기

-1. 스프링 Security의 핵심은 SecurityFilterChain이다.

  -1-1 스프링의 보안 정책의 단위는 FilterChain이고 여러개의 FilterChain을 등록할 수 있다.

  -1-2 FilterChain내에 여러개의 필터가 등록되어 순차적으로 보안정책을 적용한다.

  -1-3 아래는 인터넷에서 검색한 부분인데 출처 링크는 이미지 아래에 있다.

 

 

https://i1.wp.com/www.dineshonjava.com/wp-content/uploads/2017/02/Spring-Security-Filter-Configuration-1.jpg?resize=530%2C307&ssl=1

 

 

 

0. Spring Security를 사용하려면 2개의 dependency가 필요하다.

  0-1 spring-security-web

  0-2 spring-security-config

 

1. 스프링 Security를 사용할 때 주의할 점이 있다.

  1-1 스프링 Securitys는 다른 스프링 패키지와 별도의 프로젝트이다.

    1-1-2 따라서 별도의 release 주기를 가지고 버전도 별도로 설정된다. 

    1-1-3 핵심은 스프링 라이브러리와 스프링 Security라이브러리가 호환되지 않는 버전을 사용할 수 있다는 점이다.

    1-1-4 결국 호환되는 버전을 찾는 것이 중요하다.

 

  1-2 스프링 라이브러리와 호환되는 버전 찾기

    1-2-1 mvnrepository.com에 들어가서 spring security web을 검색한다.

    1-2-2 최신 버전을 선택하면 화면의 아래에 compile dependencies라는 부분이 있다.

    1-2-3 거기를 보면 다양한 스프링 라이브러리가 있는데 그곳에서 사용할 spring 버전을 확인하면 된다.

    1-2-4 아래는 security는 5.3.2 버전이고 spring core는 5.2.6 버전이다. 이렇게 확인가능하다.

 

 

 

 

2. Spring Web MVC에 Spring Security를 추가한 pom.xml은 다음과 같다.

  2-1 org.apache.maven.archetype webapp 1.4로 생성한 파일에 dependency와 properties만 수정한 파일이다.

 

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>pe.pilseong</groupId>
	<artifactId>springsecurity</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>

	<name>springsecurity Maven Webapp</name>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<maven.compiler.source>11</maven.compiler.source>
		<maven.compiler.target>11</maven.compiler.target>
		<springframework.version>5.2.6.RELEASE</springframework.version>
		<springsecurity.version>5.3.2.RELEASE</springsecurity.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.11</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${springframework.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${springframework.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${springframework.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-web</artifactId>
			<version>${springsecurity.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-config</artifactId>
			<version>${springsecurity.version}</version>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>javax.servlet.jsp-api</artifactId>
			<version>2.3.3</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>4.0.1</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<version>1.18.12</version>
			<scope>provided</scope>
		</dependency>
	</dependencies>

	<build>
		<finalName>springsecurity</finalName>
		<pluginManagement><!-- lock down plugins versions to avoid using Maven 
				defaults (may be moved to parent pom) -->
			<plugins>
				<plugin>
					<artifactId>maven-clean-plugin</artifactId>
					<version>3.1.0</version>
				</plugin>
				<!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
				<plugin>
					<artifactId>maven-resources-plugin</artifactId>
					<version>3.0.2</version>
				</plugin>
				<plugin>
					<artifactId>maven-compiler-plugin</artifactId>
					<version>3.8.0</version>
				</plugin>
				<plugin>
					<artifactId>maven-surefire-plugin</artifactId>
					<version>2.22.1</version>
				</plugin>
				<plugin>
					<artifactId>maven-war-plugin</artifactId>
					<version>3.2.2</version>
				</plugin>
				<plugin>
					<artifactId>maven-install-plugin</artifactId>
					<version>2.5.2</version>
				</plugin>
				<plugin>
					<artifactId>maven-deploy-plugin</artifactId>
					<version>2.8.2</version>
				</plugin>
			</plugins>
		</pluginManagement>
	</build>
</project>

 

3. 기본적인 Spring Security 설정은 다음과 같다.

  3-1 Spring Security는 스프링 Security를 초기화하기 위해 Security Web App Initializer를 제공한다.

    3-1-0 SpringWebAppInitializer는 DispatcherServletInitializer와 동일하게 servlet container 초기화에 사용된다.

    3-1-1 WebMvc의 DispatcherServlet Initializer 생성과 동일한 방식으로 정의한다.

    3-1-2 이 코드는 스프링 Security를 관리하는 Spring Security Filters를 등록하고 활성화 시킨다.

    3-1-3 생성할 클래스는 AbstractSecurityWebApplicationInitializer를 상속해야 한다.

    3-1-4 상속만 한 클래스 작성으로 충분하다. 세부적인 내용은 @Configuration 클래스에서 설정한다.

 

package pe.pilseong.springsecurity.config;

import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;

public class SpringSecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {

}

 

  3-2 @Configuration을 사용한 Spring Security Config파일 생성한다.

    3-2-1 WebMvc에서 JavaConfig를 생성한 것과 동일한 구조다.

    3-2-2 WebSecurityConfigurerAdapter를 상속해서 생성하는데

      3-2-2-1 Spring Security 설정에 필요한 WebSecurityConfigurer인터페이스를 기본적으로 구현한 클래스이다.

      3-2-2-2 따라서 필요한 부분만 Override하여 추가로 구현하면 편리하다.

 

  3-3 사용자, 비밀번호, role을 등록한다.

    3-3-1 아래 코드는 Spring Security가 정상동작하는지 확인하기 위해 간단한 in memory 인증을 사용한다.

    3-3-2 SecurityConfig에 user를 생성하고 role을 부여하는 간단한 코드이다.

    3-3-3 userdetails.User 의 withDefaultPasswordEncoder 메소드는 deprecated되었지만 간단한 예제라서 사용했다.

 

package pe.pilseong.springsecurity.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.User.UserBuilder;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
  
  @Override
  protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    UserBuilder users = User.withDefaultPasswordEncoder();
    
    auth.inMemoryAuthentication()
      .withUser(users.username("pilseong").password("pilseong").roles("EMPLOYEE"))
      .withUser(users.username("suel").password("suel").roles("MANAGER"))
      .withUser(users.username("noel").password("noel").roles("ADMIN"));
  }
}

 

    3-3-4 deprecated된 withDefaultPasswordEncoder()를 사용하기 싫으면 password 마다 {noop}을 붙이면 된다.

 

  @Override
  protected void configure(AuthenticationManagerBuilder auth) throws Exception {    
    auth.inMemoryAuthentication()
      .withUser(users.username("pilseong").password("{noop}pilseong").roles("EMPLOYEE"))
      .withUser(users.username("suel").password("{noop}suel").roles("MANAGER"))
      .withUser(users.username("noel").password("{noop}noel").roles("ADMIN"));
  }

 

 

4. 실행 화면

 

728x90
댓글