PostgreSQL에서 Django 세션 디코딩

Django 회의에서.


세션은 HTTP 기반 웹 프레임워크의 중요한 구성 요소입니다.그것들은 웹 서버에서 HTTP 클라이언트의 신분을 반복해서 추적할 수 있으며, 모든 요청에 대해 다시 신분 검증을 할 필요가 없다.세션을 추적하는 몇 가지 다른 방법이 있다.어떤 것은 서버에서 세션 데이터를 저장할 필요가 없고, 어떤 것은 필요하다.
Django는 Python 기반 웹 프레임워크로 기본 세션 백엔드를 첨부하여 지속적인 세션 데이터를 저장합니다.몇 가지 저장 및 캐시 옵션이 있습니다.세션을 SQL 데이터베이스에 간단하게 저장하고, 찾을 때마다 Redis나 Memcached 같은 캐시에 저장하거나, 이 두 가지 캐시를 동시에 사용하며, 데이터베이스 저장소 앞에 캐시 엔진을 설정할 수 있습니다.세션을 최종적으로 SQL에 저장하는 옵션 중 하나를 사용하는 경우 django_session 테이블에는 사용자의 세션이 포함됩니다.
본문 캡처는 Arctype에서 나온 것이다.

세션 모드


응용 프로그램의 데이터를 자세히 볼 때 사용자의 세션 데이터를 실제 사용자 항목(auth_user표)에 연결해야 하는 문제가 발생할 수 있습니다.최근에 나는 이런 상황을 만났다. 내가 세션표의 패턴 정의를 보았을 때, 나는 user_id이 열로 저장되지 않은 것에 놀랐다.왜 이런 상황이 발생했는지에 대해 중요한 디자인 결정이 있지만 나 같은 SQL 사용자에게는 불편하다.
session_key은 고객 제공의 핵심입니다.일반적으로 요청한 고객 기회는 session_key을 쿠키의 일부분으로 한다.웹 서버가 요청을 받았을 때, session_key (존재할 경우) 을 찾아서 키가 알고 있는지 확인합니다.만약 그렇다면, session_data을 보고 사용자 및 세션에 대한 메타데이터를 검색합니다.
이것이 Django 요청에서 request.user을 액세스하는 방법입니다.디코딩된 user_id에서 session_data을 추출하여 저장된 user_id에 따라 내장된 사용자 대상을 채우고 사용자 대상은 전체 항목 보기에서 사용할 수 있다.
일부 빠른 구글 검색은 기본적으로 세션 데이터가 JSON으로 저장된다는 것을 알려준다.나는 이미 Postgres의 우수한 JSON 능력(if you are not, check out this blog post)을 알고 있기 때문에 이것은 우리가 Postgres의 범위 내에서 사용할 수 있는 물건이라고 의심한다.나처럼 박사 뒤에 많은 시간을 들인 사람에게는 좋은 소식이다.

질의 작성


첫눈



첫 번째 그림에서 보듯이session 데이터는 JSON이 아닌 것 같습니다.JSON으로 저장된 메타데이터는 base64 encoding 뒤에 숨겨집니다.다행히도, 우리는 Postgres에서base64를 쉽게 디코딩할 수 있다.

Base64에서 디코딩



이것은 사람들로 하여금 이해하게 하기 매우 어렵다.우리는 2진 데이터를 텍스트로 변환해야 한다.

텍스트로 인코딩


Postgres의 "encode"기능을 사용하면 바이너리 데이터를 텍스트 표시로 인코딩할 수 있습니다.

이제 우리는 마침내 인류가 읽을 수 있는 것들을 볼 수 있게 되었다.다음은 텍스트 형식의 전체 디코딩 결과 중 하나입니다.
11fcbb0d460fd406e83b60ae082991818a1321a4:{"_auth_user_hash":"39308b9542b9305fc038d28a51088905e14246a1","_auth_user_backend":"x.alternate_auth.Backend","_auth_user_id":"52135"}

JSON 추출


여기에 JSON blob이 하나 있는데, 앞에는 사칭과 산열 순서가 있다.우리는 JSON blob에만 관심이 있습니다.해시와 사칭된 텍스트만 추출하는 빠른 방법은 첫 번째 사칭의 위치를 찾고 그 뒤에 있는 모든 문자를 추출하는 것이다.
이를 실현하기 위해 우리는 RIGHT 함수와 string 함수를 이용하여 전자는 POSITION의 마지막 n개의 문자를 되돌려주고 후자는 문자열의 문자의 위치를 되돌려준다.POSITION은 검색할 문자열의 첫 번째 실례의 위치만 되돌려줍니다.RIGHT 함수는 마이너스 인덱스를 받아들인다.마이너스 인덱스는 문자열의 오른쪽에서 마이너스 인덱스가 표시하는 문자를 제외한 문자를 추출합니다.
이 조회를 더욱 구성하기 위해서, 우리는 CTE를 사용하여 그것을 두 부분으로 분해할 것이다.CTE는 평범하지 않은 열을 구축하고 선택하고 여러 번 사용해야 할 때 유용합니다.만약 우리가 SELECT을 계속 사용한다면, 우리는 어쩔 수 없이 encode(decode(session_data, 'base64'), 'escape') 부분을 여러 번 입력해야 한다.이것은 매우 혼란스럽습니다. 만약 인코딩 데이터를 해석하는 방식을 바꾸기로 결정한다면, 반드시 두 위치에서 함수 호출을 변경해야 합니다.
다음은 JSON 섹션을 추출한 업데이트된 질의입니다.

