(+) 제가 직접 제작한 이미지들과 코드들이므로 불펌은 하지 말아주세요! 출처만 남겨주신다면 좋을 것 같습니다! 😊
스프링부트는 refresh token을 발급해줄 때 set-cookie 설정을 통해 쿠키를 set 해줘야 합니다.
ResponseCookie cookie = ResponseCookie.from("refreshToken", refreshToken)
.maxAge(7 * 24 * 60 * 60)
.path("/")
.secure(true)
.sameSite("None")
.httpOnly(true)
.build();
response.setHeader("Set-Cookie", cookie.toString());
ResponseCookie cookie = ResponseCookie.from("refreshToken", refreshToken)
// 토큰의 유효 기간
.maxAge(7 * 24 * 60 * 60)
.path("/")
// https 환경에서만 쿠키가 발동합니다.
.secure(true)
// 동일 사이트과 크로스 사이트에 모두 쿠키 전송이 가능합니다
.sameSite("None")
.httpOnly(true)
// 브라우저에서 쿠키에 접근할 수 없도록 제한
.build();
response.setHeader("Set-Cookie", cookie.toString());
1-1-1 ) 실제 응답 결과 :
1) json response
"success": true,
"code": 0,
"result": {
"data": {
"accessToken": "Bearer eyJhbGciOi~E2MjAyNH0.2PUzUF4ECX3bZFRehI0V27ed_Yu3pd5_dyvdKjqKp3I",
"refreshToken": "httponly",
}
}
1) 클라이언트 요청 보낼 때 (postman 예시)
Authorization
헤더에 Bearer abc...
를 넣는 형식으로 반드시 액세스 토큰을 보내줘야 합니다.액세스가 유효하지 않다는 에러를 throw 하는 것은 아래와 같은 응답을 돌려준다는 것입니다.
액세스가 유효하지 않다는 응답을 돌려받게 되면, 프론트 단에서는 다시 액세스를 발급받아야 하므로 해야 하므로 액세스 토큰 재발급 요청 api로 이동해서 새로운 액세스를 발급 받아와야 합니다.
이는 아래의 3) 과정을 따라가야 합니다.
서버에서 유효한 액세스에 대한 응답 예시는 아래와 같습니다.
서버에서 유효하지 않은 액세스에 대한 응답 예시는 아래와 같습니다.
리프레시 토큰은 쉽게 탈취당하지 않도록 우리가 set 해줄 때 http only 속성으로 쿠키에 저장을 해주었기 때문에, js 브라우저에서나 타인이 쉽게 볼 수 없고 탈취가 어렵습니다.
HTTP Only란?
- document.cookie와 같은 자바스크립트로 쿠키를 조회하는 것을 막는 옵션입니다.
- 브라우저에서 HTTP Only가 설정된 쿠키를 조회할 수 없습니다.
- 서버로 HTTP Request 요청을 보낼때만 쿠키를 전송합니다.
- 이를 통해 XSS(Cross Site Scripting) 공격을 차단할 수 있습니다.
- http only 출처
액세스 재발급 해주세요
라는 api를 발동시키게 되면, 쿠키에 저장돼있는 refreshToken을 잡아와서 이 refreshToken이 유효한 지 검사합니다.doFilter
메소드를 호출하는 곳에서 내가 허용할 origin을 명시해줍니다. @Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response1 = (HttpServletResponse) response;
HttpServletRequest request1 = (HttpServletRequest) request;
response1.setHeader("Access-Control-Allow-Origin", "https://n~y.app");
response1.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response1.setHeader("Access-Control-Max-Age", "3600");
response1.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, remember-me, Origin,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization");
response1.setHeader("Access-Control-Allow-Credentials", "true");
String token = extractToken(request);
if(validateToken(token)) {
// SecurityContext에 Authentication 객체 저장
setAuthentication(token);
}
chain.doFilter(request, response1);
}
주의사항
응답.setHeader("Access-Control-Allow-Credentials", "true");
을 설정하는 경우라면응답.setHeader("Access-Control-Allow-Origin", "cors허용할 사이트");
에서 cors허용할 사이트를 특정해 지정해줘야 합니다.- "*"로 하면 안됩니다.