Ethers.js 签名认证
核心:通过后端获取随机数,拿到随机数后进行签名,再次请求后端验证随机数是否一致,一致则代表签名正确。
const main = async () => {
const provider = new ethers.BrowserProvider(window.ethereum);
await window.ethereum.request({
method: "eth_requestAccounts",
});
const signer = await provider.getSigner();
const address = signer.address;
const nonce = auth(state.address);
const signature = await signer.signMessage(nonce.toString());
const signStatus = verify(state.address, signature);
console.log(signStatus);
};
// 服务端方法模拟
const auth = (address) => {
let user = users[address];
if (!user) {
user = {
address,
nonce: Math.floor(Math.random() * 10000000),
};
users[address] = user;
} else {
const nonce = Math.floor(Math.random() * 10000000);
user.nonce = nonce;
users[address] = user;
}
return user.nonce;
};
const verify = (address, signature) => {
let signValid = false;
console.log(`address: ${address}`);
//从数据库中取出nonce
let nonce = users[address].nonce;
//验证对nonce进行签名的地址
const decodedAddress = ethers.verifyMessage(
nonce.toString(),
signature.toString()
);
//比较地址和签名的地址是否一致
if (address.toLowerCase() === decodedAddress.toLowerCase()) {
signValid = true;
//出于安全原因,更改nonce,防止下次直接使用相同的nonce进行登录
users[address].nonce = Math.floor(Math.random() * 10000000);
}
return signValid;
};