전체 결과 예:
{"_auth_user_hash":"396db3c0f4ba3d35b350a","_auth_user_backend":"x.alternate_auth.Backend","_auth_user_id":"52646"}

JSON 인증


현재 이 열은 JSON으로 분석할 수 있고 우리는 계속할 수 있다.그러나 Postgres에서 텍스트를 올바른 JSON이 아닌 JSON으로 변환하려고 시도하면 Postgres는 오류를 던지고 검색을 중지합니다.내 데이터베이스에서 일부 세션은 해석할 수 없다.여기에는 텍스트가 해석 가능한 JSON처럼 보일 수 있도록 하는 방법이 있다.
where
    substring(decoded, position(':' in decoded) + 1, 1) = '{'
    and right(decoded, 1) = '}'`
괄호로 시작하거나 끝나지 않은 문자열은 모두 필터됩니다.
이것은 결코 그것을 해석할 수 있다는 것을 보장할 수 없지만, 나의 수백만 개의 세션 데이터베이스에 대해 이 작업을 완성했다.JSON의 해석 가능성을 검증하기 위해 맞춤형 Postgres 함수를 작성할 수 있지만 속도가 느립니다.

JSON주조

WHERE 자구를 사용하여 잘못된 세션 메타데이터를 제거하면 문자열을 Postgres의 JSON 형식으로 변환하고 _auth_user_id 키를 추출할 때가 됩니다.Django 구성에 따라 키가 다를 수 있습니다.객체를 JSON 유형으로 변환하면 object->'key' 구문 버튼을 사용하여 JSON 값을 조회할 수 있습니다.

문자열 정리


우리 거의 다 왔어!Postgres는 JSON에서 text으로 변환할 때 주위에 더블 따옴표를 추가합니다.마지막으로user id 필드가 int이길 희망하지만 Postgres는 더블 인덱스를 포함하는 문자열을 int으로 해석하지 않습니다.자바스크립트도 이러면 안 돼!TRIM이 있는 BOTH 함수는 문자열의 양쪽에서 지정한 문자를 삭제하고 깨끗한 문자열을 남겨 정수로 쉽게 변환할 수 있습니다.

최종 질의


이것은 우리가 여분의 더블 인용부호를 삭제하고 그것을 int으로 변환한 후의 최종 조회입니다.

이제 예제 결과와 같이 session_key을 Django auth_user id에 연결했습니다.
다음은 복제 가능한 형식의 전체 질의입니다.
with step1 as (
  select
    session_key,
    encode(decode(session_data, 'base64'), 'escape') :: text as decoded
  from
    django_session
)
select
  session_key,
  trim(
    both '"'
    from
      (
        right(
          decoded,
          0 - position(':' in decoded)
        ) :: json -> '_auth_user_id'
      ) :: text
  ) :: int as user_id
from
  step1
where
  substring(decoded, position(':' in decoded) + 1, 1) = '{'
  and right(decoded, 1) = '}'

물적 보기를 사용하여 빠른 조회를 진행하다


만약 당신의 데이터베이스에 많은 사용자가 있다면, 당신은 이 조회가 매우 느리다는 것을 알아차릴 것이다.물적 뷰를 생성하면 SQL을 다시 실행할 필요 없이 영구 뷰에서 질의 결과를 반복할 수 있습니다.
물적 보기를 만들 때 (보기를 새로 고칠 때), 이 보기의 원본 코드를 실행하고 결과의 줄로 채웁니다.최신 데이터가 필요할 때 반드시 보기를 새로 고치세요!
create materialized view mv_django_session_user as
with step1 as (
…
새로 고치기
refresh materialized view mv_django_session_user;

요약


Python, Ruby, PHP 등 웹 응용 프로그램이 사용하는 일반적인 언어에 비해 Postgres의 인코딩과 문자열 조작은 좀 번거롭지만 Postgres에서 하나의 보기를 구축하여 필요한 정확한 데이터를 신속하게 추출하고 다른 테이블에 직접 연결할 수 있도록 하는 것은 매우 만족스럽다.
다음에 네트워크 프레임워크나 다른 제3자가 인코딩한 데이터를 추출해야 할 때Postgres를 보셔서 답을 얻으세요!
본문 캡처는 Arctype에서 나온 것이다.

좋은 웹페이지 즐겨찾기