Mudanças entre as edições de "Go: RESTful - API-KEY"
Linha 1: | Linha 1: | ||
+ | |||
Afluentes: [[Sistemas Distribuídos e Mobile]] | Afluentes: [[Sistemas Distribuídos e Mobile]] | ||
− | = Exemplo usando api key = | + | = Exemplo usando API KEY = |
+ | Agora vamos ver um exemplo usando autenticação via api key.<syntaxhighlight lang="go"> | ||
+ | package main | ||
+ | |||
+ | import ( | ||
+ | "bufio" | ||
+ | "fmt" | ||
+ | "net/http" | ||
+ | "os" | ||
+ | ) | ||
+ | |||
+ | func main() { | ||
+ | router := http.NewServeMux() | ||
+ | |||
+ | router.HandleFunc("GET /auth", func(w http.ResponseWriter, r *http.Request) { | ||
+ | key := r.Header.Get("X-API-KEY") // Pegamos a informação X-API-KEY do cliente | ||
+ | if key != getAPIKey() { // e testamos com a informação do arquivo | ||
+ | http.Error(w, "Forbidden", http.StatusForbidden) | ||
+ | return | ||
+ | } | ||
+ | fmt.Fprintf(w, "Autentication Ok!") | ||
+ | }) | ||
+ | |||
+ | err := http.ListenAndServe("localhost:8080", router) | ||
+ | if err != nil { | ||
+ | fmt.Println(err.Error()) | ||
+ | } | ||
+ | } | ||
+ | |||
+ | // Pegamos a informação do arquivo apikey.txt que é nossa chave | ||
+ | // propriamente dita. Se não existir o arquivo ou der algum erro, | ||
+ | // retorna uma string vazia. | ||
+ | func getAPIKey() string { | ||
+ | file, err := os.Open("apikey.txt") | ||
+ | if err != nil { | ||
+ | return "" | ||
+ | } | ||
+ | defer file.Close() | ||
+ | scanner := bufio.NewScanner(file) | ||
+ | if scanner.Scan() { | ||
+ | return scanner.Text() | ||
+ | } | ||
+ | return "" | ||
+ | } | ||
+ | </syntaxhighlight>Observe que no código acima, estamos usando uma função chamada getAPIKey que busca uma informação única de um arquivo chamado apikey.txt. Caso dê algum erro, retorna uma string vazia. Então usamos essa informação para comparar com uma informação recebida da requisição, no cabeçalho, chamada <code>X-API-KEY</code>. Se forem iguais, autentica, senão fecha a aplicação e retorna um código de erro. Podemos usar o curl para testar:<syntaxhighlight lang="bash"> | ||
+ | curl -H "X-API-KEY:01234" http://localhost:8080/auth | ||
+ | </syntaxhighlight>Veja que adicionamos um cabeçalho agora. Para validar, temos que ter o arquivo <code>apikey.txt</code> com a informação <code>01234</code> dentro. | ||
+ | |||
+ | Uma '''maneira mais simples''' é colocar uma constante global e pegar a informação dessa constante. Contudo, a maneira apresentada acima permite que você possa alterar a apikey sem a necessidade de reiniciar a api. | ||
+ | |||
+ | == API KEY por Usuário == | ||
+ | Outra forma interessante é gerenciar as API KEYs por usuário, permitindo que cada usuário tenha sua própria apikey. Pode-se armazenar em um banco de dados ou arquivo json. Em banco de dados é mais recomendável, pois permite que cada usuário gerencie sua própria apikey, alterando ela quando necessário e aumentando o grau de segurança. | ||
+ | |||
+ | Então agora, nossa apikey seria um par de informações, sendo o usuário e a chave:<syntaxhighlight lang="go"> | ||
+ | // Podemos ler as informações de um arquivo JSON e jogar em um MAP | ||
+ | apiKeys := getAPIKeys("apikeys.json") | ||
+ | |||
+ | // Pegamos as informações vindas da requisição | ||
+ | user := r.Header.Get("X-User") | ||
+ | key := r.Header.Get("X-API-KEY") | ||
+ | |||
+ | // Depois validamos | ||
+ | if apiKeys[user] != key { | ||
+ | http.Error(w, "Forbidden", http.StatusForbidden) | ||
+ | return | ||
+ | } | ||
+ | </syntaxhighlight>Nesse caso, o arquivo apikeys.json ficaria mais ou menos assim:<syntaxhighlight lang="json"> | ||
+ | { | ||
+ | "user1": "apikey1", | ||
+ | "user2": "apikey2", | ||
+ | "user3": "apikey3" | ||
+ | } | ||
+ | |||
+ | </syntaxhighlight>E pra testar com curl:<syntaxhighlight lang="bash"> | ||
+ | curl -H "X-User: user1" -H "X-API-KEY: apikey1" http://localhost:8080/auth | ||
+ | </syntaxhighlight> |
Edição das 13h14min de 5 de junho de 2024
Afluentes: Sistemas Distribuídos e Mobile
Exemplo usando API KEY
Agora vamos ver um exemplo usando autenticação via api key.
package main
import (
"bufio"
"fmt"
"net/http"
"os"
)
func main() {
router := http.NewServeMux()
router.HandleFunc("GET /auth", func(w http.ResponseWriter, r *http.Request) {
key := r.Header.Get("X-API-KEY") // Pegamos a informação X-API-KEY do cliente
if key != getAPIKey() { // e testamos com a informação do arquivo
http.Error(w, "Forbidden", http.StatusForbidden)
return
}
fmt.Fprintf(w, "Autentication Ok!")
})
err := http.ListenAndServe("localhost:8080", router)
if err != nil {
fmt.Println(err.Error())
}
}
// Pegamos a informação do arquivo apikey.txt que é nossa chave
// propriamente dita. Se não existir o arquivo ou der algum erro,
// retorna uma string vazia.
func getAPIKey() string {
file, err := os.Open("apikey.txt")
if err != nil {
return ""
}
defer file.Close()
scanner := bufio.NewScanner(file)
if scanner.Scan() {
return scanner.Text()
}
return ""
}
Observe que no código acima, estamos usando uma função chamada getAPIKey que busca uma informação única de um arquivo chamado apikey.txt. Caso dê algum erro, retorna uma string vazia. Então usamos essa informação para comparar com uma informação recebida da requisição, no cabeçalho, chamada X-API-KEY
. Se forem iguais, autentica, senão fecha a aplicação e retorna um código de erro. Podemos usar o curl para testar:
curl -H "X-API-KEY:01234" http://localhost:8080/auth
Veja que adicionamos um cabeçalho agora. Para validar, temos que ter o arquivo apikey.txt
com a informação 01234
dentro.
Uma maneira mais simples é colocar uma constante global e pegar a informação dessa constante. Contudo, a maneira apresentada acima permite que você possa alterar a apikey sem a necessidade de reiniciar a api.
API KEY por Usuário
Outra forma interessante é gerenciar as API KEYs por usuário, permitindo que cada usuário tenha sua própria apikey. Pode-se armazenar em um banco de dados ou arquivo json. Em banco de dados é mais recomendável, pois permite que cada usuário gerencie sua própria apikey, alterando ela quando necessário e aumentando o grau de segurança.
Então agora, nossa apikey seria um par de informações, sendo o usuário e a chave:
// Podemos ler as informações de um arquivo JSON e jogar em um MAP
apiKeys := getAPIKeys("apikeys.json")
// Pegamos as informações vindas da requisição
user := r.Header.Get("X-User")
key := r.Header.Get("X-API-KEY")
// Depois validamos
if apiKeys[user] != key {
http.Error(w, "Forbidden", http.StatusForbidden)
return
}
Nesse caso, o arquivo apikeys.json ficaria mais ou menos assim:
{
"user1": "apikey1",
"user2": "apikey2",
"user3": "apikey3"
}
E pra testar com curl:
curl -H "X-User: user1" -H "X-API-KEY: apikey1" http://localhost:8080/auth