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

Tutorial Go para Web com Redis

Go para Web usando Redis

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.


<!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>

<!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


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!")
}

Acesse:

localhost:8000

Por agora é só, nos vemos próxima. 😉

Código da aula: Github

Voltar para página principal do blog

Todas as aulas desse curso

Aula 06                       Aula 08

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

Novamente deixo meus link de afiliados:

Hostinger

Digital Ocean

One.com

Obrigado, até a próxima e bons estudos. 😉

About The Author
-

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>