Spring Security
스프링 시큐리티는 스프링 기반의 어플리케이션의 보안(인증과 권한)을 담당하는 프레임워크
보안관련 용어
- 접근 주체 (
Principal
) : 보호된 리소스에 접근하는 대상 - 인증 (
Authentication
) : 보호된 리소스에 접근한 대상에 대해 이 유저가 누구인지,Application
의 작업을 수행해도 되는지 확인하는 과정 - 인가 (
Authorize
) : 해당 리소스에 대해 접근 가능한 권한을 가지고 있는지 확인하는 과정 (After Authentication
) - 권한 : 인증된 주체가
Application
의 동작을 수행할 수 있도록 허락되어있는지를 결정- 권한 승인이 필요한 부분으로 접근하려면 인증 과정을 통해 주체가 증명 되어야만 한다
- 권한 부여에도 두가지 영역이 존재하는데 웹 요청 권한, 메소드 호출 및 도메인 인스턴스에 대한 접근 권한 부여
참고
https://spring.io/projects/spring-security
기본 예제
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"))
;
}
}
결과 확인
스프링 시큐리티가 적용되어 있어 로그인 페이지가 나타나고, 로그인 이후 모든 페이지 접근이 가능하다.
스프링 부트 시큐리티 자동 설정
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
'Dev > Spring Boot' 카테고리의 다른 글
[스프링 부트 개념과 활용] 스프링 REST 클라이언트 1부 (0) | 2020.09.03 |
---|---|
[스프링 부트 개념과 활용] 스프링 시큐리티 2부 (0) | 2020.08.31 |
[스프링 부트 개념과 활용] 스프링 데이터 12부 (0) | 2020.08.31 |
[스프링 부트 개념과 활용] 스프링 데이터 11부 (0) | 2020.08.28 |
[스프링 부트 개념과 활용] 스프링 데이터 10부 (0) | 2020.08.28 |
댓글