Autenticazione e sicurezza delle API
Aggiunga la convalida delle chiavi API, le intestazioni CORS e i filtri per la limitazione del numero di richieste
Autenticazione e sicurezza delle API è una lezione R Academy gratuita su CoddyKit. Questa è la lezione 3 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento R Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso R Academy include 4 lezioni in totale.
Perché la sicurezza delle API è importante
Un'API Plumber è un server HTTP pubblico. Senza autenticazione, chiunque possa raggiungere la porta può chiamare i Suoi endpoint. I livelli di sicurezza includono autenticazione (chi è Lei?), autorizzazione (che cosa può fare?), convalida degli input e sicurezza del trasporto.
I filtri Plumber come middleware
I filtri in Plumber vengono eseguiti prima del gestore della route. Utilizzi pr_filter(name, function(req, res){...}) per aggiungere un middleware che ispeziona ogni richiesta. Chiami plumber::forward() per passare al filtro o alla route successiva; restituisca subito un risultato per rifiutare la richiesta.
# 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)Filtro di autenticazione con chiave API
Il pattern di autenticazione semplice più comune per le API server-to-server consiste nel passare una chiave API statica in un header. Il filtro controlla l'header a ogni richiesta e restituisce 401 se manca o non è corretto.
# 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()
# }Controllare l'header Authorization
I token Bearer vengono passati nell'header Authorization: Bearer <token>. Vi si accede tramite req$HTTP_AUTHORIZATION. Esegua l'analisi con strsplit() per estrarre la parte contenente il token, quindi lo convalidi rispetto al proprio archivio.
# #* @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()
# }Ignorare l'autenticazione con #* @preempt
Alcuni endpoint, come i controlli dello stato e la documentazione pubblica, dovrebbero ignorare l'autenticazione. Li annoti con #* @preempt auth, dove auth corrisponde al nome del filtro. Plumber indirizza la richiesta direttamente al gestore, ignorando quel filtro.
# #* 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 con pr_cors()
Se la Sua API viene chiamata da un browser su un dominio diverso, deve abilitare CORS (Cross-Origin Resource Sharing). Utilizzi pr_cors() per configurare origini, metodi e header consentiti senza scrivere manualmente gli header grezzi.
# 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)Sanificazione degli input — non si fidi mai degli input dell'utente
Convalidi e sanifichi sempre gli input prima di utilizzarli nelle query o nelle operazioni sui file:
- Controlli il tipo:
is.numeric(),is.character() - Controlli l'intervallo:
id >= 1 && id <= 1e9 - Rifiuti i caratteri imprevisti:
grepl('[^a-zA-Z0-9_]', name) - Non inserisca mai direttamente le stringhe dell'utente in SQL: utilizzi query parametrizzate
# #* @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))
# }Concetti di limitazione della frequenza
Plumber non dispone di un limitatore di frequenza integrato, ma può implementarne uno in un filtro utilizzando un ambiente condiviso per tenere traccia del numero di richieste per IP:
- Registri nell'ambiente R il timestamp di ogni richiesta per IP
- Rifiuti la richiesta con 429 se il conteggio supera il limite nella finestra temporale
- In produzione, utilizzi un reverse proxy come nginx per la limitazione della frequenza
# 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()
# }Memorizzare le chiavi API in modo sicuro
Non inserisca mai i segreti direttamente nei file sorgente. Li memorizzi nelle variabili d'ambiente e li legga all'avvio con Sys.getenv(). Utilizzi localmente un file .env (escluso da git) e in produzione inietti i segreti tramite l'ambiente di deployment.
# 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
')Associare il contesto dell'utente alla richiesta
Dopo aver convalidato un token nel filtro di autenticazione, associ le informazioni decodificate sull'utente all'oggetto req, in modo che i gestori successivi possano accedervi senza ripetere la convalida. I campi personalizzati di req persistono lungo la catena di filtri.
# #* @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)
# }Gestione degli errori con tryCatch
Racchiuda la logica dell'endpoint in tryCatch() per intercettare gli errori imprevisti e restituire una risposta 500 corretta invece di causare l'arresto del worker o rivelare una traccia dello stack al chiamante.
# #* @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')
# })
# }Verifica rapida: annotazione @preempt
Che cosa fa l'annotazione #* @preempt auth a un endpoint Plumber?
Riepilogo della sicurezza delle API
La protezione di un'API Plumber richiede difese su più livelli:
pr_filter('auth', ...)— ispeziona ogni richiesta nel middlewarereq$HTTP_AUTHORIZATION/req$HTTP_X_API_KEY— legge gli header di autenticazione#* @preempt auth— ignora l'autenticazione per gli endpoint pubblicipr_cors()— configura l'accesso cross-origin dai browser- Convalida degli input prima di qualsiasi operazione sul DB o sui file
Sys.getenv()per i segreti — non inserisca mai le chiavi direttamente nel codice
Impara R con un tutor IA — gratis
Scrivi ed esegui vero codice nel tuo browser, ricevi aiuto istantaneo da un tutor IA disponibile 24/7, e riprendi da dove hai lasciato sul web o nell'app.
- Corsi
- 43
- Lezioni
- 159
Domande Frequenti
La lezione «Autenticazione e sicurezza delle API» è gratuita?
Sì — il testo completo di «Autenticazione e sicurezza delle API» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso R Academy, passa a CoddyKit PRO. Il corso R Academy include 4 lezioni in totale.
Cosa imparerò in «Autenticazione e sicurezza delle API»?
Aggiunga la convalida delle chiavi API, le intestazioni CORS e i filtri per la limitazione del numero di richieste Eserciti R Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare R Academy?
Non è richiesta alcuna esperienza precedente. R Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 4.
Quanto tempo richiede la lezione «Autenticazione e sicurezza delle API»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione R Academy?
Sì. Ogni lezione R Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Introduzione a Plumber e REST
- Creazione di endpoint GET e POST
- Autenticazione e sicurezza delle API
- Distribuzione in produzione delle API Plumber