본문 바로가기
Dev/Spring Boot

[스프링 부트 개념과 활용] 스프링 시큐리티 1부

by dev_jsk 2020. 8. 31.
728x90
반응형

Spring Security

스프링 시큐리티는 스프링 기반의 어플리케이션의 보안(인증과 권한)을 담당하는 프레임워크

보안관련 용어

  • 접근 주체 (Principal) : 보호된 리소스에 접근하는 대상
  • 인증 (Authentication) : 보호된 리소스에 접근한 대상에 대해 이 유저가 누구인지, Application의 작업을 수행해도 되는지 확인하는 과정
  • 인가 (Authorize) : 해당 리소스에 대해 접근 가능한 권한을 가지고 있는지 확인하는 과정 (After Authentication)
  • 권한 : 인증된 주체가 Application의 동작을 수행할 수 있도록 허락되어있는지를 결정
    • 권한 승인이 필요한 부분으로 접근하려면 인증 과정을 통해 주체가 증명 되어야만 한다
    • 권한 부여에도 두가지 영역이 존재하는데 웹 요청 권한, 메소드 호출 및 도메인 인스턴스에 대한 접근 권한 부여

참고

https://spring.io/projects/spring-security

 

Spring Security

Spring Security is a framework that focuses on providing both authentication and authorization to Java applications. Like all Spring projects, the real power of Spring Security is found in how easily it can be extended to meet custom requirements

spring.io

기본 예제

1. 의존성 추가

// pom.xml

<!-- thymeleaf -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

<!-- spring security -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

2. HomeController 생성

// HomeController.java

@Controller
public class HomeController {
    @GetMapping(value="/hello")
    public String hello() {
        return "hello";
    }

    @GetMapping(value="/my")
    public String my() {
        return "my";
    }
}

* Controller가 다른 로직 없이 View Name만 리턴해주는 용도 일 경우엔 View Controller를 등록하여 사용할 수 있다.

// WebConfig.java

@Configuration
public class WebConfig implements WebMvcConfigurer {
    // 로직 없이 View 로만 보낼경우 사용
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/helloView").setViewName("hello");
    }
}

3. 페이지 생성

// index.html

<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8'>
    <title>Page Title</title>
</head>
<body>
    <h1>Welcome</h1>
    <a href="/hello">hello</a>
    <a href="/my">my page</a>
</body>
</html>

// hello.html

<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8'>
    <title>Page Title</title>
</head>
<body>
    <h1>Hello</h1>
</body>
</html>

// my.html

<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8'>
    <title>Page Title</title>
</head>
<body>
    <h1>My</h1>
</body>
</html>

4. HomeControllerTest 생성

// HomeControllerTest

@RunWith(SpringRunner.class)
@WebMvcTest(HomeController.class)
public class HomeControllerTest {
    @Autowired
    MockMvc mockMvc;

    @Test
    public void hello() throws Exception {
        mockMvc.perform(MockMvcRequestBuilders.get("/hello").accept(MediaType.TEXT_HTML))
            .andDo(MockMvcResultHandlers.print())
            .andExpect(MockMvcResultMatchers.status().isOk())
            .andExpect(MockMvcResultMatchers.view().name("hello"))
        ;
    }

    @Test
    public void my() throws Exception {
        mockMvc.perform(MockMvcRequestBuilders.get("/my"))
            .andDo(MockMvcResultHandlers.print())
            .andExpect(MockMvcResultMatchers.status().isOk())
            .andExpect(MockMvcResultMatchers.view().name("my"))
        ;
    }
}

결과 확인

스프링 시큐리티가 적용되어 있어 로그인 페이지가 나타나고, 로그인 이후 모든 페이지 접근이 가능하다.

ID : user, PW는 App 구동 시 매번 생성되어 Console에 출력

스프링 부트 시큐리티 자동 설정

SecurityAutoConfiguration : DefaultAuthenticationEventPublisher가 등록되어있음(비밀번호 오류, 유저 미존재, 계정 만료 등등)

UserDetailsServiceAutoConfiguration : Spring Boot App 구동 시 User 객체 하나를 inMemoryUserDetailsManager를 만들어 제공

 

시큐리티 자동 설정 모방하기

WebSecurityConfig 생성 하여 기존 자동 설정을 사용하는 것과 동일한 결과를 나타낸다.

// WebSecurityConfig.java

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
}

결국 동일한 결과를 나타내기 때문에 스프링 부트가 스프링 시큐리티 관련해서 해주는 것이 거의 없다고 보면 되고, inMemoryUserDetailsManager를 이용해 User객체 하나 만드는 것 하나 정도만 수행한다.

하지만 그마저도 스프링 시큐리티를 적용하는 프로젝트들은 프로젝트만의 UserDetailsService를 등록하게 되어있어 사실상 사용하는 것이 없다고 보면 된다.

 

테스트 오류 해결하기

1. 의존성 추가

// pom.xml

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-test</artifactId>
    <version>${spring-security.version}</version>
    <scope>test</scope>
</dependency>

2. HomeControllerTest 수정

// HomeControllerTest.java

@RunWith(SpringRunner.class)
@WebMvcTest(HomeController.class)
public class HomeControllerTest {
    @Autowired
    MockMvc mockMvc;

    @Test
    @WithMockUser   // 가짜 User 인증정보 사용
    public void hello() throws Exception {
        mockMvc.perform(MockMvcRequestBuilders.get("/hello").accept(MediaType.TEXT_HTML))
            .andDo(MockMvcResultHandlers.print())
            .andExpect(MockMvcResultMatchers.status().isOk())
            .andExpect(MockMvcResultMatchers.view().name("hello"))
        ;
    }

    @Test
    public void hello_without_user() throws Exception {
        mockMvc.perform(MockMvcRequestBuilders.get("/hello"))
            .andDo(MockMvcResultHandlers.print())
            .andExpect(MockMvcResultMatchers.status().isUnauthorized())
        ;
    }

    @Test
    @WithMockUser
    public void my() throws Exception {
        mockMvc.perform(MockMvcRequestBuilders.get("/my"))
            .andDo(MockMvcResultHandlers.print())
            .andExpect(MockMvcResultMatchers.status().isOk())
            .andExpect(MockMvcResultMatchers.view().name("my"))
        ;
    }
}

결과 확인

참고

https://docs.spring.io/spring-security/site/docs/current/reference/html5/#test-method

 

Spring Security Reference

In Spring Security 3.0, the codebase was sub-divided into separate jars which more clearly separate different functionality areas and third-party dependencies. If you use Maven to build your project, these are the modules you should add to your pom.xml. Ev

docs.spring.io

 

728x90
반응형

댓글