前端使用bcrypt對密碼加密,服務器對密碼進行校驗


以前為了防止前端密碼安全問題,都是對密碼進行md5(password + salt)。
有些也會用別的加密方式,但還是會存在撞庫,彩虹表等破解常規密碼。
因此使用bcrypt加密是一個不錯的選擇,因為每次加密都會隨機salt,每次加密結果都不一樣,相對安全性更高些。

下面是一個示例代碼,啟動一個http服務器,瀏覽器輸入http://127.0.0.1:8080,當填入密碼與服務器一致時提示成功,不一致時報錯。

package main

import (
	"flag"
	"fmt"
	"golang.org/x/crypto/bcrypt"
	"net/http"
)

func main() {
	pass := flag.String("p", "admin", "check password")
	flag.Parse()
	password := []byte(*pass)

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		w.Write(html)
	})
	http.HandleFunc("/users/login", func(w http.ResponseWriter, r *http.Request) {
		hashedPassword := r.FormValue("pass")
		fmt.Println(hashedPassword)
		err := bcrypt.CompareHashAndPassword([]byte(hashedPassword), password)
		if err != nil {
			fmt.Fprintln(w, err)
		} else {
			fmt.Fprintln(w, "password ok")
		}
	})
	http.ListenAndServe(":8080", nil)
}

var html = []byte(`<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="https://cdn.jsdelivr.net/gh/dcodeIO/bcrypt.js/dist/bcrypt.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/gh/jquery/jquery@3.2.1/dist/jquery.min.js"></script>
</head>
<body>
<p>密碼: <input id="pass" type="password" name="pass"/></p>
<button type="button" onclick="login()">提交</button>
<script type="text/javascript">
function login() {
	/* https://github.com/dcodeIO/bcrypt.js */
	var bcrypt = dcodeIO.bcrypt;
	/* 將密碼加密提交 */
	$.post('/users/login',{pass: bcrypt.hashSync($('#pass').val(), 8)},
        function(result) {
            alert(result);
        }
    );
}
</script>
</body>
</html>`)

該方案實際還是有一個問題,就是前端加密傳輸的文本是無法解密的。服務器只能用正確的密碼同前端傳上去的密文進行相同的加密規則比較密文是否一致。
此時服務器要么存明文密碼,要么對密碼做非對稱加密,因為服務器是需要明文密碼。以前使用md5值hash時,服務器直接存hash后的字符串,因此是沒有問題的。
服務器存明文會存在密碼泄露的風險,對密碼做非對稱或對稱加密都會對服務器造成一些性能損耗。而且最終密碼是可破解的。
有想過一個方案就是,前端初始獲取rsa公鑰,密碼使用公鑰加密,服務器使用私鑰解密,然后把密碼進行hash與數據庫里面的hash值比較。有些人覺得這是多此一舉。
總之各個方案都有各個方案的優缺點吧。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM