계정당 하나의 세션을 허용하는 정책은 두 번째 로그인이 올 때까지 확정된 것처럼 보인다. 두 가지 결과가 가능하다. 새로 온 쪽이 기존 세션을 대체하거나, 기존 세션이 슬롯을 유지하고 새 쪽이 거부되는 것이다. 첫 세션이 이기는 정책은 후자뿐이다. 대부분의 사람이 선택하는 클라이언트 옵션은 동시 접속을 켜므로 이 결과를 만들지 않는다.

하나의 설정 뒤에 두 개의 계약이 숨어 있다

동시 접속을 끄면 같은 인증서 이름을 가진 두 번째 연결이 이미 실행 중인 세션을 밀어낼 수 있다. 동시 접속을 켜면 여러 세션을 한꺼번에 허용하므로 제한과는 정반대다. 어느 상태도 거부 정책이 아니므로 결정은 완전히 다른 곳에서 내려야 한다.

무엇이든 구현하기 전에 계약을 적어라. 누가 거부되는지, 무엇이 기존 세션을 식별하는지, 깔끔한 연결 종료 없이 세션이 죽으면 어떻게 되는지. 이렇게 말로 정리한 사람이 없는 정책은 나중에 검증할 수 없다.

축출은 연결 훅보다 먼저 일어난다

2.6 서버 코드 경로에서는 동시 접속이 꺼져 있을 때 새 클라이언트의 초기 설정이 같은 이름의 기존 인스턴스를 제거한다. 그 제거는 연결 핸들러 체인이 실행되기 전에 일어난다. 따라서 중복을 알아채고 실패를 반환하는 스크립트는 기존 세션이 이미 버려진 뒤에 새 연결을 거부하며, 바로 정책이 막으려던 결과가 된다. 업스트림 구현의 콜백 순서만이 당신의 빌드에 대한 신뢰할 수 있는 답이다.

StageWho can still refuseEffect on the incumbent
Certificate checkServer trust configurationNone
Authentication decisionThe authentication controllerNone, because establishment has not run
Connect handlerA profile scriptAlready evicted in the same-name case
Post-establishmentStatus tooling, monitoringBoth sessions already exist or one is gone

상태 파일을 폴링하는 것도 게이트가 아니다. 동시에 도착한 두 시도는 어느 쪽도 확정하기 전에 빈 슬롯을 볼 수 있고, 둘 다 진행한다.

결정을 인증으로 옮겨라

인증서 검증 후 관리 인터페이스가 인증 결정을 맡을 수 있다. 이 구성에서 컨트롤러는 감시자가 아니다. 연결하는 각 클라이언트 인스턴스를 받아 그 인스턴스가 진행해도 되는지 답한다. 답이 설정보다 먼저 오므로 거부해도 기존 세션은 그대로 남는다. 같은 채널이 연결 종료를 보고하며, 컨트롤러는 이렇게 슬롯이 정당하게 해제되었음을 안다.

모든 새 인스턴스는 이 게이트를 통과해야 한다. 재연결과 프롬프트 없이 다시 인증하는 경로도 포함된다. 일부 인스턴스가 결코 도달하지 못하는 게이트는 아무것도 보호하지 못하며, 누군가 우회로를 시도할 때까지 그 누락은 보이지 않는다.

토큰은 게이트를 그냥 지나칠 수 있다

토큰이 발급되면 서버는 이를 내부에서 검증하고 그 연결에 대한 외부 인증을 건너뛸 수 있다. 관리 호출은 결코 일어나지 않으므로 그곳에만 구현한 슬롯 검사는 새 인스턴스를 보지 못한다. 이 동작은 사용자에게는 편리함이고 동시 접속 정책에는 구멍이다. 토큰 인증 연결도 동등한 권위 있는 검사를 통과하게 하거나, 모든 연결에서 결정을 요구하는 정책이라면 토큰 경로를 비활성화하라.

모든 토큰을 무조건 받아들여 이를 보상하지 마라. 만료되었거나 유효하지 않은 토큰은 여전히 실패해야 하고, 다른 모든 것과 같은 결정 지점에서 실패해야 한다.

예약을 주소가 아니라 인스턴스에 묶어라

주소는 약한 신원이다. 같은 노트북에서의 재연결이 다른 주소에서 올 수 있고, 복사한 자격 증명이 같은 주소에서 올 수 있다. 예약을 서버가 할당하는 클라이언트 인스턴스에 묶어, 이미 허용된 인스턴스의 재인증이 소유자로 인식되게 하라. 새 인스턴스 식별자는 같은 토큰을 제시하더라도 먼저 온 쪽이 이긴다는 결정을 통해 자기 슬롯을 얻어야 한다.

실패한 시도에 속한 예약만 해제하라. 이전 시도의 지연된 연결 종료 이벤트가 더 새로운 소유자의 슬롯을 지워서는 안 되며, 그래서 해제는 계정이 아니라 인스턴스를 지목한다. 컨트롤러를 다시 시작한 뒤에는 누구를 받아들이기 전에 살아 있는 세션을 조정하고, 계정을 서비스하는 모든 게이트웨이에 같은 규칙을 적용하라.

정말 오래된 슬롯을 어떻게 회수할지는 따로 정하라. 관리자에게는 이를 지우는 문서화된 방법이 필요하며, 그 경로는 재연결을 클릭하는 사용자에게 닿지 않아야 한다.

중요한 조합을 시험하라. 거의 동시에 일어난 두 로그인, 깔끔한 종료 후 재연결, 기존 세션의 재인증, 거부된 새 연결, 컨트롤러 재시작이다. 어느 경우든 기존 세션은 쓸 수 있는 상태로 남아야 하고 새 연결은 다른 계정에 피해 없이 거부되어야 한다.

관련 글