文档开发者中心
我的
|

App开发

DevEco Studio

软件开发

移动开发

用户注册与登录功能实现——玩具店购物应用开发实战(二)

用户注册与登录功能实现——玩具店购物应用开发实战(二)

在上一篇文章中,我们完成了玩具店购物应用的项目规划与环境搭建。本篇文章将详细介绍用户注册和登录功能的实现,包括用户输入验证、密码加密、登录状态管理等。

一、功能概述

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);
  }
}

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);
  }
}

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: '登录成功' });
      resultSet.close();
​
      // 保存登录状态
      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中设置断点,逐步检查代码执行流程。

  • 查看数据库:在开发过程中,可以使用数据库浏览工具查看数据库内容,验证数据是否正确写入。

目前我们实现了玩具店购物应用的用户注册和登录功能。通过对用户输入的验证、密码的加密存储以及登录状态的管理,确保了用户数据的安全性和应用的易用性。在下一篇文章中,我们将实现商品列表和商品详情展示,包括从数据库或网络加载商品数据、商品的搜索和筛选等功能。

点赞
1
收藏
2
回复
分享
举报
浏览353 发布于2024-11-06 02:40上海
全部评论
最多点赞
最新发布
最早发布
暂无评论
暂无评论
写回答
新增插入模板功能
一键使用模板,快速填写内容,轻松发帖~
知道了
  • 为了保障您的信息安全,请勿上传您的敏感个人信息(如您的密码等信息)和您的敏感资产信息(如关键源代码、签名私钥、调试安装包、业务日志等信息),且您需自行承担由此产生的信息泄露等安全风险。
  • 如您发布的内容为转载内容,请注明内容来源。

我要发帖子

目录 收起
用户注册与登录功能实现——玩具店购物应用开发实战(二)
一、功能概述
1. 功能需求
2. 技术难点
二、数据库设计与实现
1. 数据库初始化
2. 密码加密存储
三、用户注册功能实现
1. 注册页面布局
2. 输入验证
3. 解释
四、用户登录功能实现
1. 登录页面布局
2. 登录逻辑实现
3. 解释
五、登录状态管理
1. 自动登录实现
2. 用户注销功能
六、完善用户体验
1. 异常处理
2. 输入提示
3. 界面优化
七、测试与调试
1. 测试用例
2. 调试方法
了解社区公约,与您携手共创和谐专业的开发者社区。