아이패드 크롬에서만 로그인이 안 돼요 — nginx, 로드밸런서, 그리고 사라진 https

 "갤럭시 패드 크롬은 되고요, 아이패드 사파리도 되는데, 아이패드 크롬만 로그인이 안 돼요."   운영하다 보면 이런 신고가 제일 골치 아픕니다. 특정 브라우저, 특정 기기에서만 재현되는 버그. 코드를 아무리 들여다봐도 "브라우저마다 다르게 동작할 이유"가 안 보이거든요. 이 글은 그 신고 한 건이 사실은 nginx가 로드밸런서 뒤에서 https를 http로 떨어뜨리던 고전적인 인프라 함정이었다는 걸 추적한 기록입니다.   증상 : 관리자 대시보드에서 다른 시스템으로 넘어가는 로그인 버튼이 있는데, 이게 특정 환경에서만 실패했습니다.  아이패드 크롬  :  실패,  아이패드 사파리 : 성공  갤럭시탭 크롬 :  성공  PC: 성공    "크롬 문제다"라고 단정하기엔 갤럭시 크롬은 멀쩡합니다. "iOS 문제다"라고 하기엔 사파리는 됩니다. 딱 iOS × 크롬 교집합에서만 터집니다.   로그를 나란히 놓고 본다   증상이 아니라 데이터를 봅니다. 백엔드 referer 검증 로그를 실패/성공 케이스로 나란히 놓으니 결정적 차이가 한 줄에 드러났습니다.   아이패드 크롬 (실패):   referer: http://app.example.com/        ← http, 그리고 루트 경로   허용목록: ['https://admin.example.com/', 'https://app.example.com/']   → referer 체크 후 리다이렉트 (301, 로그인 차단)   아이패드 사파리 (성공):   referer: https://app.example.com/   ← https, 정상 경로   → 통과, 정상 로그인 진행   검증 코드는 단순했습니다.   허용 목록은 전부 https://로 시작합니다. 그런데 ...

MySQL password 대응

MySQL 8에서 사라진 PASSWORD() 함수, 어떻게 대처해야 할까? MySQL을 5.x 버전대에서 8.0 이상으로 업그레이드한 개발자라면 한 번쯤 마주쳤을 법한 오류가 있습니다. 바로 이전에 잘 사용하던 PASSWORD() 함수가 더 이상 작동하지 않는 문제입니다. 기존에는 아래와 같은 쿼리로 사용자의 비밀번호를 손쉽게 해시하여 저장할 수 있었습니다. -- MySQL 8.0 이전 버전에서 사용되던 방식 UPDATE user SET password_column = PASSWORD('my_password'); 하지만 MySQL 8.0부터 PASSWORD() 함수는 지원 중단(deprecated) 후 제거 되었기 때문에, 위 쿼리를 실행하면 오류가 발생합니다. 왜 PASSWORD() 함수가 사라졌을까? 가장 큰 이유는 보안 입니다. PASSWORD() 함수는 ' mysql_native_password ' 인증 방식에 사용되는 해시 값을 생성했는데, 이 해싱 알고리즘은 솔트(salt)를 사용하지 않는 오래된 방식입니다. 최신 보안 표준에 비해 취약점이 존재하여, MySQL 8.0부터는 기본 인증 플러그인이 더 강력한 caching_sha2_password 로 변경되면서 PASSWORD() 함수도 자연스럽게 사라지게 된 것입니다. 임시 해결책: PASSWORD() 함수 직접 구현하기 만약 기존 시스템과의 호환성 문제로 PASSWORD() 함수와 동일한 결과값이 반드시 필요한 상황이라면, 아래와 같이 수동으로 해시 값을 생성할 수 있습니다. 이는 PASSWORD() 함수의 내부 동작을 SQL 함수로 그대로 구현한 것입니다. UPDATE user SET password_column = CONCAT ('*', UPPER( SHA1 ( UNHEX (SHA1('my_password'))))); 이 쿼리는 다음 단계로 실행됩니다. SHA1('m...

MySQL 8.0 Incorrect date value error

  aws Aurora MySQL  5.7에서 8 업그레이드 하면서 나온 에러 date 컬럼에 where '' 했더니 에러 하지만 '0000-00-00' 검색 됨 . 이유는 고마우신분이 작성한 글 내용 MySQL 서버에서 sql_mode 옵션에 NO_ZERO_DATE 옵션과, NO_ZERO_IN_DATE 옵션이 존재한다. 이 2개 옵션은 다음과 같이 동작한다. ​ NO_ZERO_DATE enable: 0000-00-00 값을 invalid date로 인식한다. disable: 0000-00-00 값을 저장할 수 있다. ​ NO_ZERO_IN_DATE enable: date의 month 또는 day 부분에 0이 입력되면 invalid date로 인식한다. disable: 2022-12-00 또는 2022-00-01과 같은 형태의 date 입력이 가능하다. ​ MySQL 5.7, 8.0 이상의 버전에서는 아래와 같은 테이블을 생성하고 데이터를 넣지 않은 상태에서 mysql > CREATE TABLE `new_table` ( `id_table` int(11) NOT NULL AUTO_INCREMENT, `text_table` varchar(45) DEFAULT NULL, `date_table` date DEFAULT NULL, PRIMARY KEY (`id_table`) ) ENGINE=InnoDB 다음의 WHERE절 조건을 가진 쿼리를 수행하면, mysql > SELECT id_table, text_table FROM new_table WHERE date_table = '' OR mysql > SELECT id_table, text_table FROM new_table WHERE date_table = '0000-00-00' Incorrect date value라는 오류가 발생한다. 데이터를 넣는 경우에도 마찬가지이다. 반면에 MySQL 5.6 버전 에서는 경고(Warning)...