Để đăng nhập người dùng, hãy truy xuất thông tin xác thực từ trình quản lý mật khẩu của trình duyệt và sử dụng thông tin đó để tự động đăng nhập người dùng. Đối với người dùng có nhiều tài khoản, hãy cho phép họ chọn tài khoản chỉ bằng một lần nhấn bằng trình chọn tài khoản.
Tự động đăng nhập
Tính năng tự động đăng nhập có thể xảy ra ở bất kỳ đâu trên trang web của bạn; không chỉ trang cấp cao nhất mà còn cả các trang chi tiết khác. Điều này hữu ích khi người dùng truy cập vào nhiều trang trong trang web của bạn thông qua một công cụ tìm kiếm.
Cách bật tính năng tự động đăng nhập:
- Lấy thông tin xác thực.
- Xác thực người dùng.
- Cập nhật giao diện người dùng hoặc chuyển đến trang được cá nhân hoá.
Lấy thông tin xác thực
Để lấy thông tin xác thực, hãy gọi navigator.credentials.get()
.
Chỉ định loại thông tin xác thực cần yêu cầu bằng cách cung cấp password
hoặc federated
.
Luôn sử dụng mediation: 'silent'
để tự động đăng nhập,
vì vậy, bạn có thể dễ dàng đóng quy trình này nếu người dùng:
- Không có thông tin xác thực nào được lưu trữ.
- Đã lưu trữ nhiều thông tin xác thực.
- Đã đăng xuất.
Trước khi lấy thông tin xác thực, đừng quên kiểm tra xem người dùng đã đăng nhập hay chưa:
if (window.PasswordCredential || window.FederatedCredential) {
if (!user.isSignedIn()) {
navigator.credentials.get({
password: true,
federated: {
providers: ['https://accounts.google.com'],
},
mediation: 'silent',
});
// ...
}
}
Lời hứa do navigator.credentials.get()
trả về sẽ phân giải bằng một đối tượng thông tin xác thực hoặc null
.
Để xác định đó là PasswordCredential
hay FederatedCredential
, bạn chỉ cần xem thuộc tính .type
của đối tượng. Thuộc tính này sẽ là password
hoặc federated
.
Nếu .type
là federated
, thì thuộc tính .provider
là một chuỗi đại diện cho nhà cung cấp danh tính.
Xác thực người dùng
Sau khi bạn có thông tin xác thực, hãy chạy quy trình xác thực tuỳ thuộc vào loại thông tin xác thực, password
hoặc federated
:
}).then(c => {
if (c) {
switch (c.type) {
case 'password':
return sendRequest(c);
break;
case 'federated':
return gSignIn(c);
break;
}
} else {
return Promise.resolve();
}
Khi lời hứa được thực hiện, hãy kiểm tra xem bạn đã nhận được đối tượng thông tin xác thực hay chưa. Nếu không, tức là tính năng tự động đăng nhập không thể thực hiện được. Ẩn quá trình tự động đăng nhập.
Cập nhật giao diện người dùng
Nếu xác thực thành công, hãy cập nhật giao diện người dùng hoặc chuyển tiếp người dùng đến trang được cá nhân hoá:
}).then(profile => {
if (profile) {
updateUI(profile);
}
Đừng quên hiển thị thông báo lỗi xác thực
Để tránh gây nhầm lẫn cho người dùng, người dùng sẽ thấy một thông báo ngắn màu xanh dương có nội dung "Đang đăng nhập" tại thời điểm nhận đối tượng thông tin xác thực:
Một mẹo quan trọng: nếu bạn thành công trong việc lấy đối tượng thông tin xác thực nhưng không xác thực được người dùng, bạn nên hiển thị thông báo lỗi:
}).catch(error => {
showError('Sign-in Failed');
});
}
}
Ví dụ đầy đủ về mã
if (window.PasswordCredential || window.FederatedCredential) {
if (!user.isSignedIn()) {
navigator.credentials
.get({
password: true,
federated: {
providers: ['https://accounts.google.com'],
},
mediation: 'silent',
})
.then((c) => {
if (c) {
switch (c.type) {
case 'password':
return sendRequest(c);
break;
case 'federated':
return gSignIn(c);
break;
}
} else {
return Promise.resolve();
}
})
.then((profile) => {
if (profile) {
updateUI(profile);
}
})
.catch((error) => {
showError('Sign-in Failed');
});
}
}
Đăng nhập thông qua bộ chọn tài khoản
Nếu người dùng yêu cầu dàn xếp hoặc có nhiều tài khoản, hãy sử dụng bộ chọn tài khoản để cho phép người dùng đăng nhập, bỏ qua biểu mẫu đăng nhập thông thường, ví dụ:
Các bước đăng nhập thông qua trình chọn tài khoản giống như trong tính năng tự động đăng nhập, với một lệnh gọi bổ sung để hiển thị trình chọn tài khoản trong quá trình lấy thông tin xác thực:
- Lấy thông tin xác thực và hiển thị bộ chọn tài khoản.
- Xác thực người dùng.
- Cập nhật giao diện người dùng hoặc chuyển đến trang được cá nhân hoá.
Nhận thông tin xác thực và hiển thị bộ chọn tài khoản
Hiển thị bộ chọn tài khoản để phản hồi một hành động đã xác định của người dùng, chẳng hạn như khi người dùng nhấn vào nút "Đăng nhập". Gọi navigator.credentials.get()
và thêm mediation: 'optional'
hoặc mediation: 'required'
để hiển thị bộ chọn tài khoản.
Khi mediation
là required
, người dùng luôn thấy một bộ chọn tài khoản để đăng nhập.
Lựa chọn này cho phép người dùng có nhiều tài khoản dễ dàng chuyển đổi giữa các tài khoản đó.
Khi mediation
là optional
, người dùng sẽ thấy rõ một bộ chọn tài khoản để đăng nhập sau lệnh gọi navigator.credentials.preventSilentAccess()
.
Điều này thường là để đảm bảo tính năng tự động đăng nhập không xảy ra sau khi người dùng chọn đăng xuất hoặc huỷ đăng ký.
Ví dụ minh hoạ mediation: 'optional'
:
var signin = document.querySelector('#signin');
signin.addEventListener('click', e => {
if (window.PasswordCredential || window.FederatedCredential) {
navigator.credentials.get({
password: true,
federated: {
providers: [
'https://accounts.google.com'
]
},
mediation: 'optional'
}).then(c => {
Sau khi người dùng chọn một tài khoản, lời hứa sẽ được phân giải bằng thông tin xác thực.
Nếu người dùng huỷ trình chọn tài khoản hoặc không có thông tin xác thực nào được lưu trữ, thì lời hứa sẽ được phân giải bằng null
.
Trong trường hợp đó, hãy quay lại trải nghiệm đăng nhập bằng biểu mẫu.
Đừng quên quay lại biểu mẫu đăng nhập
Bạn nên quay lại sử dụng biểu mẫu đăng nhập vì những lý do sau:
- Không có thông tin xác thực nào được lưu trữ.
- Người dùng đóng trình chọn tài khoản mà không chọn tài khoản nào.
- API không hoạt động.
}).then(profile => {
if (profile) {
updateUI(profile);
} else {
location.href = '/signin';
}
}).catch(error => {
location.href = '/signin';
});
Ví dụ đầy đủ về mã
var signin = document.querySelector('#signin');
signin.addEventListener('click', (e) => {
if (window.PasswordCredential || window.FederatedCredential) {
navigator.credentials
.get({
password: true,
federated: {
providers: ['https://accounts.google.com'],
},
mediation: 'optional',
})
.then((c) => {
if (c) {
switch (c.type) {
case 'password':
return sendRequest(c);
break;
case 'federated':
return gSignIn(c);
break;
}
} else {
return Promise.resolve();
}
})
.then((profile) => {
if (profile) {
updateUI(profile);
} else {
location.href = '/signin';
}
})
.catch((error) => {
location.href = '/signin';
});
}
});
Đăng nhập liên kết
Tính năng đăng nhập liên kết cho phép người dùng đăng nhập bằng một lần nhấn mà không cần phải nhớ thêm thông tin đăng nhập cho trang web của bạn.
Cách triển khai tính năng đăng nhập liên kết:
- Xác thực người dùng bằng danh tính của bên thứ ba.
- Lưu trữ thông tin nhận dạng.
- Cập nhật giao diện người dùng hoặc chuyển đến trang được cá nhân hoá (tương tự như trong tính năng tự động đăng nhập).
Xác thực người dùng bằng danh tính bên thứ ba
Khi người dùng nhấn vào nút đăng nhập liên kết, hãy chạy quy trình xác thực nhà cung cấp danh tính cụ thể bằng FederatedCredential
.
Ví dụ: nếu nhà cung cấp là Google, hãy sử dụng thư viện JavaScript Đăng nhập bằng Google:
navigator.credentials
.get({
password: true,
mediation: 'optional',
federated: {
providers: ['https://account.google.com'],
},
})
.then(function (cred) {
if (cred) {
// Instantiate an auth object
var auth2 = gapi.auth2.getAuthInstance();
// Is this user already signed in?
if (auth2.isSignedIn.get()) {
var googleUser = auth2.currentUser.get();
// Same user as in the credential object?
if (googleUser.getBasicProfile().getEmail() === cred.id) {
// Continue with the signed-in user.
return Promise.resolve(googleUser);
}
}
// Otherwise, run a new authentication flow.
return auth2.signIn({
login_hint: id || '',
});
}
});
Tính năng Đăng nhập bằng Google sẽ tạo một mã thông báo nhận dạng làm bằng chứng xác thực.
Nhìn chung, tính năng đăng nhập liên kết được xây dựng dựa trên các giao thức chuẩn như OpenID Connect hoặc OAuth. Để tìm hiểu cách xác thực bằng tài khoản liên kết, hãy tham khảo tài liệu của nhà cung cấp danh tính liên kết tương ứng. Sau đây là một số ví dụ phổ biến:
Lưu trữ thông tin nhận dạng
Sau khi xác thực, bạn có thể lưu trữ thông tin nhận dạng.
Thông tin bạn sẽ lưu trữ tại đây là id
từ nhà cung cấp danh tính và một chuỗi nhà cung cấp đại diện cho nhà cung cấp danh tính (name
và iconURL
là không bắt buộc).
Tìm hiểu thêm về thông tin này trong Quy cách quản lý thông tin xác thực.
Để lưu trữ thông tin tài khoản liên kết, hãy tạo bản sao của đối tượng FederatedCredential
mới bằng giá trị nhận dạng của người dùng và giá trị nhận dạng của nhà cung cấp.
Sau đó, hãy gọi navigator.credentials.store()
để lưu trữ thông tin nhận dạng.
Sau khi liên kết thành công, hãy tạo bản sao FederatedCredential
một cách đồng bộ hoặc không đồng bộ:
Ví dụ về phương pháp đồng bộ:
// Create credential object synchronously.
var cred = new FederatedCredential({
id: id, // id in IdP
provider: 'https://account.google.com', // A string representing IdP
name: name, // name in IdP
iconURL: iconUrl, // Profile image url
});
Ví dụ về phương pháp không đồng bộ:
// Create credential object asynchronously.
var cred = await navigator.credentials.create({
federated: {
id: id,
provider: 'https://accounts.google.com',
name: name,
iconURL: iconUrl,
},
});
Sau đó, hãy lưu trữ đối tượng thông tin xác thực:
// Store it
navigator.credentials.store(cred).then(function () {
// continuation
});
Đăng xuất
Đăng xuất người dùng khi họ nhấn vào nút đăng xuất. Trước tiên, hãy chấm dứt phiên, sau đó tắt tính năng tự động đăng nhập cho các lượt truy cập sau này. (Cách bạn chấm dứt phiên hoàn toàn tuỳ thuộc vào bạn.)
Tắt tính năng tự động đăng nhập cho các lần truy cập sau này
Gọi navigator.credentials.preventSilentAccess()
:
signoutUser();
if (navigator.credentials && navigator.credentials.preventSilentAccess) {
navigator.credentials.preventSilentAccess();
}
Điều này sẽ đảm bảo tính năng tự động đăng nhập sẽ không xảy ra cho đến lần tiếp theo người dùng bật tính năng tự động đăng nhập. Để tiếp tục tính năng tự động đăng nhập, người dùng có thể chọn đăng nhập theo cách có chủ ý bằng cách chọn tài khoản mà họ muốn đăng nhập trong trình chọn tài khoản. Sau đó, người dùng luôn được đăng nhập lại cho đến khi họ đăng xuất một cách rõ ràng.