Skip to content

Instantly share code, notes, and snippets.

@chwnam
Last active July 2, 2024 10:00
Show Gist options
  • Save chwnam/5b583ecb6bafa7f8b25de41827f3d510 to your computer and use it in GitHub Desktop.
Save chwnam/5b583ecb6bafa7f8b25de41827f3d510 to your computer and use it in GitHub Desktop.
스타벅스 와이파이 자동 인증 파이썬3 스크립트
#!/usr/bin/env python3
import time
from http.cookiejar import Cookie
from re import search, findall
from urllib.parse import urlencode
from urllib.request import (
HTTPCookieProcessor,
HTTPRedirectHandler,
Request,
build_opener
)
class RedirectionCheckHandler(HTTPRedirectHandler):
"""
302 리다이렉션이 일어났는지 점검하기 위한 핸들러
"""
def __init__(self):
self.code = ''
self.redirect_url = ''
def http_error_302(self, req, fp, code, msg, headers):
self.code = code
self.redirect_url = ''
return super().http_error_302(req, fp, code, msg, headers)
class KtStarbucksAutoAuthorize(object):
"""
KT 스타벅스에 자동으로 접속 인증합니다.
{"result_cd":"0000"} 이라는 응답이 들어오면 성공입니다.
"""
def __init__(self):
self.cooke_processor = HTTPCookieProcessor()
self.redirect_handler = RedirectionCheckHandler()
self.opener = build_opener(self.redirect_handler, self.cooke_processor)
def authorize(self):
"""
스타벅스 와이파이 네트워크에 인증 처리를 시도합니다.
"""
url = self.step1_check_captive_network()
if not url:
print("이미 인증 된 것 같은데요? 인터넷 잘 쓰세요!")
return
data = self.step2_post_form(url)
if not data:
print('스타벅스 지점을 못 찾았네요...')
return
print(self.step3_authorize(data))
def step1_check_captive_network(self):
"""
captive network 점검입니다. http 쪽으로 테스트를 해서 302 응답이 날아오는지 점검합니다.
"""
response = self.get_response('http://detectportal.firefox.com/success.txt')
if self.redirect_handler.code != 302:
return ''
html = response.read().decode('utf-8')
found = search('location.href = "(http://.+)";', html)
if not found:
return ''
return found.group(1)
def step2_post_form(self, url):
"""
step1 에서 302 리다이렉션의 주소로 접속을 시도합니다.
응답으로 아주 심플한 자바스크립트를 얻게 됩니다. 이 스크립트를 통해 재차 리다이렉션이 일어날 것을 기대하고 있습니다.
리다이렉션을 통해 접속한 URL 에서는 폼을 발견할 수 있습니다. 이 폼 양식을 POST 전송하게 되어 있습니다.
간단하게 HTML 홈 양식을 분석해 웹브라우저를 흉내냅니다.
"""
response = self.get_response(url)
html = response.read().decode('euc-kr')
# step3에 사용할 쿠키를 구워 둡니다. 스크립트와 정확히 동작하게 한다는 가정하에 작성하였으나,
# 테스트 결과 없어도 큰 문제는 없었습니다.
# cookie_found = findall('<script language="javascript">document.cookie="(.+?)";</script>', html)
# if cookie_found:
# for cookie in cookie_found:
# self.set_cookie(cookie, 'first.wifi.olleh.com')
form_found = findall('<input type="hidden" name="(.+?)" value="(.+?)">', html)
if not form_found:
return ''
data = {key: value for key, value in form_found}
self.get_response(
url='http://first.wifi.olleh.com/starbucks/index_en.html', # 폼이 전송될 곳은 정해져 있습니다.
data=data
)
return data
def step3_authorize(self, data):
"""
step2 에서 POST 전송을 보내면, 비로소 웹브라우저 화면과 유사한 사용자 동의 체크박스가 나오는 화면의 HTML 문서를 전달받습니다.
웹브라우저에서 사용자 동의 체크 박스가 나오는 화면입니다.
여기서 마지막으로 인증을 위한 POST 요청을 보내면 됩니다. 이 때 referer 필드는 중요합니다.
"""
print('data', data);
data = {
'firstflag': 'starbucks',
'branchflag': data['branchflag'] if 'branchflag' in data else '',
'lang': 'en',
'devicecode': 'pc',
'ip': data['ip'],
'secure_id': '',
'ssid': data['ssid'],
'mac': data['mac']
}
print('data', data)
response = self.get_response(
url='http://first.wifi.olleh.com/starbucks/auth_issue.php',
data=data,
referer='https://first.wifi.olleh.com/starbucks/index_kr.html'
)
return response.read().decode('utf-8').strip()
def get_response(self, url, data=None, referer=None):
if data:
data = urlencode(data).encode('utf-8')
headers = {
'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0',
'Accept': '*/*',
'Accept-Language': 'ko,en-US;q=0.7,en;q=0.3',
'Connection': 'keep-alive',
'Upgrade-Insecure-Requests': '1',
}
if referer:
headers['Referer'] = referer
request = Request(
url=url,
data=data,
headers=headers
)
return self.opener.open(request)
def set_cookie(self, cookie_string, domain):
"""
쿠키를 굽습니다. 인증 과정에 있어 중요한 요소는 아닌 것 같지만, 가급적 웹브라우저의 요청/응답과 유사하게 하기 위해 구현해 두었습니다.
"""
params = {
"version": 0,
"name": '',
"value": '',
"port": None,
"port_specified": False,
"domain": '',
"domain_specified": False,
"domain_initial_dot": False,
"path": '/',
"path_specified": True,
"secure": False,
"expires": None,
"discard": True,
"comment": None,
"comment_url": None,
"rest": {},
"rfc2109": False
}
items = cookie_string.split(';')
key_val = items[0].split('=')
name = key_val[0].strip()
value = key_val[1].strip()
params['name'] = name
params['value'] = value
for item in items[1:]:
key_val = item.split('=')
key = key_val[0].strip()
val = key_val[1].strip()
params[key] = val
params['domain'] = domain
if params['expires']:
pattern = '%a, %d %b %Y %H:%M:%S %Z'
epoch = int(time.mktime(time.strptime(params['expires'], pattern)))
params['expires'] = epoch
self.cooke_processor.cookiejar.set_cookie(Cookie(**params))
if __name__ == '__main__':
KtStarbucksAutoAuthorize().authorize()
@chwnam
Copy link
Author

chwnam commented Mar 1, 2023

2023년에도 잘 동작한다!

@Zeta611
Copy link

Zeta611 commented Jul 2, 2024

와 대박입니다..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment