IRIS 비밀번호 오류로 인해 로그인이 안 될 때
IRIS 비밀번호를 까먹었다. 비번 찾기 눌러서 임시비밀번호를 받았는데, 이걸로 로그인이 안 된다. 임시비번을 만들어준 게 IRIS 본인인데 정작 그 비번이 IRIS 로그인 규칙에 안 맞는 상황. 하도 어이가 없어서 좀 파봤고, 결국 파이썬으로 우회해서 들어갔다. 그 삽질 기록이다.
일단 비번을 까먹었다
비번 찾기로 임시비밀번호를 발급받았다. 메일로 온 임시비번을 그대로 쳤는데 로그인 버튼이 안 먹는다. 뭐가 문제인가 콘솔 열어보니 이게 떠 있었다.
"비밀번호는 영문·숫자·특수문자를 모두 포함해야 합니다."
웃긴 게, 그 임시비번을 뱉은 게 IRIS인데 정작 거기엔 특수문자가 없다. 즉 자기가 준 비번이 자기 로그인 검사를 통과 못 한다. 서버는 그 비번 받아줄 준비가 돼 있는데 프론트 자바스크립트가 폼 제출 자체를 막는 거다. 비번 바꾸려면 로그인부터 돼야 하는데, 그 로그인이 안 된다. 도돌이표.
그래서 방법은 하나였다. 특수문자 검사가 사는 곳(브라우저)을 그냥 건너뛰고 서버한테 직접 로그인 요청을 던지는 것.
로그인 요청부터 구경
서버한테 뭘 보내야 하는지 알아야 하니까, 개발자도구 Network 탭 켜고 login.do 요청을 봤다. 페이로드에서 눈에 띈 건 이 정도.
_csrf— 메인 페이지 HTML에 hidden으로 박혀 오는 토큰. 세션이랑 짝이다.password— 평문이 아니라 base64로 감싸서 보낸다. 암호화는 아니고 그냥 인코딩.kstTime,browser,device— 시간이랑 브라우저/OS 같은 로그 찍는 용도 필드들.
결국 /login.do에 폼 데이터 POST 한 방이 전부고, 특수문자 규칙은 프론트에만 있었다. 그럼 브라우저 빼고 똑같이 보내면 되잖아.
그럼 직접 보내자
파이썬 기본 라이브러리면 충분하다. 순서도 별거 없다. main.do 한번 긁어서 세션 쿠키랑 _csrf 챙기고, 비번을 base64로 바꿔서 login.do에 POST. 끝.
#!/usr/bin/env python3
import base64, re, sys, json, datetime, urllib.request, urllib.parse, http.cookiejar
USERNAME = "YOUR_ID" # 본인 아이디
PASSWORD = "YOUR_PASSWORD" # 메일로 받은 임시비밀번호 (특수문자 없음)
BASE = "https://www.iris.go.kr"
UA = ("Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 "
"(KHTML, like Gecko) Chrome/126.0 Safari/537.36")
jar = http.cookiejar.CookieJar()
opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(jar))
opener.addheaders = [("User-Agent", UA)]
def get(url):
return opener.open(urllib.request.Request(url), timeout=30).read().decode("utf-8", "replace")
# 1) 메인 페이지에서 세션 쿠키 + _csrf 토큰 받기
html = get(BASE + "/main.do")
m = re.search(r'name="_csrf"\s+value="([^"]+)"', html)
if not m:
sys.exit("CSRF 토큰을 못 찾음")
csrf = m.group(1)
# 2) 로그인 POST (비번은 프론트랑 똑같이 base64)
now = datetime.datetime.now(datetime.timezone(datetime.timedelta(hours=9)))
form = {
"_csrf": csrf, "referer": "", "tempYn": "N", "moveUrl": "",
"username": USERNAME,
"password": base64.b64encode(PASSWORD.encode()).decode(),
"browser": "Google Chrome", "device": "Linux",
"kstTime": now.strftime("%Y. %m. %d. %H:%M:%S"), "country": "",
}
data = urllib.parse.urlencode(form).encode()
req = urllib.request.Request(BASE + "/login.do", data=data, method="POST")
req.add_header("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
req.add_header("Referer", BASE + "/main.do")
req.add_header("X-Requested-With", "XMLHttpRequest")
resp = opener.open(req, timeout=30)
# 3) 쌓인 세션 쿠키 뱉기
cookies = {c.name: c.value for c in jar}
print("; ".join(f"{k}={v}" for k, v in cookies.items()))볼 건 두 줄이다. 비번을 base64.b64encode로 감싸서 프론트랑 형식 맞추는 거, 그리고 CookieJar가 main.do에서 받은 세션 쿠키를 알아서 다음 login.do 요청에 붙여주는 거. 특수문자 검사하던 자바스크립트는 이 경로엔 애초에 없다.
쿠키
돌리면 로그인되고 세션 쿠키가 그냥 찍혀 나온다. 이거 통째로 curl에 물리면 로그인된 페이지도 그대로 긁힌다.

근데 난 페이지 긁으려던 게 아니었다. 그냥 평소 쓰던 크롬에서 로그인된 채로 들어가서 비번을 제대로 바꾸고 싶었을 뿐이다. 그래서 이 쿠키를 브라우저에 직접 넣기로 했다.
이 쿠키를 그냥 쓰던 크롬에 넣기
쿠키만 있으면 브라우저한테 "나 이미 로그인함"이라고 뻥칠 수 있다. 크롬 개발자도구로 직접 넣어보자. 파이어폭스도 Storage 탭에서 거의 똑같다.
1. iris.go.kr 켜고 F12
https://www.iris.go.kr 들어가서 F12 누르고 위쪽 Application 탭으로 간다. 쿠키는 그 사이트 페이지가 떠 있는 상태에서 넣어야 먹는다. 딴 페이지에서 넣으면 안 된다.

2. Cookies에서 도메인 고르기
왼쪽에서 Storage → Cookies → https://www.iris.go.kr 누르면 오른쪽에 쿠키가 쭉 뜬다. Name / Value / Domain / Path / Expires / HttpOnly / Secure 이런 열들. 여기서 값을 바꾼다.
3. Value 칸 더블클릭해서 갈아끼우기
JSESSIONID 줄의 Value 칸을 더블클릭하면 고칠 수 있다. 아까 스크립트가 뱉은 값으로 통째로 바꾸고 엔터. WMONID 같은 거 있으면 그것도 똑같이. 표에 그 쿠키가 아예 없으면 위에 + 눌러서 새로 만들고 Name·Value 채운 다음 Domain은 .iris.go.kr, Path는 /로 두면 대충 다 먹는다.

4. 새로고침
F5 누르면 방금 넣은 쿠키를 서버가 보고 "어 로그인 돼 있네" 하고 들여보내 준다. 이제 그냥 평소처럼 쓰면 된다.
JSESSIONID처럼HttpOnly붙은 쿠키는 콘솔에서document.cookie로는 절대 안 들어간다. 안 먹힌다고 삽질하지 말고, 위처럼 개발자도구 Application 탭에서 직접 고쳐야 한다.