✅ 문제 직면
현재 개발하는 서비스에서 다른 사이트의 로그인 정보를 받아야 하는 상황 속에서 SSO (Single-Sign-On)를 활용하지 않아본인이 직접 API를 통해 사용자 정보를 입력 받고 Session을 생성해야 하는 상황에 놓여졌다.
✅ 서비스 흐름
- 서버는 Session 정보를 확인하지 못하면 접근을 차단한다.
- SessionController를 통해 사용자 정보를 전달받고 해당 데이터를 통해 Session을 생성한다.
- 사용자는 해당 SessionId를 전달 받고 서버에 접근한다.
여기서 새로운 문제에 직면한다.
✅ 도메인 간 쿠기 생성
분명 본인의 서버에서 테스트를 진행할 때는 문제가 없이 Session이 만들어지고 JSESSONID 쿠키가 생성이 되었는데..
다른 서비스 (타 도메인)에서 접근하려고 하니 서버에 접근이 불가능했다.
이유인 즉, 타 도메인(A도메인) 에 쿠키를 생성할 수 없기 때문이다.
테스트를 진행할 때는 나의 서버(B도메인) 안에서 테스트를 진행했기 때문에 정상적으로 쿠키가 생성이 됐는데
타 도메인(A도메인)에서 SessionController에 접근을 해도 Session은 생성되지만 쿠키를 생성할 수 없어서
접근을 하지 못했던 것이다.
✅ 문제 해결
해당 문제는 SameSite: None으로 해결이 가능하다. 물론 보안상 문제가 있을 수 있다.
우선 CORS 설정을 진행한다.
🟧 Config
⏹️ CorsConfig.java
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") // 영향 받는 곳
.allowedOriginPatterns("*") // 허용할 도메인 패턴
.allowedMethods("GET", "POST") // 허용할 메서드
.allowedHeaders("*")
.allowCredentials(true) // 이거는 꼭 허용해줘야 한다.
.maxAge(1800);
}
}
보안을 위해 특정 도메인만 허용하는 것을 추천한다.
⏹️ AppConfig.java
@Configuration
public class AppConfig implements WebMvcConfigurer {
@Autowired
private SessionInterceptor sessionInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(sessionInterceptor)
.addPathPatterns("/**") // 영향 받는 곳
.excludePathPatterns("/session/**") // 예외 허용
}
}
위 코드는 Session이 없으면 서버 접근을 하지 못하도록 하는 것이기 때문에 큰 상관은 없다.
🟧 Interceptor
⏹️ SessionInterceptor.java
@Component
public class SessionInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession(false); // 세션이 없으면 null 반환
if (session == null || session.getAttribute("userSession") == null) {
response.sendRedirect("/permissionDenied");
return false;
}
return true;
}
}
위 코드 또한 Session 없이 서버에 접근하는 것을 막기 위한 방법이다.
NodeJs에 미들웨어가 있는 것처럼 Spring boot에도 Interceptor가 있다.
🟧 Controller
⏹️ SessionController.java
@RestController
@RequestMapping("/session")
public class SessionController {
@PostMapping("/createSession")
public ResponseEntity<String> createSession(@RequestBody Map<String, Object> data, HttpServletResponse response, HttpSession session) {
session.setAttribute("userSession", data);
String sessionId = session.getId();
response.setHeader("Set-Cookie", "JSESSIONID=" + sessionId + "; SameSite=None; Secure");
return ResponseEntity.ok(sessionId);
}
}
위 코드에서 핵심 부분은 SameSite=None; Secure 이 부분이다.
이렇게 설정해 놓으면 타 도메인에도 쿠키를 생성할 수 있는데 한 가지 문제가 있다고 한다면
https에서만 가능하다는 점이다.
🟧 Client
$.ajax({
url: "https://blabla/session/createSession",
data: JSON.stringify(data),
type: "POST",
async: false,
timeout: 4000,
xhrFields: {
withCredentials: true
},
contentType: "application/json",
success: function(data) {
window.open("https://blabla");
},
error: function(xhr) {
console.log(xhr);
}
});
클라이언트 쪽에서는 이렇게 데이터를 전달하고 접근하면 되는데 여기서 중요한 것이
xhrFields: {
withCredentials: true
},
해당 옵션을 넣어줘야 쿠키 생성이 가능하다는 것이다.
이렇듯 서버와 클라이언트 모두 옵션을 추가해 줘야 하고 번거로운 사항이 많다.
별로 추천하지 않는다... 에휴
'Etc' 카테고리의 다른 글
이클립스 단축키 꿀팁 (0) | 2023.06.20 |
---|---|
Eclipse UI 크기 조절하기 (0) | 2023.05.09 |
favicon.ico 404 에러 (0) | 2023.03.09 |
추억의 달팽이, Up & Down 게임 만들기 (0) | 2023.02.10 |
CS 지식 정리 (0) | 2022.11.16 |