Web3js
驗證使用者是否真正擁有該地址
Web3js 前端和 Vue,.NET Core 和 Nethereum 在後面。
此功能的關鍵目標是在前端對消息進行簽名,將簽名和地址發送到後端以驗證他確實擁有該地址。
問題是我不斷得到不同的地址結果。這絕對意味著我的程式碼的某些部分是錯誤的。任何人都可以發現問題嗎?<3
出於開發測試的目的,我暫時將原始消息添加為 API 的一部分。
- 前端
// Modern dapp browsers... if (window.ethereum) { // Propagate Web3 window.web3 = new Web3(ethereum); await window.ethereum.enable(); window.ethereum.autoRefreshOnNetworkChange = false; // Obtain the user accounts let authMsg = 'This is a Nozomi auth message'; let accounts = await window.web3.eth.getAccounts(); // Ensure that the user is holding the wallet/s by asking him to unlock his // account with a random message. // https://ethereum.stackexchange.com/questions/48489/how-to-prove-that-a-user-owns-their-public-key-for-free= if (accounts != null && accounts.length > 0) { // https://stackoverflow.com/questions/37576685/using-async-await-with-a-foreach-loop // await Promise.all(accounts.map(async (account) => { // })); let shaMsg = window.web3.utils.sha3(authMsg); let signed = await window.web3.eth.accounts.sign(accounts[0], shaMsg, function (err, sig) { console.dir("Signature: " + sig); this.$buefy.notification.open({ duration: 5000, message: `There was an error signing the validation request.`, position: 'is-bottom-right', type: 'is-danger', hasIcon: true }); }); console.dir("User signed data: "); console.dir(signed); // Validate the signed object on server side and provide an auth let result = await axios({ method: 'post', headers: { "Content-Type": "application/json"}, url: '/api/auth/ethauth', data: { "claimerAddress": accounts[0], "signature": signed.signature, "rawMessage": authMsg } }).then(function (response) { console.log(response); }).catch(function (error) { console.log(error); }); console.dir("result: " + result); } }
- 後端
public bool ValidateOwner(ValidateOwnerQuery request) { // Null Checks var addrValidator = new AddressUtil(); if (request == null || string.IsNullOrEmpty(request.RawMessage) || string.IsNullOrEmpty(request.Signature) || addrValidator.IsAnEmptyAddress(request.ClaimerAddress) || !addrValidator.IsValidEthereumAddressHexFormat(request.ClaimerAddress)) return false; // Check for validity var signer = new EthereumMessageSigner(); var resultantAddr = signer.EncodeUTF8AndEcRecover(request.RawMessage, request.Signature); return !addrValidator.IsAnEmptyAddress(resultantAddr) && resultantAddr.Equals(request.ClaimerAddress); }
不要使用 web3.eth.accounts API,而是使用 web3.eth.personal 來簽署消息,因為您使用的是使用者的地址來簽署消息,而不是他/她的私鑰。
使用 web3.personal.sign 在伺服器上進行 MetaMask 驗證
代替
let signed = await window.web3.eth.accounts.sign(accounts[0], shaMsg, function (err, sig) { console.dir("Signature: " + sig); });
做
let signed = await window.web3.eth.personal.sign(authMsg, accounts[0], function (err, sig) { console.dir("Signature: " + sig); });