SpringBoot + vue.js를 이용한 커스텀 쿠키 받기
🔍 프론트 서버에서 커스텀 쿠키 받기
커스텀 쿠키를 저장하기 위해서는 axios 요청에 withCredentials
속성을 true
로 설정해주어야 한다. 이는 교차 출처 요청에서 자격 증명을 보내는 것이 보안 문제를 야기할 수 있으며, 사용자가 그러한 동작을 인식하고 명시적으로 허용했는지 확인하기를 원하기 때문입니다.
Vue.js의 axios 코드에 withCredentials: true
를 추가해줍시다.
1
2
3
4
5
6
useAxios(
'products?keyword=mango',{
withCredentials: true,
},
...
)
서버에서도 교차 출처에서 인증 정보를 주고 받을 수 있도록 설정해주겠습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Configuration
class WebConfig: WebMvcConfigurer {
override fun addCorsMappings(registry: CorsRegistry) {
registry.addMapping("/**")
.allowedOrigins(FRONT_SERVER)
.allowCredentials(true) ---- 추가
.allowedMethods(
HttpMethod.GET.name(),
HttpMethod.HEAD.name(),
HttpMethod.POST.name(),
HttpMethod.PUT.name(),
HttpMethod.PATCH.name(),
HttpMethod.DELETE.name()
);
}
}
다음 설정을 마치고 나면 응답으로 받은 쿠키가 자동으로 저장됨을 확인할 수 있습니다.
그런데 네트워크에서 요청과 응답을 확인해보면 두 번의 요청이 발생했음을 확인할 수 있습니다.
🔍 트러블 슈팅
✏️ CORS 교차 출처 문제와 preflight
CORS가 처음 등장 했을 때는 요청이 허용되는지 여부를 확인하기 위한 방법이 없었습니다. 그래서 서버는 모든 요청을 허용하거나 거부해야만 했습니다. 이러한 방식은 보안과 성능적인 측면에서 문제가 생겼고 이러한 문제를 해결하기 위해 preflight 도입되었습니다. 따라서 교차 출처 요청 전에는 항상 preflight 요청이 선행됩니다.
따라서 교차 출처를 해결할 수 있도록 코드를 추가해주어야 합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Component
class SessionFilter(): OncePerRequestFilter() {
override fun doFilterInternal(
request: HttpServletRequest,
response: HttpServletResponse,
filterChain: FilterChain
) {
// preflight 요청 확인 로직
if (request.method == HttpMethod.OPTIONS.toString()) {
log.debug("This is preflight")
return;
}
...
filterChain.doFilter(request, response)
}
}
✏️ 디버깅 과정
1.필터에서 OPTIONS를 못 걸러 낸다는 것은 프론트에서 PREFLIGHT가 아닌 GET요청을 보내고 있다고 생각했다.
2.프론트 서버의 콘솔을 확인해보니 axios에 대한 로그가 하나도 출력이 안 됨을 인지했다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
submit() {
const { submit } = useAxios(
'products?keyword=mango',{
withCredentials: true,
},
{
method: 'get',
},
{
immediate: false,
onSuccess: (response) => {
console.log(response);
onError: (e) => {
console.log(e);
}
},
);
}
submit();
}
3.검색을 해보니 immediate 속성과 관련이 있는 것 같아 axios 코드로 바꿨더니 해결되었다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const requestConfig = {
method: 'get',
url: 'http://localhost:8080/products',
params: {
keyword: 'mango',
},
withCredentials: true,
};
axios(requestConfig)
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.error(error);
});
✏️ 문제의 원인
- axios의 설정에 immediate: false와 withCredentials = true 속성을 같이 사용하게 되면 preflight는 초기화 하는 시점에 한 번 날라가게 되고 submit()을 호출할 때 한 번더 날라가게 됩니다.
- 실제로 setup()함수에 axios를 초기화 하고 이후 버튼을 클릭하면 submit()을 호출하도록 로직을 바꿨더니 화면에 들어가는 순간 preflight 요청이 실행됨을 확인할 수 있어습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
setup() {
const requestConfig = {
method: 'get',
url: 'http://localhost:8080/products',
params: {
keyword: 'mango',
},
withCredentials: true,
};
const submit = axios(requestConfig)
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.error(error);
});
return { getImageUrl, submit }
},
- 요청하는 시점에 preflight를 한 번 더 보내니까 총 두 번의 GET요청이 발생한 것입니다.
📋결론
- axios의 설정에 immediate: false와 withCredentials = true 속성을 같이 사용하게 되면 preflight는 초기화 하는 시점에 한 번 날라가게 되고 submit()을 호출할 때 한 번더 날라가게 됩니다.
- 따라서 immediate: true 또는 제거해줌으로써 이를 해결할 수 있습니다.
This post is licensed under CC BY 4.0 by the author.