HarmonyOS 鸿蒙Next 用户注册与登录功能实现——玩具店购物应用开发实战(二)
HarmonyOS 鸿蒙Next 用户注册与登录功能实现——玩具店购物应用开发实战(二)
用户注册与登录功能实现——玩具店购物应用开发实战(二)
在上一篇文章中,我们完成了玩具店购物应用的项目规划与环境搭建。本篇文章将详细介绍用户注册和登录功能的实现,包括用户输入验证、密码加密、登录状态管理等。
一、功能概述
1. 功能需求
-
用户注册:
- 用户可以通过邮箱和密码注册新账号。
- 注册时需要对输入的信息进行验证,如邮箱格式、密码强度等。
- 注册成功后,自动登录并跳转到商品列表页。
-
用户登录:
- 已注册用户可以通过邮箱和密码登录。
- 登录时需要验证用户输入的邮箱和密码是否正确。
- 登录成功后,保存登录状态,方便下次自动登录。
-
用户注销:
- 用户可以退出登录状态,清除本地的登录信息。
2. 技术难点
- 输入验证:如何有效地验证用户输入的信息,确保数据的有效性和安全性。
- 密码加密:如何对用户的密码进行加密存储,防止明文存储导致的安全问题。
- 登录状态管理:如何在应用中保存和管理用户的登录状态,实现自动登录。
二、数据库设计与实现
在第一篇文章中,我们已经设计了users
表,用于存储用户信息。现在,我们需要完善数据库的初始化和连接。
1. 数据库初始化
在common/utils/DatabaseHelper.ets
中,已经创建了DatabaseHelper
类,用于数据库的初始化。现在,我们需要完善用户表的创建和密码加密。
// common/utils/DatabaseHelper.ets
import rdb from '@ohos.data.rdb';
export class DatabaseHelper {
private static instance: rdb.RdbStore;
static async getRdbStore(): Promise<rdb.RdbStore> {
if (!this.instance) {
const config = {
name: 'ToyStore.db',
version: 1,
onCreate: (db: rdb.RdbStore) => {
// 创建用户表
db.executeSql(`
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
email TEXT UNIQUE,
password TEXT
)
`);
// 其他表的创建...
},
};
this.instance = await rdb.getRdbStore(config);
}
return this.instance;
}
}
2. 密码加密存储
为了保证用户密码的安全性,我们需要对密码进行加密存储。这里我们使用SHA-256
算法进行哈希处理。
创建加密工具类
在common/utils
目录下,创建CryptoHelper.ets
,用于密码的加密。
// common/utils/CryptoHelper.ets
import crypto from '@ohos.cryptographic';
export class CryptoHelper {
static hashPassword(password: string): string {
const messageDigest = crypto.createMessageDigest('SHA-256');
messageDigest.update(new Uint8Array(crypto.stringToUint8Array(password)));
const hash = messageDigest.digest();
return crypto.uint8ArrayToHex(hash);
}
}
三、用户注册功能实现
1. 注册页面布局
在pages/RegisterPage.ets
中,创建注册页面的UI布局。
// pages/RegisterPage.ets
@Entry
@Component
struct RegisterPage {
@State email: string = '';
@State password: string = '';
@State confirmPassword: string = '';
build() {
Column({ space: 16 }) {
Text('用户注册').fontSize(24).margin({ top: 32 });
TextField({ placeholder: '邮箱', text: this.email })
.onChange(value => this.email = value)
.type(TextInputType.EmailAddress);
TextField({ placeholder: '密码', text: this.password })
.onChange(value => this.password = value)
.type(TextInputType.Password);
TextField({ placeholder: '确认密码', text: this.confirmPassword })
.onChange(value => this.confirmPassword = value)
.type(TextInputType.Password);
Button('注册')
.onClick(() => this.register())
.margin({ top: 16 });
Button('已有账号?登录')
.onClick(() => Router.replace({ uri: 'LoginPage' }))
.type(ButtonType.Normal);
}.padding(16);
}
async register() {
// 输入验证
if (!this.email || !this.password || !this.confirmPassword) {
prompt.showToast({ message: '请填写完整信息' });
return;
}
if (!this.validateEmail(this.email)) {
prompt.showToast({ message: '邮箱格式不正确' });
return;
}
if (this.password !== this.confirmPassword) {
prompt.showToast({ message: '两次密码输入不一致' });
return;
}
if (this.password.length < 6) {
prompt.showToast({ message: '密码长度至少为6位' });
return;
}
// 检查邮箱是否已注册
const query = 'SELECT * FROM users WHERE email = ?';
const resultSet = await this.store.query(query, [this.email]);
if (resultSet.goToFirstRow()) {
prompt.showToast({ message: '邮箱已注册' });
resultSet.close();
return;
}
resultSet.close();
// 密码加密
const hashedPassword = CryptoHelper.hashPassword(this.password);
// 插入新用户
const values = {
'email': this.email,
'password': hashedPassword,
};
await this.store.insert('users', values);
prompt.showToast({ message: '注册成功' });
// 自动登录,保存登录状态
AppStorage.SetOrCreate('isLoggedIn', true);
AppStorage.SetOrCreate('userEmail', this.email);
// 跳转到商品列表页
Router.replace({ uri: 'ProductListPage' });
}
validateEmail(email: string): boolean {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
}
}
2. 输入验证
在register()
方法中,添加对用户输入的验证。
import prompt from '@ohos.prompt';
import { DatabaseHelper } from '../common/utils/DatabaseHelper';
import { CryptoHelper } from '../common/utils/CryptoHelper';
@Component
struct RegisterPage {
// 前面的代码
private store: rdb.RdbStore;
aboutToAppear() {
this.initDatabase();
}
async initDatabase() {
this.store = await DatabaseHelper.getRdbStore();
}
async register() {
// 输入验证
if (!this.email || !this.password || !this.confirmPassword) {
prompt.showToast({ message: '请填写完整信息' });
return;
}
if (!this.validateEmail(this.email)) {
prompt.showToast({ message: '邮箱格式不正确' });
return;
}
if (this.password !== this.confirmPassword) {
prompt.showToast({ message: '两次密码输入不一致' });
return;
}
if (this.password.length < 6) {
prompt.showToast({ message: '密码长度至少为6位' });
return;
}
// 检查邮箱是否已注册
const query = 'SELECT * FROM users WHERE email = ?';
const resultSet = await this.store.query(query, [this.email]);
if (resultSet.goToFirstRow()) {
prompt.showToast({ message: '邮箱已注册' });
resultSet.close();
return;
}
resultSet.close();
// 密码加密
const hashedPassword = CryptoHelper.hashPassword(this.password);
// 插入新用户
const values = {
'email': this.email,
'password': hashedPassword,
};
await this.store.insert('users', values);
prompt.showToast({ message: '注册成功' });
// 自动登录,保存登录状态
AppStorage.SetOrCreate('isLoggedIn', true);
AppStorage.SetOrCreate('userEmail', this.email);
// 跳转到商品列表页
Router.replace({ uri: 'ProductListPage' });
}
validateEmail(email: string): boolean {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
}
}
3. 解释
- 输入验证:检查邮箱格式、密码长度、两次密码是否一致等。
- 邮箱唯一性:在数据库中查询是否已有相同的邮箱注册。
- 密码加密:使用
CryptoHelper.hashPassword()
对密码进行哈希处理。 - 保存登录状态:使用
AppStorage
保存登录状态和用户邮箱。 - 页面跳转:注册成功后,跳转到商品列表页。
四、用户登录功能实现
1. 登录页面布局
在pages/LoginPage.ets
中,创建登录页面的UI布局。
// pages/LoginPage.ets
@Entry
@Component
struct LoginPage {
@State email: string = '';
@State password: string = '';
build() {
Column({ space: 16 }) {
Text('用户登录').fontSize(24).margin({ top: 32 });
TextField({ placeholder: '邮箱', text: this.email })
.onChange(value => this.email = value)
.type(TextInputType.EmailAddress);
TextField({ placeholder: '密码', text: this.password })
.onChange(value => this.password = value)
.type(TextInputType.Password);
Button('登录')
.onClick(() => this.login())
.margin({ top: 16 });
Button('没有账号?注册')
.onClick(() => Router.replace({ uri: 'RegisterPage' }))
.type(ButtonType.Normal);
}.padding(16);
}
async login() {
if (!this.email || !this.password) {
prompt.showToast({ message: '请输入邮箱和密码' });
return;
}
// 密码加密
const hashedPassword = CryptoHelper.hashPassword(this.password);
// 查询用户
const query = 'SELECT * FROM users WHERE email = ? AND password = ?';
const resultSet = await this.store.query(query, [this.email, hashedPassword]);
if (resultSet.goToFirstRow()) {
prompt.showToast({ message: '登录成功' });
// 保存登录状态
AppStorage.SetOrCreate('isLoggedIn', true);
AppStorage.SetOrCreate('userEmail', this.email);
// 跳转到商品列表页
Router.replace({ uri: 'ProductListPage' });
} else {
prompt.showToast({ message: '邮箱或密码错误' });
}
resultSet.close();
}
}
2. 登录逻辑实现
import prompt from '@ohos.prompt';
import { DatabaseHelper } from '../common/utils/DatabaseHelper';
import { CryptoHelper } from '../common/utils/CryptoHelper';
@Component
struct LoginPage {
// 前面的代码
private store: rdb.RdbStore;
aboutToAppear() {
this.initDatabase();
}
async initDatabase() {
this.store = await DatabaseHelper.getRdbStore();
}
async login() {
if (!this.email || !this.password) {
prompt.showToast({ message: '请输入邮箱和密码' });
return;
}
// 密码加密
const hashedPassword = CryptoHelper.hashPassword(this.password);
// 查询用户
const query = 'SELECT * FROM users WHERE email = ? AND password = ?';
const resultSet = await this.store.query(query, [this.email, hashedPassword]);
if (resultSet.goToFirstRow()) {
prompt.showToast({ message: '登录成功' });
// 保存登录状态
AppStorage.SetOrCreate('isLoggedIn', true);
AppStorage.SetOrCreate('userEmail', this.email);
// 跳转到商品列表页
Router.replace({ uri: 'ProductListPage' });
} else {
prompt.showToast({ message: '邮箱或密码错误' });
}
resultSet.close();
}
}
3. 解释
- 密码加密对比:将用户输入的密码进行哈希处理,与数据库中的加密密码进行比较。
- 保存登录状态:登录成功后,使用
AppStorage
保存登录状态。 - 错误提示:登录失败时,给出友好的提示信息。
五、登录状态管理
1. 自动登录实现
在app.ets
中,应用启动时检查登录状态,决定跳转的页面。
// app.ets
import router from '@ohos.router';
@Entry
@Component
struct App {
build() {
// 检查登录状态
if (AppStorage.Get('isLoggedIn')) {
router.replace({ uri: 'ProductListPage' });
} else {
router.replace({ uri: 'LoginPage' });
}
}
}
2. 用户注销功能
在商品列表页或个人中心页,添加“注销”按钮,用户可以退出登录。
// 在商品列表页或其他页面添加注销功能
Button('注销')
.onClick(() => this.logout())
.margin({ top: 16 });
logout() {
// 清除登录状态
AppStorage.Set('isLoggedIn', false);
AppStorage.Delete('userEmail');
prompt.showToast({ message: '已退出登录' });
Router.replace({ uri: 'LoginPage' });
}
六、完善用户体验
1. 异常处理
- 数据库异常:在数据库操作中,添加
try...catch
,捕获异常并提示用户。 - 网络异常:如果有网络请求,需处理网络不可用或超时的情况。
2. 输入提示
- 在用户输入不符合要求时,使用
prompt.showToast()
给出明确的提示信息,指导用户正确输入。
3. 界面优化
- 布局美化:使用合理的间距、字体大小和颜色,提升界面美观度。
- 按钮样式:自定义按钮的样式,使其更加符合应用的风格。
七、测试与调试
1. 测试用例
-
注册流程测试:
- 输入有效的邮箱和密码,注册成功。
- 输入已注册的邮箱,提示邮箱已注册。
- 输入不匹配的密码和确认密码,提示错误。
-
登录流程测试:
- 输入正确的邮箱和密码,登录成功。
- 输入错误的邮箱或密码,提示登录失败。
-
自动登录测试:
- 登录成功后,关闭应用再打开,自动跳转到商品列表页。
-
注销功能测试:
- 点击注销按钮,成功退出登录,回到登录页。
2. 调试方法
- 日志输出:使用
console.log()
或console.error()
输出调试信息。 - 断点调试:在DevEco Studio中设置断点,逐步检查代码执行流程。
- 查看数据库:在开发过程中,可以使用数据库浏览工具查看数据库内容,验证数据是否正确写入。
目前我们实现了玩具店购物应用的用户注册和登录功能。通过对用户输入的验证、密码的加密存储以及登录状态的管理,确保了用户数据的安全性和应用的易用性。在下一篇文章中,我们将实现商品列表和商品详情展示,包括从数据库或网络加载商品数据、商品的搜索和筛选等功能。
更多关于HarmonyOS 鸿蒙Next 用户注册与登录功能实现——玩具店购物应用开发实战(二)的实战教程也可以访问 https://www.itying.com/category-93-b0.html
更多关于HarmonyOS 鸿蒙Next 用户注册与登录功能实现——玩具店购物应用开发实战(二)的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
针对帖子标题“HarmonyOS 鸿蒙Next 用户注册与登录功能实现——玩具店购物应用开发实战(二)”的问题,以下是关于鸿蒙系统中实现用户注册与登录功能的专业回答:
在鸿蒙系统中实现用户注册与登录功能,通常涉及以下几个关键步骤:
-
界面设计:首先,需要在鸿蒙的ArkUI框架中设计用户注册与登录的界面。这包括输入框、按钮等UI组件,确保用户能够方便地输入账号、密码等信息。
-
数据存储:为了实现用户信息的持久化存储,可以使用鸿蒙提供的分布式数据管理功能,或者通过SQLite等数据库来存储用户数据。
-
网络请求:在用户点击注册或登录按钮时,应用需要向服务器发送请求。鸿蒙系统支持多种网络请求方式,如Fetch API等,可用于实现与后端的通信。
-
安全性考虑:在实现过程中,需要注意保护用户数据的安全性,如使用HTTPS协议进行通信,对密码进行加密处理等。
-
错误处理:对用户输入的错误、网络请求失败等情况进行妥善处理,提高应用的用户体验。
通过上述步骤,可以在鸿蒙系统中实现用户注册与登录的基本功能。如果在实现过程中遇到问题,可以参考鸿蒙系统的官方文档或开发者社区的资源。如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html。