[Web Crawling] 폼과 로그인
폼(form, 양식) 태그와 입력(input) 태그
- 하나의 form 태그는 여러개의 input 태그를 가진다.
HTML: 폼(from) 태그
폼(from) 태그 동작 방법
1. 클라이언트
- 폼이 있는 웹페이지를 방문한다.
- 폼 내용을 입력한다.
- 폼 안에 있는 데이터를 웹 서버로 보낸다. : submit
2. 서버
- 웹 서버는 받은 폼 데이터를 처리하기 위해 웹 프로그램으로 넘긴다.
- 웹 프로그램은 폼 데이터를 처리한다.
- 처리결과에 따른 새로운 html 페이지를 웹 서버에 보낸다.
- 웹 서버는 받은 html 페이지를 브라우저에 보낸다
3. 클라이언트
- 브라우저는 받은 html 페이지를 보여줌
입력(input) 태그
입력 태그 속성
- type : 입력 태그의 유형
- value : 입력 태그의 초기값
- name : 서버로 전달되는 변수명
ex) <input type='text'> : 사용자가 문자열을 입력할 수 있다.
<input type='password'> : 사용자가 입력을 할 때 *로 대체되어서 보인다.
<input type='submit'> : 사용자가 클릭하면 서버에서 action script가 실행된다.
폼 태그 속성, 입력 태그 속성
폼 태그 속성
- action : 폼 요청을 처리할 서버 파일
- method : 폼 요청 처리 방법 -> GET or POST
입력 태그 속성
- name : <input> 태그의 name 속성들
Action URL로 변수로 전달한다.
GET : https://example.com/login?username=aaa&password=bbb
POST: https://example.com/login
항목 | GET | POST |
전송위치 | URL 뒤에 데이터가 붙는다. (쿼리스트링) | HTTP 바디에 데이터가 포함된다. |
보안 | 낮다. (URL에 정보가 노출된다.) | 상대적으로 안전하다. |
데이터 길이 제한 | 있다. (URL 길이는 제한된다.) | 거의 없다. |
사용 예시 | 검색창 | 로그인, 회원가입 |
파이썬으로 폼 전송 요청 방법
서버에 보낼 데이터 생성 (payload)
- 로그인 정보 또는 폼 입력값
-> input 태그의 name 속성값 이용
action url 생성
- <form> 태그에서 action 속성값을 추출한다.
- action 속성값을 url로 바꾼다. : urljoin
POST 요청
- action url을 생성한 딕셔너리를 첨부하여 post 방식으로 요청한다.
- 필요에 따라 요청헤더에 정보를 추가한다.
from bs4 import BeutifulSoup
import requests as rq
from urllib.parse import urljoin
url = "https://www.w3schools.com/html/tryit.asp?filename=tryhtml_input_password"
res = rq.get(url)
soup = BeautifulSoup(res.text, 'lxml')
data = {'username' : 'myid', 'pwd' : 'mypwd'} # payload 생성
action = soup.select_one('form').get('action') # from의 action 값 추출
action_url = urljoin(url, action)
action_res = rq.post(action_url, data)
soup = BeautifulSoup(action_res.text, 'lxml')
print(soup.select_one(".w3-container.w3-large.w3-border").text.strip())
로그인관련 보안
특정 웹서버들은 보안상의 이유로 로그인을 복잡하게 만든다.
-> 프로그램으로 로그인 하기 어려움
로그인 보안
- user id와 password 확인
- session id 확인 : 사용자가 가지고 있는 session id 값과 서버에 저장하고 있는 session id 값을 비교한다.
- user-agent : 확인 되지 않은 브라우저에서 요청이 오면 거부한다.
- Referer 확인 : 어떤 사이트에서 요청이 왔는지 확인한다.
- CSRF 토큰 확인 : 브라우저가 저장하고 있는 CSRF 토큰 값과 서버에 있는 값이 같은지 확인한다.
- CAPTCHA 확인 : 화면에 보이는 숫자를 입력하시오.
웹 쿠키(web cookie)
쿠키란 무엇인가?
- 웹 쿠키는 웹사이트가 사용자의 컴퓨터나 모바일 기기에 저장하는 작은 텍스트 파일이다.
- 쿠키에는 사용자의 로그인 정보, 선호하는 웹사이트 설정, 과거 방문 기록 등 다양한 정보가 저장될 수 있다.
서버에서 생성 쿠키
- 서버에서 Set-cookie 헤더에 쿠키를 생성해서 클라이언트에 보낸다. -> 클라이언트는 해당 쿠키를 보관한다.
- 인증, 로그인 유지, 사용자 식별 위해
클라이언트 생성 쿠키
- UI 설정, 팝업 여부, 간단한 정보 저장
세션(Session)
세션이란?
- 세션은 서버가 클라이언트를 식별하고 그 상태를 유지하기 위한 방법이다.
- 사용자가 웹사이트를 방문해서 접속을 시작하고 종료할 때까지의 상태 정보를 서버가 기억한다.
- 서버에서는 클라이언트를 구분하기 위해 세션ID를 부여하며 웹 브라우저가 서버에 접속해서 브라우저를 종료할 때까지 인증상태를 유지한다.
특징
- 각 클라이언트에게 고유ID를 부여한다.
- 세션ID로 클라이언트를 구분해서 클라이언트의 요구에 맞는 서비스를 제공한다.
- 사용자가 많으면 서버 메모리를 많이 차지한다.
- 로그인과 같이 보안상 중요한 작업을 수행할 때 사용한다.
import requests as rq
s = rq.Session()
항목 | 일반 요청 (rq.get(), rq.post()) | 세션 요청 (s.get(), s.post()) |
쿠키 저장 | 요청마다 새로 시작한다. | 쿠키를 저장하고 다음 요청에 자동으로 포함한다. |
헤더 재사용 | 요청마다 새로 설정한다. | 헤더를 한 번 설정하면 자동으로 계속 사용된다. |
연결 효율성 | HTTP 연결 매본 새로 만든다. | Keep-Alive 연결 재사용 |
로그인 | 어려움 | 로그인 후 세션 쿠키를 자동 저장하고 유지한다. |
login_url = 'https://example.com/login'
login_data = {'user_id' : 'myid', 'user_pw':'mypassword'}
res = s.post(login_url, login_data)
mypage_url = 'https://example.com/mypage'
res2 = s.get(mypage_url)
User-Agent 확인
- HTTP 요청 헤더 중 하나로, 클라이언트의 정보를 서버에 알려주는 역할이다.
- 일부 서버는 정상적인 브라우저에서 온 요청만 허용하고 의심스러운 User-Agent를 차단한다.
- 웹크롤러가 'python-requests','curl' 등 기본 User-Agent로 접근할 경우 차단될 수 있다.
-> 웹크롤러를 브라우저처럼 위장하는 User-Agent 설정이 필요하다. : 파이썬 feake-usragent 라이브러리
from fake_useragent import UserAgent
ua = UserAgent()
print(ua.ie) # 인터넷 익스플로러
print(ua.chrome)
print(ua.firefox)
print(ua.safari)
print(ua.random) # 랜덤한 User-Agent
headers = {'User-Agent' : ua.chrome}
user_agent = ua.Chrome
headers = {'User-Agent' : user_agent}
url = 'https://www.naver.com'
res = rq.get(url, headers=headers)
print(res.request.headers)
CSRF 공격
- 인터넷 사용자가 자신의 의자와는 무관하게 공격자가 의도한 행위를 특정 웹사이트에 요청하게 만드는 공격
CSRF 방어 방법
Referer 확인
- HTTP 요청 헤더 중 하나로, 현재 요청이 어떤 사이트에서 했는지 나타내는 정보이다.
- 요청을 보낸 이전 페이지의 URL이 담겨있어, 서버는 이 요청이 어떤 경로를 통해 왔는지 알 수 있다.
- 의심스러운 사이트에서 요청이 왔다면 요청을 거부한다.
- Referer는 조작이 가능하므로 신뢰하지 않아야 한다. -> CSRF 토큰과 함께 사용한다.
CSRF 토큰 확인
- CSRF 공격을 방지하기 위해 서버가 클라이언트에게 발급하는 임의의 난수 값이다.
- 사용자가 폼 요청을 보낼 때마다, 이 토큰과 함께 전송하게 해서 정상적인 요청인지 서버가 확인한다.
- CSRF 토큰은 자동 전송되지 않기 때문에 공격자가 사용자의 세션을 이용할 수는 있어도 토큰 값을 예측하거나 생성할 수 없다.
1. 사용자가 사이트에 접속한다. -> 서버는 세션과 함께 CSRF 토큰을 생성한다.
2. 서버는 이 토큰을 HTML 폼의 hidden input에 삽입사용자가 폼 태그를 제출한다.
3. 서버는 토큰 값을 세션에 저장된 것과 비교한다.
-> 일치하면 정상 처리, 불일치하면 요청 차단