MFA
概念:通过两种以上的认证机制之后,才能得到授权
本文以两步验证为例进行说明
期约连锁
期约连锁就是一个期约接一个期约地拼接。之所以可以这样做,是因为每个期约实例的方法(then()、catch()和finally())都会返回一个新的期约对象,而这个新期约又有自己的实例方法。这样连缀方法调用就可以构成所谓的“期约连锁”。
实现MFA
利用期约本身的状态(待定pending、落定settled)及期约连锁可以实现MFA。在首次认证之后连缀调用二次认证,最后连缀调用登录成功的回调。
而在首次认证之后可以通过再返回一个待定期约实例来等待二次认证,因为连锁的期约会因为该实例的待定状态而暂停,直到完成二次认证后该实例转为落定状态。
//JavaScript
const signInDiv = document.getElementById('signInDiv');
const mfaDiv = document.getElementById('mfaDiv');
const loginInfo = document.getElementById('loginInfo');
function firstAuth(callback) {
Promise.resolve()
.then(callback)
.then(res => loginInfo.innerText = res);
}
function secondAuth() {
return Promise.resolve('Logined!');
}
function singIn() {
firstAuth(res => new Promise(resolve => {
addConfirm(resolve);
mfaDiv.style.display = 'block';
signInDiv.style.display = 'none';
loginInfo.innerText = 'Please enter the verification code';
}));
}
function addConfirm(resolve) {
document.getElementById('confirm').onclick = () => secondAuth().then(res => resolve(res));
}
<!-- HTML -->
<div id="loginDiv">
<div id="signInDiv" style="display: block;">
<div class="title">Sign in</div>
<input id="username" placeholder="Username">
<input id="password" placeholder="Password" type="password">
<button class="singin" onclick="singIn()">
Sign in
</button>
</div>
<div id="mfaDiv" style="display: none;">
<div class="title">MFA</div>
<input id="verificationCode" placeholder="Verification Code">
<button id="confirm" class="singin">
Confirm
</button>
</div>
<div id="loginInfo">Please login before browsing</div>
</div>
/* CSS */
#loginDiv {
overflow: hidden;
color: #96B97D;
border-radius: 8px;
width: 688px;
height: 288px;
box-shadow: 0px 0px 6px black;
}
.title {
position: absolute;
left: 200px;
top: 20px;
font-size: 26px;
font-weight: 700;
}
#username {
position: absolute;
left: 200px;
top: 70px;
width: 300px;
height: 38px;
padding-left: 10px;
padding-right: 10px;
border-radius: 4px;
border:1px solid #bbb;
font-size: 14px;
}
#password {
position: absolute;
left: 200px;
top: 120px;
width: 300px;
height: 38px;
padding-left: 10px;
padding-right: 10px;
border-radius: 4px;
border: 1px solid #BBB;
font-size: 14px;
}
#verificationCode {
position: absolute;
left: 200px;
top: 98px;
width: 300px;
height: 38px;
padding-left: 10px;
padding-right: 10px;
border-radius: 4px;
border: 1px solid #BBB;
font-size: 14px;
}
.singin {
position: absolute;
left: 200px;
top: 170px;
width: 300px;
height: 38px;
border: none;
background-color: #96B97D;
color: white;
border-radius: 4px;
font-size: 16px;
font-weight: 700;
cursor: pointer;
}
#loginInfo {
position: relative;
top: 230px;
width: 100%
height: 35px;
text-align: center;
color: #96B97D;
font-size: 16px;
font-weight: 700;
}