티스토리 뷰
Abstract
Spring Security 를 적용하고 컨트롤러 테스트를 했는데 에러가 발생했다.
403 에러였고, 찾아보니 클라이언트가 접근 권한이 없을 때 발생하는 forbidden 에러였다.
해결
먼저 Spring Security 적용 후에 컨트롤러 테스트를 하기 위해서는 테스트에서도 API 에 접근할 수 있어야 하므로 새로운 의존성을 추가해야 한다. 바로 spring-security-test 이다.
추가한 후에는 컨트롤러 테스트에서 MockMvc 클래스의 가짜 객체에 서비스의 의존성을 주입해 사용하여 post 요청을 보낼 때 .with(csrf()) 를 붙여주어야 한다.
Note
CSRF는 Cross-Site Request Forgery 의 줄임말로, 어떤 사이트에 로그인 된 유저들을 이용해서 사이트의 특정 요청을 보내도록 강제하는 공격을 말한다. CSRF 공격들은 웹 어플리케이션이 유저에게 갖고 있는 신뢰를 이용하는 것이다. (반대로 Cross-Site Scripting (XSS) 공격들은 웹 어플리케이션에 대한 유저의 신뢰를 이용한다.)
CSRF 공격은 웹 어플리케이션이 실제 사용자로부터 온 자발적인 요청과 사용자가 아닌 해커가 사용자의 인증 정보를 사용해 생성한 요청을 분간하지 못한다는 취약점을 이용한다.
Spring Security 는 CSRF 토큰을 이용해 CSRF 공격을 방어한다. 매 새션에 로그인된 사용자에게 임의의 난수로 된 토큰을 발급하고, 요청과 일치하는지 확인한 후에 응답하는 방식을 사용한다.
with(csrf()) 는 유효한 토큰을 가지고 테스트 중이니, API 에서 응답을 달라는 의미이다.
그리고 테스트를 실행해보니, 이번에는 401 unauthorized 에러가 발생했다. 유저 인증 과정을 거치지 않은 것이다.
이는 가짜로 인증 받은 유저로서 API 에 접근할 수 있도록 @WithMockUser 붙임으로서 해결할 수 있다.
@WithMockUser
가짜 유저로서 테스트를 실행할 때 붙이는 어노테이션인 @WithMockUser 는 다양한 옵션을 붙여 사용할 수 있다.
1. 디폴트값
먼저 아무 옵션도 붙이지 않은 채 @WithMockUser 을 사용하면, 아래 정보로 로그인한다. 실제로 존재하지 않는 아이디와 비밀번호여도 상관 없다. 가짜 유저이기 때문이다.
- username="user"
- password="password"
- roles="ROLE_USER"
Spring Security 는 이 세 개의 정보를 가지고 가짜 유저를 만든다.
- Spring Security의 User 객체가 Authentication 에서 핵심적으로 사용된다. 그래서 테스트에 MockUser 가 필요하다.
- Spring Security 에서 역할을 제한할 때 사용하는 GrantedAuthority 클래스의 객체 ROLE_USER 를 부여받는다.
2. 다양한 옵션들
위의 정보들을 옵션들을 통해 다양하게 바꾸어줄 수 있다. username 과 roles 를 아래와 같이 바꿀 수 있다.
@Test
@WithMockUser(username="customUsername",roles={"USER","ADMIN"})
public void getMessageWithMockUserCustomUser() {
String message = messageService.getMessage();
...
}
roles 에서 ROLE_USER 의 USER 는 Spring Security 에서 authorities 라고 하는 권한을 나타내는데, 변경 가능하다.
@Test
@WithMockUser(username = "customUsername", authorities = { "ADMIN", "USER" })
public void getMessageWithMockUserCustomAuthorities() {
String message = messageService.getMessage();
...
}
이렇게 하면 권한에 ADMIN 을 추가해 roles 는 ROLE_ADMIN 과 ROLE_USER 두 개가 된다.
Tip
어노테이션을 클래스 레벨에 붙이면 매 메소드마다 어노테이션을 붙일 필요 없어 편리하게 사용할 수 있다.
인증받은 사용자에게만 요청을 허가하는 특정 API 의 테스트
post(url) 뒤에 .contentType() 외에도 .content() 를 하나 더 붙여 Authentication 을 매개변수로 주어야 한다. 왜냐하면 컨트롤러에서 API 구현 시 Authentication 객체를 매개변수로 받도록 했기 때문이다:
출처
https://docs.spring.io/spring-security/reference/servlet/test/mockmvc/csrf.html
Testing with CSRF Protection :: Spring Security
When testing any non-safe HTTP methods and using Spring Security’s CSRF protection, you must include a valid CSRF Token in the request. To specify a valid CSRF token as a request parameter use the CSRF RequestPostProcessor like so:
docs.spring.io
https://www.synopsys.com/glossary/what-is-csrf.html
What Is Cross-Site Request Forgery (CSRF) and How Does It Work? | Synopsys
Cross-Site Request Forgery (CSRF) is an attack that forces authenticated users to submit a request to a web application against which they are currently authenticated. Learn more at Synopsys.com.
www.synopsys.com
https://docs.spring.io/spring-security/site/docs/5.0.x/reference/html/test-method.html
11. Testing Method Security
This section demonstrates how to use Spring Security’s Test support to test method based security. We first introduce a MessageService that requires the user to be authenticated in order to access it. The result of getMessage is a String saying "Hello" t
docs.spring.io
11. Testing Method Security
This section demonstrates how to use Spring Security’s Test support to test method based security. We first introduce a MessageService that requires the user to be authenticated in order to access it. The result of getMessage is a String saying "Hello" t
docs.spring.io
'Web Framework' 카테고리의 다른 글
[Spring Security] 경로에 @PathVariable 을 포함하는 API 를 인증 없이도 호출하도록 설정하기 (5) | 2023.01.05 |
---|---|
[Spring Security] HandlerExceptionResolver 를 사용한 토큰 필터에서의 예외 처리 (0) | 2022.12.26 |
[Spring Security] 토큰 발행 후 API에 토큰 인증 절차 추가하기 (2) | 2022.12.06 |
[Spring] ResponseEntity (0) | 2022.11.28 |
[SPRING] @RestController와 @Controller의 차이 (0) | 2022.11.18 |
- Total
- Today
- Yesterday
- ci/cd
- json web token
- 인증/인가
- @RequestBody
- DeSerialization
- JPA
- 프로그래머스
- 실시간데이터
- FCM
- DTO
- spring
- Firebase
- LazyInitializationException
- Jackson
- 코테
- google cloud
- 지연 로딩
- N+1
- JPQL
- 기지국 설치
- Spring Boot
- 역직렬화
- 알고리즘
- docker
- 가상 서버
- 도커
- JOIN FETCH
- gitlab
- 깃랩
- Java Data Types
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |