Aula 08 – Golang para Web – Senhas Encriptadas com Hashing
Aula 08 – Golang para Web – Senhas Encriptadas com Hashing
Voltar para página principal do blog
Todas as aulas desse curso
Aula 07 Aula 09
Se gostarem do conteúdo dêem um joinha 👍 na página do Código Fluente no
Facebook
Link do código fluente no Pinterest
Meus links de afiliados:
Hostinger
Digital Ocean
One.com
Código da aula: Github
Melhore seu NETWORKING
Participe de comunidades de desenvolvedores:
Fiquem a vontade para me adicionar ao linkedin.
E também para me seguir no GITHUB.
Ah, se puder, clica na estrela nos meus repositórios pra dá uma força ao meu perfil no GITHUB.
Senhas encriptadas usando bcrypt
Utilizaremos o bcrypt para manipular a autenticação de senha dos usuários.
A ideia básica é que você nunca armazene a senha do usuário no seu banco de dados, ao invés disso, sempre aplique uma função de hash.
Ela é um tipo especial de função unidirecional que transforma o senha do usuário em um novo valor que não pode ser facilmente revertido para recuperar.
Esse valor de transformado pela função de hash é o que a gente armazena no banco de dados.
Quando o usuário faz o login, a mesma transformação é aplicada para a senha, o resultado é comparado com o que foi armazenado no banco de dados e se o resultado é o mesmo que o valor armazenado, o login é feito.
Dessa forma, se um invasor tiver acesso ao seu banco de dados, eles só conseguirão ver as senhas com o hash.
Eles podem até tentar quebrar as senhas usando força bruta, tentando combinações diferentes e aplicando a mesma função hash que usamos até tentar encontrar.
Mas, algoritmos como bcrypt, são projetados com um parâmetro de custo que nos permite ajustar quanto poder computacional o hash vai precisar.
Isso permite aumentar o custo dos hashes para que fique mais difícil ainda quebrar as senhas com força bruta.
Instalação do bcrypt
Digite no terminal:
go get golang.org/x/crypto/bcrypt
Agora podemos importar ele no código.
Veja as modificações que iremos fazer nessa aula:
Vamos deletar a função testGetHandler que fizemos na aula passada.
Vamos adicionar dois novos manipuladores ao nosso aplicativo para registrar novos usuários, o registerGetHandler e o registerPostHandler.
E também o register.html na pasta de templates.
Vamos alterar a login.html para inserir o campo de senha.
Vamos também pegar uma sessão existente ou criar uma nova no indexGetHandler usando o store.Get.
Existem melhores maneiras de lidar com isso, diferente de como vamos fazer nessa aula, porque essa abordagem tem algumas falhas, uma delas é que estamos forçando o usuário a estar logado, para acessar a página principal.
Você poderá perceber, que quando entrar na:
localhost:8000/register
Vai ser redirecionado para a página de login.
A gente vai melhorar isso mais na frente.
Então partiu código! 💻🤘🏻
Veja os códigos.
web_app/templates/register.html
<!DOCTYPE html>
<html>
<head>
<title>Register</title>
</head>
<body>
<form method="POST">
<div>Username: <input name="username"></div>
<div>Password: <input name="password"></div>
<div>
<button type="submit">Register</button>
</div>
</form>
</body>
</html>
web_app/templates/login.html
<!DOCTYPE html>
<html>
<head>
<title>Login</title>
</head>
<body>
<form method="POST">
<div>Username: <input name="username"></div>
<div>Password: <input name="password"></div>
<div>
<button type="submit">Login</button>
</div>
</form>
</body>
</html>
Seguindo
web_app/main.go
package main
import (
"html/template"
"net/http"
"github.com/go-redis/redis"
"github.com/gorilla/mux"
"github.com/gorilla/sessions"
"golang.org/x/crypto/bcrypt"
)
//globals variables
var client *redis.Client
var store = sessions.NewCookieStore([]byte("t0p-s3cr3t"))
var templates *template.Template
func main() {
client = redis.NewClient(&redis.Options{
Addr: "localhost:6379",
})
templates = template.Must(template.ParseGlob("templates/*.html"))
r := mux.NewRouter()
r.HandleFunc("/", indexGetHandler).Methods("GET")
r.HandleFunc("/", indexPostHandler).Methods("POST")
r.HandleFunc("/login", loginGetHandler).Methods("GET")
r.HandleFunc("/login", loginPostHandler).Methods("POST")
r.HandleFunc("/register", registerGetHandler).Methods("GET")
r.HandleFunc("/register", registerPostHandler).Methods("POST")
fs := http.FileServer(http.Dir("./static/"))
r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", fs))
http.Handle("/", r)
http.ListenAndServe(":8080", nil)
}
//request hello handle
func indexGetHandler(w http.ResponseWriter, r *http.Request) {
session, _ := store.Get(r, "session")
_, ok := session.Values["username"]
if !ok {
http.Redirect(w, r, "/login", 302)
return
}
comments, err := client.LRange("comments", 0, 10).Result()
if err != nil {
return
}
templates.ExecuteTemplate(w, "index.html", comments)
}
func indexPostHandler(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
comment := r.PostForm.Get("comment")
client.LPush("comments", comment)
http.Redirect(w, r, "/", 302)
}
func loginGetHandler(w http.ResponseWriter, r *http.Request) {
templates.ExecuteTemplate(w, "login.html", nil)
}
func loginPostHandler(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
username := r.PostForm.Get("username")
password := r.PostForm.Get("password")
hash, err := client.Get("user: " + username).Bytes()
if err != nil {
return
}
err = bcrypt.CompareHashAndPassword(hash, []byte(password))
if err != nil {
return
}
session, _ := store.Get(r, "session")
session.Values["username"] = username
session.Save(r, w)
http.Redirect(w, r, "/", 302)
}
func registerGetHandler(w http.ResponseWriter, r *http.Request) {
templates.ExecuteTemplate(w, "register.html", nil)
}
func registerPostHandler(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
username := r.PostForm.Get("username")
password := r.PostForm.Get("password")
cost := bcrypt.DefaultCost
hash, err := bcrypt.GenerateFromPassword([]byte(password), cost)
if err != nil {
return
}
client.Set("user: "+username, hash, 0)
http.Redirect(w, r, "/login", 302)
}
//request contact page handle
func contactHandler(w http.ResponseWriter, r *http.Request) {
templates.ExecuteTemplate(w, "contact.html", "This is the contact page!")
}
//request about page handle
func aboutHandler(w http.ResponseWriter, r *http.Request) {
templates.ExecuteTemplate(w, "about.html", "This is the about page!")
}