token <- Sys.getenv("GITHUB_TOKEN")
svar <- request("https://api.github.com/user/repos") |>
req_auth_bearer_token(token) |>
req_perform()Aðgangsstýrðar vefþjónustur
Hvernig á að vinna með vefþjónustur sem krefjast aðgangslykils: geyma lykla utan Git, lesa þá úr umhverfisbreytum og frysta niðurstöður sem má endurbyggja síðar.
Lyklar fara aldrei í Git
Margar þjónustur krefjast aðgangslykils (e. API key eða token). Lykill er lykilorð: sá sem hefur hann getur gert allt sem þú mátt gera, í þínu nafni.
# ALDREI SVONA
svar <- request("https://api.example.is/gogn") |>
req_headers(Authorization = "Bearer LYKILLINN-MINN") |>
req_perform()Lykillinn er nú í kóðanum. Committirðu skránni er hann í Git-sögunni — og hann er þar áfram þótt þú eyðir línunni síðar, því sagan geymir allar útgáfur. Geymslur eru vaktaðar af sjálfvirkum skanna og lyklar sem lenda í opnum geymslum eru misnotaðir á mínútum.
Rétta leiðin er að geyma lykilinn í umhverfisbreytu utan geymslunnar. Í R er það .Renviron:
# ~/.Renviron — eða .Renviron í rót verkefnisins
GITHUB_TOKEN=<lykillinn-thinn-hingad>Raunverulegur GitHub-lykill byrjar á ghp_ og er 40 stafir. Slíkur strengur er hér vísvitandi ekki notaður, jafnvel sem dæmi: leyndarmálaskannar leita að því sniði og myndu flagga skjölunina. Notaðu sama hátt í þínum eigin dæmum og README-skrám.
Endurræstu R og lestu hann með Sys.getenv():
Kóðinn ber engan lykil og má fara á GitHub. Sé .Renviron í verkefnismöppunni verður hún að vera í .gitignore:
# .gitignore
.Renviron
.env
Ekki reyna að fjarlægja hann úr sögunni fyrst. Afturkallaðu hann strax hjá þjónustunni og búðu til nýjan — það gerir gamla lykilinn gagnslausan á augabragði. Að hreinsa Git-söguna er seinna verk og skiptir minna máli.
Sjá einnig öryggi á GitHub.
Dæmi: TMDB
TMDB (The Movie Database) er gott dæmi um þjónustu sem krefst lykils. Lykillinn er ókeypis fyrir persónuleg verkefni — þú sækir um hann, staðfestir að notkunin sé ekki í viðskiptaskyni, og færð hann samstundis.
Sæktu lykilinn á developer.themoviedb.org og settu hann í .Renviron (R) eða .env (Python) — aldrei í kóðann.
library(httr2)
myndir <- request("https://api.themoviedb.org/3/search/movie") |>
req_url_query(query = "Sódóma Reykjavík") |>
req_auth_bearer_token(Sys.getenv("TMDB_TOKEN")) |>
req_perform() |>
resp_body_json(simplifyVector = TRUE)
myndir$results |>
dplyr::select(title, release_date, vote_average).Renviron er lesin við ræsingu
Tvennt sem eru líklegir villuvaldar:
R les .Renviron aðeins þegar hún ræsist. Bætirðu lykli við skrána meðan R er opin gerist ekkert — þú verður að endurræsa (í RStudio: Session → Restart R).
Skráin verður að vera í þeirri möppu sem R ræsist úr. Sé .Renviron í rót verkefnisins finnur R hana aðeins ef R ræsist þar — sem er sjálfgefið þegar unnið er í RStudio-verkefni. Viltu að lykillinn gildi alls staðar seturðu hann í ~/.Renviron í heimamöppunni þinni.
Athugaðu að hann hafi lesist áður en þú sendir beiðni:
nzchar(Sys.getenv("TMDB_TOKEN")) # TRUE ef lykillinn er kominn inn[1] FALSE
Skráin þarf líka að enda á línuskilum — annars sleppir R síðustu línunni þegjandi.
import os
import requests
import pandas as pd
svar = requests.get(
"https://api.themoviedb.org/3/search/movie",
params={"query": "Sódóma Reykjavík"},
headers={"Authorization": "Bearer " + os.environ["TMDB_TOKEN"]},
timeout=30,
)
svar.raise_for_status()
pd.json_normalize(svar.json()["results"])[["title", "release_date", "vote_average"]]Í Python les python-dotenv skrána .env inn í os.environ:
pip install python-dotenvfrom dotenv import load_dotenv
load_dotenv() # les .env úr vinnumöppunniÞegar lykilinn vantar
Þetta er fyrsta sem gerist hjá öllum, og málin tvö bregðast gjörólíkt við:
Sys.getenv("TMDB_TOKEN")Hann prentar lykilinn. Væri hann keyrður á vél þar sem lykillinn er til staðar færi hann inn í úttak skjalsins — og það er í opinni geymslu. eval: false er hér öryggisráðstöfun, ekki þægindi.
Sama gildir um þinn eigin kóða: það sem búturinn prentar endar í skjalinu.
[1] ""
Sys.getenv() skilar tómum streng — engin villa, engin viðvörun. Beiðnin fer af stað með hausinn Authorization: Bearer og þjónustan svarar:
401 Invalid API key: You must be granted a valid key.
Villan bendir á lykilinn, en ekki á að hann hafi aldrei verið lesinn. Þess vegna borgar sig að athuga sjálf/ur:
token <- Sys.getenv("TMDB_TOKEN", unset = NA)
stopifnot(!is.na(token), nzchar(token))import os
os.environ["TMDB_TOKEN"]KeyError: 'TMDB_TOKEN'
Python stöðvar strax og segir nákvæmlega hvað vantar — engin beiðni fer af stað. Það er betri hegðun.
Í gagnvirkri lotu (REPL) lítur þetta þó verr út en það er. Fyrsta línan fellur, svar verður þar með aldrei til, og hver einasta lína á eftir fellur líka:
>>> svar = requests.get(..., headers={"Authorization": "Bearer " + os.environ["TMDB_TOKEN"]})
KeyError: 'TMDB_TOKEN'
>>> svar.raise_for_status()
NameError: name 'svar' is not defined
>>> pd.json_normalize(svar.json()["results"])
NameError: name 'svar' is not defined
Þrjár villur, eitt vandamál. Lestu alltaf fyrstu villuna — hinar eru bergmál af henni. NameError hér er ekki sjálfstæð villa heldur afleiðing þess að fyrsta skrefið tókst aldrei.
Viltu mýkri villuboð:
token = os.environ.get("TMDB_TOKEN")
if not token:
raise SystemExit("TMDB_TOKEN vantar — settu hann í .env og keyrðu load_dotenv().")R-hegðunin er dæmi um nákvæmlega það sem varað er við annars staðar í þessum kafla: kóðinn heldur áfram með tómt gildi og villan kemur fram löngu síðar, á stað sem bendir í ranga átt. Athugaðu því alltaf að lykillinn hafi lesist áður en þú sendir beiðnina.
Byggingarþjónninn hjá GitHub á ekki að fá kennaralykil eða nemendalykil. Ef þú vilt birta niðurstöður úr þjónustu eins og TMDB er örugga mynstrið að keyra sóknina á eigin vél, vista strípuð gögn í skrá og láta skýrsluna lesa þá skrá.
Þá fer lykillinn aldrei úr vélinni sem sótti gögnin. Það sem fer í geymsluna er kóðinn sem skýrir hvernig gögnin voru sótt og lítil gagnaskrá með því sem greiningin þarf — ekki umhverfisbreytan sjálf.
Þegar þú sækir um TMDB-lykil samþykkirðu að nota hann ekki í viðskiptaskyni. Það er raunveruleg kvöð, ekki formsatriði: lykillinn er afturkallaður sé hún brotin. Sama gildir um flestar þjónustur sem gefa ókeypis aðgang — lestu skilmálana áður en þú byggir verkefni á þeim.
TMDB krefst þess líka að getið sé heimildar þegar gögnin eru birt.
Aðgreindu lykla og gefðu lágmarksréttindi
Þegar þú býrð til lykil er oft hægt að velja hvað hann má og hve lengi hann gildir. Hér á eftir er farið yfir hvers vegna það skiptir máli og hvernig best er að gera það.
Hvers vegna lágmarksréttindi?
Veldu alltaf minnstu réttindi sem duga. Þetta kallast meginreglan um lágmarksréttindi (e. principle of least privilege). Gott er að hugsa um áhættuna af lykli sem tvo þætti sem margfaldast saman:
áhætta ≈ líkur á að lykillinn leki × tjónið sem hægt er að valda með honum
Fyrri þættinum ræður þú aldrei alveg. Lykill getur lent í Git-sögu, skjáskoti, spjallskilaboðum eða úttaki skjals, eins og sýnt er hér að ofan. Seinni þættinum ræður þú hins vegar alveg, og það gerirðu á þeirri stundu sem þú býrð lykilinn til. Lesaðgangur að opnum gögnum sem lekur er óþægilegur. Lykill sem má eyða gögnum, skrifa í geymslur eða stofna til kostnaðar getur valdið raunverulegu tjóni.
Einn lykill, einn tilgangur
Aðgreining þýðir að nota ekki sama lykilinn alls staðar. Búðu frekar til sérstakan lykil fyrir hvern tilgang:
- Hvern liðsmann. Hver og einn í hópnum sækir sinn eigin lykil og geymir hann í sinni eigin
.Renvironeða.env. Lyklum er ekki deilt í spjalli eða tölvupósti. - Hvert verkefni. Lykillinn fyrir hópverkefnið á ekki að vera sá sami og þú notar í eigin tilraunir eða önnur námskeið.
- Hvert umhverfi. Ef sjálfvirk keyrsla þarf lykil fær hún sinn eigin, ekki lykilinn af fartölvunni þinni.
Þetta borgar sig þegar eitthvað fer úrskeiðis:
- Þú getur afturkallað einn lykil án þess að brjóta allt hitt. Leki lykill eins liðsmanns þarf aðeins að skipta þeim lykli út. Aðrir í hópnum halda áfram að vinna.
- Þú sérð hvaðan notkunin kemur. Margar þjónustur sýna notkun og takmörk (e. rate limit) eftir lyklum. Hagi einn lykill sér undarlega veistu strax hvar á að leita.
- Hver lykill fær aðeins þau réttindi sem hlutverk hans krefst. Aðgreining gerir lágmarksréttindi mögulegar. Lykill sem á að þjóna öllu þarf að mega allt.
Gefðu lyklunum lýsandi nöfn þegar þjónustan leyfir, til dæmis idn302g-hopverkefni-lestur, svo auðvelt sé að sjá síðar hvaða lykil á að afturkalla.
Dæmi: fínstilltur GitHub-lykill
GitHub býður upp á fine-grained personal access tokens (undir Settings → Developer settings). Þar velurðu hvaða geymslur lykillinn nær til, hvaða réttindi hann hefur og hvenær hann rennur út:
| Stilling | Of víðtækt | Lágmarksréttindi |
|---|---|---|
| Repository access | All repositories | Aðeins sú geymsla sem verkefnið þarf |
| Permissions | Read and write á allt | Aðeins það sem þarf, t.d. Contents: Read-only |
| Expiration | No expiration | Út önnina eða skemur |
Leki lykill úr hægri dálkinum gefur hann aðeins lesaðgang að einni geymslu í takmarkaðan tíma. Leki lykill úr vinstri dálkinum getur sá sem finnur hann breytt eða eytt öllum geymslunum þínum þar til þú tekur eftir því.
Gildistími
Lykill án gildistíma er virkur þar til einhver man eftir að afturkalla hann, og það gleymist. Hópverkefnið klárast, önnin líður, en lykillinn liggur enn í gamalli .Renviron eða í Git-sögu einhvers staðar. Með gildistíma verður gleymdur lykill sjálfkrafa skaðlaus. Þegar hann rennur út býrðu einfaldlega til nýjan og setur hann í stað þess gamla.
Bjóði þjónustan ekki upp á gildistíma, eins og á við um suma ókeypis lykla, skaltu afturkalla lykilinn þegar verkefninu lýkur.
Lekur lykill þrátt fyrir allt gildir það sama og áður: afturkallaðu hann strax (sjá Hafi lykill lekið ofar á síðunni). Aðgreining og lágmarksréttindi breyta því ekki, en þau tryggja að tjónið sé lítið og að viðbrögðin séu einföld.
Gátlisti
Áður en þú notar nýjan lykil: