# Cookies && Session
*Min*
---
## 先來聊聊HTTP吧
----
http本身是個無狀態(Stateless)的協議,可以在Client與Server兩端進行溝通,但是無法紀錄網路上的行為。
一般而言,今天如果要登入一個網站,每次訪問該網站時,就需要將登入帳密再輸入一次,使用起來會非常不便。
----
Cookie和Session因此誕生,解決無紀錄狀態的問題。
---
## Cookie
----
是一段由Server送給使用者瀏覽器的一小塊~~餅乾~~資料。
----
### cookie的格式 key:value

先建立一個key->test value->123的cookie
----

可以在F12 -> Application -> Cookies裡看到目前的Cookies
----
特性
* 特定網域:只針對原本的 網域(domain) 起作用。舉例: 在 \*.myExample.com 存入的 cookie,不會出現在 *.not-myExample.com
* 有生命期限: 到了所設定的生命期限之後會失效。
---
## Session
----
Session 負責紀錄在 server端上的使用者訊息,存下所需的用戶資料,接著產生一組對應的ID,存入 cookie 後傳回用戶端。
----
在server端設定session

client端會得到 session ID

----
server端就能透過session ID取得user的值了


---
## 這樣講感覺有點枯燥
----
## 我們來實戰看看吧
還記得之前綱庭教過的爬蟲嗎 [連結](https://hackmd.io/@fan9704/rJzCRdMnt#/6/2)
----
安裝一下pipenv跟Requests吧
```bash=
pip3 install pipenv #安裝pipenv
mkdir crawler_test #建立專案資料夾
cd crawler_test
pipenv shell #pipenv初始化專案資料夾
pipenv install requests
pipenv install bs4
```
---
## 來做一個雲科單一爬蟲吧
----
先試試直接拜訪首頁的話
會發生什麼事

----
### 接著點開F12 -> network來看看他是怎麼登入的
----
似乎是對這個網頁post一筆資料過去

----
接著點進payload來看究竟送了什麼

----
__RequestVerificationToken ???
----
```python=
loginURL = "https://webapp.yuntech.edu.tw/YuntechSSO/Account/Login"
r = requests.get(loginURL)
tokenDOM = BeautifulSoup(r.text, "html.parser").select_one("input[name='__RequestVerificationToken']")
print(tokenDOM["value"])
```
----
把剛剛__RequestVerificationToken帶進去
```python=
payload = {
"__RequestVerificationToken": tokenDOM["value"],
"pRememberMe": False,
"RedirectTo": "",
"redirectUrl": "",
"pLoginName": "B10900000",
"pLoginPassword": "p@ssW05d"
}
loginRes = requests.post(loginURL, data=payload)
print(loginRes.text)
```
就可以登入了
嗎?
---
## 好像還是不行,那我們到底還缺了什麼呢
----
## 沒錯 cookie
由於__RequestVerificationToken是跟cookie綁在一起的
----
要登入時也要把一開始的cookie帶進去
```python=
loginRes = requests.post(loginURL, data=payload, cookies=r.cookies)
```
----
完整程式碼
```python
import requests
from bs4 import BeautifulSoup
def main():
loginURL = "https://webapp.yuntech.edu.tw/YuntechSSO/Account/Login"
r = requests.get(loginURL)
tokenDOM = BeautifulSoup(
r.text,
"html.parser").select_one("input[name='__RequestVerificationToken']")
payload = {
"__RequestVerificationToken": tokenDOM["value"],
"pRememberMe": False,
"RedirectTo": "",
"redirectUrl": "",
"pLoginName": "B10900000",
"pLoginPassword": "p@ssW05d"
}
loginRes = requests.post(loginURL, data=payload, cookies=r.cookies)
print(loginRes.text)
if "__main__" == __name__:
main()
```
----
不想一直把cookie帶著怎麼辦
或許可以試試看session
```python
import requests
from bs4 import BeautifulSoup
def main():
loginURL = "https://webapp.yuntech.edu.tw/YuntechSSO/Account/Login"
session = requests.session()
r = session.get(loginURL)
tokenDOM = BeautifulSoup(
r.text,
"html.parser").select_one("input[name='__RequestVerificationToken']")
payload = {
"__RequestVerificationToken": tokenDOM["value"],
"pRememberMe": False,
"RedirectTo": "",
"redirectUrl": "",
"pLoginName": "B10900000",
"pLoginPassword": "p@ssW05d"
}
loginRes = session.post(loginURL, data=payload)
print(loginRes.text)
if "__main__" == __name__:
main()
```
---
## 延伸閱讀
[一個搶課機器人](https://github.com/kukina622/yuntech-course-crawler)
[一些安全問題](https://devco.re/blog/2014/06/11/setcookie-httponly-security-issues-of-http-headers-3/)
----
## 接著明年就換你們教課了
## 加油哦 d(`・∀・)b
{"metaMigratedAt":"2023-06-17T01:52:53.897Z","metaMigratedFrom":"YAML","title":"Cookies && Session","breaks":true,"slideOptions":"{\"transition\":\"slide\"}","contributors":"[{\"id\":\"cfefc38e-571b-4baa-8dd1-9a75490e7f5f\",\"add\":3905,\"del\":36}]"}