Authentifizierung und API-Sicherheit
Fügen Sie API-Schlüsselvalidierung, CORS-Header und Filter zur Ratenbegrenzung hinzu
Authentifizierung und API-Sicherheit ist eine kostenlose R Academy-Lektion auf CoddyKit. Dies ist Lektion 3 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des R Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der R Academy-Kurs umfasst insgesamt 4 Lektionen.
Warum API-Sicherheit wichtig ist
Eine Plumber-API ist ein öffentlicher HTTP-Server. Ohne Authentifizierung kann jeder, der den Port erreichen kann, Ihre Endpunkte aufrufen. Zu den Sicherheitsebenen gehören Authentifizierung (wer sind Sie?), Autorisierung (was dürfen Sie tun?), Eingabevalidierung und Transportsicherheit.
Plumber-Filter als Middleware
Filter in Plumber werden vor dem Routen-Handler ausgeführt. Verwenden Sie pr_filter(name, function(req, res){...}), um Middleware hinzuzufügen, die jede Anfrage untersucht. Rufen Sie plumber::forward() auf, um an den nächsten Filter oder die Route weiterzuleiten; geben Sie frühzeitig zurück, um die Anfrage abzulehnen.
# library(plumber)
# pr <- plumb('api.R')
# pr |>
# pr_filter('logger', function(req, res) {
# cat(req$REQUEST_METHOD, req$PATH_INFO, '
')
# plumber::forward() # must call to continue
# }) |>
# pr_run(port = 8000)Authentifizierungsfilter mit API-Schlüssel
Das gängigste einfache Authentifizierungsmuster für Server-zu-Server-APIs ist ein statischer API-Schlüssel, der in einem Header übergeben wird. Der Filter prüft den Header bei jeder Anfrage und gibt 401 zurück, wenn er fehlt oder ungültig ist.
# In api.R:
# VALID_KEY <- Sys.getenv('API_SECRET_KEY')
#
# #* @filter auth
# function(req, res) {
# key <- req$HTTP_X_API_KEY
# if (is.null(key) || key != VALID_KEY) {
# res$status <- 401L
# return(list(error = 'Unauthorized'))
# }
# plumber::forward()
# }Authorization-Header prüfen
Bearer-Token werden im Header Authorization: Bearer <token> übergeben. Greifen Sie über req$HTTP_AUTHORIZATION darauf zu. Zerlegen Sie ihn mit strsplit(), um den Token-Teil zu extrahieren, und validieren Sie ihn anschließend gegen Ihren Speicher.
# #* @filter bearer_auth
# function(req, res) {
# auth_header <- req$HTTP_AUTHORIZATION
# if (is.null(auth_header) || !startsWith(auth_header, 'Bearer ')) {
# res$status <- 401L
# return(list(error = 'Bearer token required'))
# }
# token <- substring(auth_header, 8) # strip 'Bearer '
# if (!token_is_valid(token)) {
# res$status <- 401L
# return(list(error = 'Invalid token'))
# }
# plumber::forward()
# }Authentifizierung mit #* @preempt überspringen
Einige Endpunkte (etwa für Health-Checks oder öffentliche Dokumentation) sollten die Authentifizierung überspringen. Annotieren Sie sie mit #* @preempt auth, wobei auth dem Namen des Filters entspricht. Plumber leitet die Anfrage direkt an den Handler weiter und umgeht diesen Filter.
# #* Health check — no auth required
# #* @preempt auth
# #* @get /ping
# function() {
# list(status = 'ok', time = as.character(Sys.time()))
# }
#
# #* Protected endpoint — goes through auth filter
# #* @get /data
# function() {
# list(secret = 'sensitive data')
# }CORS mit pr_cors()
Wenn Ihre API von einem Browser unter einer anderen Domain aufgerufen wird, müssen Sie CORS (Cross-Origin Resource Sharing) aktivieren. Verwenden Sie pr_cors(), um zulässige Ursprünge, Methoden und Header zu konfigurieren, ohne rohe Header manuell schreiben zu müssen.
# library(plumber)
# pr <- plumb('api.R')
# pr |>
# pr_cors(
# origin = 'https://myapp.example.com',
# methods = c('GET', 'POST'),
# headers = c('Content-Type', 'X-API-Key'),
# credentials = TRUE
# ) |>
# pr_run(port = 8000)Eingaben bereinigen – Benutzereingaben niemals vertrauen
Validieren und bereinigen Sie Eingaben immer, bevor Sie sie in Abfragen oder Dateioperationen verwenden:
- Typ prüfen:
is.numeric(),is.character() - Wertebereich prüfen:
id >= 1 && id <= 1e9 - Unerwartete Zeichen ablehnen:
grepl('[^a-zA-Z0-9_]', name) - Benutzerzeichenfolgen niemals direkt in SQL einsetzen – verwenden Sie parametrisierte Abfragen
# #* @post /search
# function(req, res) {
# body <- jsonlite::fromJSON(req$postBody)
# query <- body$query
# if (!is.character(query) || nchar(query) > 200) {
# res$status <- 400L
# return(list(error = 'query must be a string <= 200 chars'))
# }
# if (grepl('[;\'"]', query)) {
# res$status <- 400L
# return(list(error = 'Invalid characters in query'))
# }
# list(results = search_db(query))
# }Konzepte zur Ratenbegrenzung
Plumber verfügt über keine integrierte Ratenbegrenzung. Sie können jedoch eine solche Begrenzung in einem Filter mit einer gemeinsam genutzten Umgebung implementieren, um die Anzahl der Anfragen pro IP-Adresse zu verfolgen:
- Zeitstempel jeder Anfrage pro IP-Adresse in einer R-Umgebung speichern
- Mit 429 ablehnen, wenn die Anzahl innerhalb des Zeitfensters das Limit überschreitet
- Verwenden Sie in der Produktion einen Reverse-Proxy wie nginx zur Ratenbegrenzung
# request_log <- new.env()
#
# #* @filter rate_limit
# function(req, res) {
# ip <- req$REMOTE_ADDR
# now <- as.numeric(Sys.time())
# if (!exists(ip, envir = request_log)) assign(ip, c(), envir = request_log)
# times <- get(ip, envir = request_log)
# times <- times[times > now - 60] # last 60 seconds
# if (length(times) >= 60) { res$status <- 429L; return(list(error='Too Many Requests')) }
# assign(ip, c(times, now), envir = request_log)
# plumber::forward()
# }API-Schlüssel sicher speichern
Speichern Sie Geheimnisse niemals fest im Quellcode. Legen Sie sie in Umgebungsvariablen ab und lesen Sie sie beim Start mit Sys.getenv() ein. Verwenden Sie lokal eine .env-Datei (von git ausgeschlossen) und fügen Sie Geheimnisse in der Produktion über die Deployment-Umgebung ein.
# In .env (never commit this file):
# API_SECRET_KEY=my_super_secret_key_here
#
# In api.R:
# VALID_KEY <- Sys.getenv('API_SECRET_KEY', unset = '')
# if (nchar(VALID_KEY) == 0) stop('API_SECRET_KEY not set')
#
# Load .env locally (devtools::load_dot_env or Sys.setenv):
# readRenviron('.env')
cat('Sys.getenv reads API keys without exposing them in source
')Benutzerkontext an die Anfrage anhängen
Hängen Sie nach der Validierung eines Tokens im Authentifizierungsfilter die entschlüsselten Benutzerinformationen an das req-Objekt an, damit nachgelagerte Handler darauf zugreifen können, ohne sie erneut zu validieren. Benutzerdefinierte Felder in req bleiben während der gesamten Filterkette erhalten.
# #* @filter auth
# function(req, res) {
# token <- req$HTTP_AUTHORIZATION
# user <- validate_token(token) # returns list(id=1, role='admin')
# if (is.null(user)) { res$status <- 401L; return(list(error='Unauthorized')) }
# req$user <- user # attach to request
# plumber::forward()
# }
#
# #* @get /profile
# function(req) {
# list(user_id = req$user$id, role = req$user$role)
# }Fehlerbehandlung mit tryCatch
Umschließen Sie Ihre Endpunktlogik mit tryCatch(), um unerwartete Fehler abzufangen und eine saubere 500-Antwort zurückzugeben, anstatt den Worker abstürzen zu lassen oder dem Aufrufer einen Stacktrace preiszugeben.
# #* @get /risky/<id:int>
# function(id, res) {
# tryCatch({
# result <- risky_db_call(id)
# list(data = result)
# }, error = function(e) {
# message('Error in /risky: ', conditionMessage(e))
# res$status <- 500L
# list(error = 'Internal server error')
# })
# }Schnelltest: @preempt-Annotation
Was bewirkt die Annotation #* @preempt auth bei einem Plumber-Endpunkt?
Zusammenfassung: API-Sicherheit
Die Absicherung einer Plumber-API umfasst mehrere Schutzebenen:
pr_filter('auth', ...)– jede Anfrage in der Middleware untersuchenreq$HTTP_AUTHORIZATION/req$HTTP_X_API_KEY– Authentifizierungs-Header auslesen#* @preempt auth– Authentifizierung für öffentliche Endpunkte überspringenpr_cors()– domänenübergreifenden Browserzugriff konfigurieren- Eingaben vor jeder Datenbank- oder Dateioperation validieren
Sys.getenv()für Geheimnisse verwenden – Schlüssel niemals fest im Code hinterlegen
Häufig gestellte Fragen
Ist die Lektion „Authentifizierung und API-Sicherheit“ kostenlos?
Ja — der vollständige Text von „Authentifizierung und API-Sicherheit“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des R Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der R Academy-Kurs umfasst insgesamt 4 Lektionen.
Was lerne ich in „Authentifizierung und API-Sicherheit“?
Fügen Sie API-Schlüsselvalidierung, CORS-Header und Filter zur Ratenbegrenzung hinzu Du übst R Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.
Brauche ich Erfahrung, um R Academy zu starten?
Keine Vorkenntnisse erforderlich. R Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 3 von 4.
Wie lange dauert die Lektion „Authentifizierung und API-Sicherheit“?
Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.
Kann ich in dieser R Academy-Lektion Code schreiben und ausführen?
Ja. Jede R Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.
Alle Lektionen in diesem Kurs
- Einführung in Plumber und REST
- GET- und POST-Endpunkte erstellen
- Authentifizierung und API-Sicherheit
- Plumber-APIs in der Produktion bereitstellen