当前位置:   article > 正文

HarmonyOS开发实战之认证服务 (auth in Serverless by ArkTS)_arkts 用户注册代码

arkts 用户注册代码

目录

一、了解ArkTS以及华为Serverless服务

二、功能介绍

三、功能实现


一、了解ArkTS以及华为Serverless服务

        ArkTS 是华为发布的最新的HarmonyOS 系统的主力开发语言(框架)。

它提供了声明式UI、状态管理等相应的能力,配合ArkUI组件库,你可以更简洁,高效的开发出

HarmonyOS APP。

        在语言上,TypeScript是JavaScript的超集,ArkTS则是TypeScript的超集,所以ArkTs也是

一种静态类型绑定语言,所有数据的类型都必须在编译时确定。如果你之前学过JavaScript或者

TypeScript,那么在语法上,你可以很容易的过度到ArkTS。[参考指南]

        

        Serverless 是华为推出的云开发服务,帮助开发者统一构建和管理后端服务与云资源。

Serverless提供的服务有云认证服务、云数据库、云存储等。

        较传统App开发,我们不再需要开发后端服务接口。例如认证服务,借助Serverless SDK,

我们只需要编写很少的代码就可以实现认证功能(注册,登陆,登出,注销),而不必关心Serverless背后是如何实现的。[参考指南]

        本系列带来了最新的ArkTS结合华为Serverless服务实现用户注册,登陆,登出功能。

二、功能介绍

1.Serverless配置

2.用户注册

        Serverless认证服务支持Email验证码(密码)注册登陆,手机号验证码(密码)注册登陆,匿名

登陆,第三方登陆(微信、QQ、微博等) ,自定义登陆等等。这里我们使用Email验证码(密码)来

实现注册功能。

        Email验证码发送功能,点击验证码发送按钮,会自动调用邮件服务器向填写的Email地址发

送一份注册认证邮件,其中包括6位验证码,通过此验证码可以完成注册功能。

        验证码发送按钮点击时的动画效果。

        用户注册功能。

3 用户登陆

        根据Email和注册时填写的密码登陆。

4 页面展示用户信息

        登陆后在页面显示用户UUID或者名字

5 用户登出

        清除认证信息并登出。

6 其他功能

        正则表达式验证Email格式以及密码长度。

        Email地址,用户密码,验证码输入错误时红色标注提醒,并禁用注册或登录按钮。

三、功能实现

        

1.开发之前的Serverless配置

        # 选择平台,选择 APP(HarmonyOS),是否元服务,选择是。

        # 注意创建应用时包名上架后无法更改,请确认与发布软件包的包名一致,可以是唯一域名

反转,比如cc.myspring2.serverless

        1)创建Serverless项目与应用。[参考指南]

        2)开通认证服务,这里只需要启用邮箱地址和匿名帐号。[参考指南]

        3)获取agconnect-services.json文件。[参考指南]

                Tip:agconnect-services.json文件用来标识开发者身份。

        # 使用DevEco-Studio创建项目时,Bundle name要与创建应用时包名一致。

        4)集成SDK。[参考指南]

                Tip:EntryAbility 用来管理UIAbility的生命周期,包括:创建时onCreate(),切换到前台触发onForeground(),切换到前台触发onBackground(),以及销毁onDestroy()。

2.用户注册

        1)用户注册页面

        

        UI组件布局

  1. build() {
  2. // 容器列,每列间隔10虚拟像素
  3. Column({space:10}) {
  4. // 插入一行
  5. Row(){
  6. Text("用户注册")
  7. .fontSize(28)
  8. }
  9. // 插入一行
  10. Row(){
  11. // Email输入框
  12. TextInput({placeholder:'请输入Email'})
  13. .type(InputType.Email)
  14. .width('60%')
  15. .borderRadius(0)
  16. .border({width:1,color:'#F5F5F5'})
  17. .backgroundColor('#FFFFFF')
  18. .maxLength(36)
  19. }
  20. // 插入一行 密码输入
  21. Row(){
  22. TextInput({placeholder:'密码不少于5位'})
  23. .type(InputType.Password)
  24. .width('60%')
  25. .borderRadius(0)
  26. .border({width:1,color:'#F5F5F5'})
  27. .backgroundColor('#FFFFFF')
  28. .maxLength(20)
  29. }
  30. // 插入一行 再次输入密码
  31. Row(){
  32. TextInput({placeholder:'请再次输入密码'})
  33. .type(InputType.Password)
  34. .width('60%')
  35. .borderRadius(0)
  36. .border({width:1,color:'#F5F5F5'})
  37. .backgroundColor('#FFFFFF')
  38. .maxLength(20)
  39. }
  40. // 插入一行
  41. Row(){
  42. // 行内插入一列,输入验证码
  43. Column(){
  44. TextInput({ placeholder: '验证码'})
  45. .type(InputType.Normal)
  46. .width('50%')
  47. .borderRadius(0)
  48. .border({width:1,color:'#F5F5F5'})
  49. .backgroundColor('#FFFFFF')
  50. .maxLength(6)
  51. }
  52. // 行内插入一列,点击发送验证码按钮
  53. Column(){
  54. // 正则表达式验证email合法性
  55. Button('发送验证码')
  56. .type(ButtonType.Normal)
  57. .width('50%')
  58. .fontColor('#FF7F00')
  59. .backgroundColor('#FFFFFF')
  60. .border({width:1,color:'#FF7F00'})
  61. }
  62. }.width('60%')
  63. // 插入一行,注册按钮
  64. Row({space:10}){
  65. Button("注册")
  66. .type(ButtonType.Normal)
  67. .backgroundColor('#FF7F00')
  68. }
  69. }
  70. .height('100%')
  71. .width('100%')
  72. // 对齐方式
  73. .justifyContent(FlexAlign.Center)
  74. }

        2)Email验证码发送功能

a)增加@State状态来保存验证码功能相关状态。

  1. // 定时器
  2. @State intervalId: number = -123456;
  3. // 定时倒计时
  4. @State timer: number = 60;
  5. // 验证码
  6. @State verificationCode: string = ''
  7. // email
  8. @State email: string = ''

b)修改验证码输入框UI组件代码,绑定状态变量,并增加onChange监听。

  1. // 行内插入一列,输入验证码
  2. Column(){
  3. TextInput({ placeholder: '验证码', text: this.verificationCode })
  4. .type(InputType.Normal)
  5. .width('50%')
  6. .borderRadius(0)
  7. .border({width:1,color:'#F5F5F5'})
  8. .backgroundColor('#FFFFFF')
  9. .maxLength(6)
  10. .onChange(value=>{
  11. this.verificationCode = value
  12. })
  13. }

 c)修改验证码发送按钮UI组件代码,绑定状态变量,并增加onClick监听。

  1. // 行内插入一列,点击发送验证码按钮
  2. Column(){
  3. // 如果timer倒计时结束,显示'发送验证码',否则显示倒计时
  4. Button(this.timer === 60 ? '发送验证码' : this.timer.toString())
  5. .type(ButtonType.Normal)
  6. .width('50%')
  7. .fontColor('#FF7F00')
  8. .backgroundColor('#FFFFFF')
  9. .border({width:1,color:'#FF7F00'})
  10. // 可以封装成方法调用
  11. // 发送验证码
  12. .onClick(()=>{
  13. // 这里怎么触发email框提示?
  14. this.onGetCodeButtonClicked()
  15. })
  16. }

d)处理逻辑代码。

  1. /**
  2. * 发送验证码按钮点击事件
  3. */
  4. async onGetCodeButtonClicked() {
  5. // timer === 60 表示上一次发送验证码倒计时结束
  6. if (this.timer === 60) {
  7. // 倒计时动画
  8. this.startTimer();
  9. // 调用ServerSDK发送验证码
  10. cloud.auth().requestVerifyCode({
  11. // 动作类型
  12. action: VerifyCodeAction.REGISTER_LOGIN,
  13. // 语言
  14. lang: 'zh_CN',
  15. // 发送间隔
  16. sendInterval: 60,
  17. // email发送目标地址以及类型为email验证
  18. verifyCodeType: {
  19. email: this.email,
  20. kind: "email",
  21. }
  22. }).then(verifyCodeResult => {
  23. //验证码申请成功
  24. console.log( '-----发送验证码成功!-----');
  25. }).catch(error => {
  26. //验证码申请失败
  27. console.log( '-----发送验证码失败!-----');
  28. AlertDialog.show({
  29. title: '异常',
  30. message: '发送验证码失败!',
  31. autoCancel: true
  32. })
  33. });
  34. }else{
  35. // 调用弹出框组件
  36. AlertDialog.show({
  37. title: '异常',
  38. message: '请输入正确的email',
  39. autoCancel: true
  40. })
  41. }
  42. }
  1. // 定义定时间隔触发器
  2. startTimer(): void {
  3. this.timer = 60;
  4. this.intervalId = setInterval(() => {
  5. console.log(this.timer.toString())
  6. this.timer--;
  7. if (this.timer === 0) {
  8. clearInterval(this.intervalId);
  9. this.timer = 60;
  10. }
  11. }, 1000);
  12. }

 点击发送验证码按钮后,邮件服务器会发送一封验证邮件到指定邮件地址,包括6位验证码。

        3)用户注册功能

a)增加@State状态来保存密码功能相关状态。

  1. // 密码输入
  2. @State password: string = ''
  3. // 再次输入密码
  4. @State rePassword: string = ''

 b)修改密码输入UI组件代码,绑定状态变量,并增加注册按钮onClick监听。

  1. // 插入一行 密码输入
  2. Row(){
  3. TextInput({placeholder:'密码不少于5位'})
  4. .type(InputType.Password)
  5. .width('60%')
  6. .borderRadius(0)
  7. .border({width:1,color:'#F5F5F5'})
  8. .backgroundColor('#FFFFFF')
  9. .maxLength(20)
  10. .onChange((value)=>{
  11. this.password = value;
  12. })
  13. }
  14. // 插入一行 再次输入密码
  15. Row(){
  16. TextInput({placeholder:'请再次输入密码'})
  17. .type(InputType.Password)
  18. .width('60%')
  19. .borderRadius(0)
  20. .border({width:1,color:'#F5F5F5'})
  21. .backgroundColor('#FFFFFF')
  22. .maxLength(20)
  23. .onChange((value)=>{
  24. this.rePassword = value;
  25. })
  26. }
  1. // 插入一行,注册按钮
  2. Row({space:10}){
  3. Button("注册")
  4. .type(ButtonType.Normal)
  5. .backgroundColor('#FF7F00')
  6. .onClick(()=>{
  7. this.onAuthButtonClicked()
  8. })
  9. }

 c)处理逻辑代码。

  1. /**
  2. * 点击注册
  3. */
  4. onAuthButtonClicked() {
  5. // 调用自定义emailRegister函数
  6. this.emailRegister(this.email, this.rePassword, this.verificationCode).then(user => {
  7. // 使用AppStorage存储用户认证数据以便后续使用(应用级状态共享)
  8. AppStorage.Set<AgUser>('user', user);
  9. console.log( "Logged in succesfully.");
  10. // 注册成功后跳转至主页
  11. router.pushUrl({
  12. url:"pages/Index"
  13. })
  14. }).catch((err) => {
  15. console.log("Logged in failed " + JSON.stringify(err));
  16. AlertDialog.show({
  17. title: '异常',
  18. message: '注册错误!',
  19. });
  20. });
  21. }
  1. /**
  2. * email用户注册
  3. * @param email
  4. * @param password
  5. * @param verifyCode
  6. * @returns
  7. */
  8. public async emailRegister(email: string, password: string, verifyCode: string): Promise<AgUser> {
  9. return new Promise((resolve, reject) => {
  10. // 创建email用户
  11. cloud.auth().createUser({
  12. kind: 'email',
  13. email: email,
  14. password: password,//可以给用户设置初始密码。后续可以用密码来登录
  15. verifyCode: verifyCode
  16. }).then(async (ret) => {
  17. //创建帐号成功后,默认已登录
  18. console.log("用户创建完毕并登陆..");
  19. // @ts-ignore
  20. let user = ret.getUser();
  21. // 用户认证扩展信息
  22. let userExtra = await ret.getUser().getUserExtra();
  23. // 创建认证用户实体
  24. let loginRes = new AgUser(
  25. // uuid
  26. user.getUid(),
  27. user.getPhotoUrl(),
  28. user.getPhone(),
  29. user.getEmail(),
  30. // 用户名称
  31. user.getDisplayName(),
  32. userExtra.getCreateTime(),
  33. userExtra.getLastSignInTime())
  34. console.log( '---'+user.getUid()+'---@');
  35. // 返回认证用户
  36. resolve(loginRes);
  37. }).catch(error => {
  38. //创建用户失败
  39. console.log( "Error: ", error);
  40. reject(error);
  41. })
  42. })
  43. }

 d)AgUser认证实体类定义

  1. export class AgUser {
  2. uid: String;
  3. photoUrl: String;
  4. phone: String;
  5. email: String;
  6. displayName: String;
  7. registerDate: String;
  8. lastLogin: String;
  9. constructor(uid: String ="", photoUrl: String = "", phone: String= "", email: String= "", displayName: String="", registerDate: String="", lastLogin: String="") {
  10. this.uid = uid;
  11. this.photoUrl = photoUrl;
  12. this.phone = phone;
  13. this.email = email;
  14. this.displayName = displayName;
  15. this.registerDate = registerDate;
  16. this.lastLogin = lastLogin;
  17. }
  18. getUid(): String {
  19. return this.uid;
  20. }
  21. getPhone(): String {
  22. return this.phone;
  23. }
  24. getEmail(): String {
  25. return this.email;
  26. }
  27. getDisplayName(): String {
  28. return this.displayName;
  29. }
  30. getPhotoUrl(): String {
  31. return this.photoUrl;
  32. }
  33. getRegisterDate(): String {
  34. return this.registerDate;
  35. }
  36. getLastLogin(): String {
  37. return this.lastLogin;
  38. }
  39. }

 用户注册页面完整代码

  1. /**
  2. * 邮箱注册 Serverless 认证功能
  3. */
  4. // 导入路由器组件
  5. import router from '@ohos.router'
  6. // 导入serverless认证组件
  7. import cloud, { VerifyCodeAction } from '@hw-agconnect/cloud';
  8. // email正则验证以及密码验证
  9. import { isEmail,isRightPassword} from '../../common/auth/EmailReg'
  10. // 导入用户认证信息类
  11. import { AgUser } from '../../services/Auth';
  12. // 导入日志组件
  13. import { Log } from '../../common/Log';
  14. const TAG = "[AGCAuth]";
  15. @Entry
  16. @Component
  17. struct RegisterByEmail {
  18. // 定时器
  19. @State intervalId: number = -123456;
  20. // email输入
  21. @State email: string = ''
  22. // 密码输入
  23. @State password: string = ''
  24. // 再次输入密码
  25. @State rePassword: string = ''
  26. // 验证码
  27. @State verificationCode: string = ''
  28. // 定时倒计时
  29. @State timer: number = 60;
  30. // 是否可以登陆
  31. @State canLogin: boolean = true;
  32. // email校验
  33. @State emailTipColor: string = '#F5F5F5'
  34. @State emailRightColor: string = '#F5F5F5'
  35. @State emailWrongColor: string = '#FF7F00'
  36. // 输入密码校验
  37. @State passwordTipColor: string = '#F5F5F5'
  38. @State passwordRightColor: string = '#F5F5F5'
  39. @State passwordWrongColor: string = '#FF7F00'
  40. // 再次输入密码校验
  41. @State rPasswordTipColor: string = '#F5F5F5'
  42. @State rPasswordRightColor: string = '#F5F5F5'
  43. @State rPasswordWrongColor: string = '#FF7F00'
  44. // 定时间隔
  45. startTimer(): void {
  46. this.timer = 60;
  47. this.intervalId = setInterval(() => {
  48. console.log(this.timer.toString())
  49. this.timer--;
  50. if (this.timer === 0) {
  51. clearInterval(this.intervalId);
  52. this.timer = 60;
  53. }
  54. }, 1000);
  55. }
  56. /**
  57. * 发送验证码
  58. */
  59. async onGetCodeButtonClicked() {
  60. if (isEmail(this.email) && this.timer === 60) {
  61. this.startTimer();
  62. // 调用ServerSDK发送验证码
  63. cloud.auth().requestVerifyCode({
  64. // 动作类型
  65. action: VerifyCodeAction.REGISTER_LOGIN,
  66. // 语言
  67. lang: 'zh_CN',
  68. // 发送间隔
  69. sendInterval: 60,
  70. // email发送目标地址以及类型为email验证
  71. verifyCodeType: {
  72. email: this.email,
  73. kind: "email",
  74. }
  75. }).then(verifyCodeResult => {
  76. //验证码申请成功
  77. Log.info(TAG, '-----发送验证码成功!-----');
  78. }).catch(error => {
  79. //验证码申请失败
  80. Log.info(TAG, '-----发送验证码失败!-----');
  81. AlertDialog.show({
  82. title: '异常',
  83. message: '发送验证码失败!',
  84. autoCancel: true
  85. })
  86. });
  87. }else{
  88. // 调用弹出框组件
  89. AlertDialog.show({
  90. title: '异常',
  91. message: '请输入正确的email',
  92. autoCancel: true
  93. })
  94. }
  95. }
  96. /**
  97. * 是否可以点击注册
  98. * @returns
  99. */
  100. canAuthorize(): boolean {
  101. // 正则表达式验证邮箱和密码是否合法
  102. return isEmail(this.email) && isRightPassword(this.password,this.rePassword)
  103. && this.verificationCode !== '';
  104. }
  105. /**
  106. * 点击注册
  107. */
  108. onAuthButtonClicked() {
  109. // 登陆认证
  110. this.canLogin = false;
  111. // 调用自定义emailRegister函数
  112. this.emailRegister(this.email, this.rePassword, this.verificationCode).then(user => {
  113. // 使用AppStorage存储用户数据 应用级状态共享
  114. AppStorage.Set<AgUser>('user', user);
  115. Log.info(TAG, "Logged in succesfully.");
  116. this.canLogin = true;
  117. // this.controller?.close(); ?
  118. // 注册成功后跳转至主页
  119. router.pushUrl({
  120. url:"pages/Index"
  121. })
  122. }).catch((err) => {
  123. this.canLogin = true;
  124. Log.error(TAG, "Logged in failed " + JSON.stringify(err));
  125. AlertDialog.show({
  126. title: '异常',
  127. message: '注册错误!',
  128. });
  129. });
  130. }
  131. /**
  132. * email用户注册
  133. * @param email
  134. * @param password
  135. * @param verifyCode
  136. * @returns
  137. */
  138. public async emailRegister(email: string, password: string, verifyCode: string): Promise<AgUser> {
  139. return new Promise((resolve, reject) => {
  140. // 创建email用户
  141. cloud.auth().createUser({
  142. kind: 'email',
  143. email: email,
  144. password: password,//可以给用户设置初始密码。后续可以用密码来登录
  145. verifyCode: verifyCode
  146. }).then(async (ret) => { //理解async关键字作用
  147. //创建帐号成功后,默认已登录
  148. Log.info(TAG, "用户创建完毕并登陆..");
  149. // @ts-ignore
  150. let user = ret.getUser();
  151. // 用户认证扩展信息
  152. let userExtra = await ret.getUser().getUserExtra();
  153. // 创建认证用户实体
  154. let loginRes = new AgUser(
  155. // uuid
  156. user.getUid(),
  157. user.getPhotoUrl(),
  158. user.getPhone(),
  159. user.getEmail(),
  160. // 用户名称
  161. user.getDisplayName(),
  162. userExtra.getCreateTime(),
  163. userExtra.getLastSignInTime())
  164. Log.info(TAG, '---'+user.getUid()+'---@');
  165. resolve(loginRes);
  166. }).catch(error => {
  167. //创建用户失败
  168. Log.error(TAG, "Error: ", error);
  169. reject(error);
  170. })
  171. })
  172. }
  173. build() {
  174. // 容器列,每列间隔10虚拟像素
  175. Column({space:10}) {
  176. // 插入一行
  177. Row(){
  178. Text("用户注册")
  179. .fontSize(28)
  180. }
  181. // 插入一行
  182. Row(){
  183. // Email输入框
  184. TextInput({placeholder:'请输入Email'})
  185. .type(InputType.Email)
  186. .width('60%')
  187. .borderRadius(0)
  188. .border({width:1,color:this.emailTipColor})
  189. .backgroundColor('#FFFFFF')
  190. .maxLength(36)
  191. .onChange((value)=>{
  192. this.email = value;
  193. if(isEmail(this.email)){
  194. this.emailTipColor = this.emailRightColor
  195. }
  196. })
  197. // 失去焦点时错误提示
  198. .onBlur(()=>{
  199. if(isEmail(this.email)){
  200. this.emailTipColor = this.emailRightColor
  201. }else{
  202. this.emailTipColor = this.emailWrongColor
  203. }
  204. })
  205. }
  206. // 插入一行 密码输入
  207. Row(){
  208. TextInput({placeholder:'密码不少于5位'})
  209. .type(InputType.Password)
  210. .width('60%')
  211. .borderRadius(0)
  212. .border({width:1,color:this.passwordTipColor})
  213. .backgroundColor('#FFFFFF')
  214. .maxLength(20)
  215. .onChange((value)=>{
  216. this.password = value;
  217. if(this.password.length>=5){
  218. this.passwordTipColor = this.passwordRightColor
  219. }
  220. })
  221. // 失去焦点时错误提示
  222. .onBlur(()=>{
  223. if(this.password.length<5){
  224. this.passwordTipColor = this.passwordWrongColor
  225. }else{
  226. this.passwordTipColor = this.passwordRightColor
  227. }
  228. })
  229. }
  230. // 插入一行 再次输入密码
  231. Row(){
  232. TextInput({placeholder:'请再次输入密码'})
  233. .type(InputType.Password)
  234. .width('60%')
  235. .borderRadius(0)
  236. .border({width:1,color:this.rPasswordTipColor})
  237. .backgroundColor('#FFFFFF')
  238. .maxLength(20)
  239. .onChange((value)=>{
  240. this.rePassword = value;
  241. if(this.rePassword===this.password){
  242. this.rPasswordTipColor = this.rPasswordRightColor
  243. }
  244. })
  245. // 失去焦点时错误提示
  246. .onBlur(()=>{
  247. if(this.rePassword!=this.password){
  248. this.rPasswordTipColor = this.rPasswordWrongColor
  249. }else{
  250. this.rPasswordTipColor = this.rPasswordRightColor
  251. }
  252. })
  253. }
  254. // 插入一行
  255. Row(){
  256. // 行内插入一列,输入验证码
  257. Column(){
  258. TextInput({ placeholder: '验证码', text: this.verificationCode })
  259. .type(InputType.Normal)
  260. .width('50%')
  261. .borderRadius(0)
  262. .border({width:1,color:'#F5F5F5'})
  263. .backgroundColor('#FFFFFF')
  264. .maxLength(6)
  265. .onChange(value=>{
  266. this.verificationCode = value
  267. })
  268. }
  269. // 行内插入一列,点击发送验证码按钮
  270. Column(){
  271. // 正则表达式验证email合法性
  272. Button(this.timer === 60 ? '发送验证码' : this.timer.toString())
  273. .type(ButtonType.Normal)
  274. .width('50%')
  275. .fontColor('#FF7F00')
  276. .backgroundColor('#FFFFFF')
  277. .border({width:1,color:'#FF7F00'})
  278. // 可以封装成方法调用
  279. // 发送验证码
  280. .onClick(()=>{
  281. // 这里怎么触发email框提示?
  282. this.onGetCodeButtonClicked()
  283. })
  284. }
  285. }.width('60%')
  286. // 插入一行,注册按钮
  287. Row({space:10}){
  288. Button("注册")
  289. .type(ButtonType.Normal)
  290. .backgroundColor('#FF7F00')
  291. // 透明度?
  292. .opacity(this.canLogin ? 1 : 0.5)
  293. // 正则表达式验证email合法性
  294. .enabled(this.canAuthorize()&&this.verificationCode.length>5&& this.canLogin)
  295. .onClick(()=>{
  296. // console.log("表单输入-----")
  297. // console.log(this.email)
  298. // console.log(this.verificationCode)
  299. // console.log("-----")
  300. this.onAuthButtonClicked()
  301. })
  302. }
  303. }
  304. .height('100%')
  305. .width('100%')
  306. .justifyContent(FlexAlign.Center)
  307. }
  308. }

3.用户登陆 

        1)用户登录页面

        UI组件布局

  1. build() {
  2. Column({space:10}) {
  3. Row(){
  4. Text("Email登陆")
  5. .fontSize(28)
  6. }
  7. Row(){
  8. TextInput({placeholder:'请输入Email'})
  9. .type(InputType.Email)
  10. .width('60%')
  11. .borderRadius(0)
  12. .border({width:1,color:'#F5F5F5'})
  13. .backgroundColor('#FFFFFF')
  14. .maxLength(36)
  15. }
  16. Row(){
  17. TextInput({placeholder:'请输入密码'})
  18. .type(InputType.Password)
  19. .width('60%')
  20. .borderRadius(0)
  21. .border({width:1,color:'#F5F5F5'})
  22. .backgroundColor('#FFFFFF')
  23. .maxLength(20)
  24. }
  25. Row({space:10}){
  26. Button("登陆")
  27. .type(ButtonType.Normal)
  28. .backgroundColor('#FF7F00')
  29. Button("注册")
  30. .type(ButtonType.Normal)
  31. .backgroundColor('#336699')
  32. }
  33. Row(){
  34. Button("匿名登陆")
  35. .type(ButtonType.Normal)
  36. .border({width:1,color:'#F5F5F5'})
  37. .backgroundColor('#FFFFFF')
  38. .fontColor('#000000')
  39. }
  40. }
  41. .height('100%')
  42. .width('100%')
  43. .justifyContent(FlexAlign.Center)
  44. }

        2)用户登录功能

a)增加@State状态来保存密码功能相关状态。

  1. @State email: string = ''
  2. @State password: string = ''

 b)修改登录按钮代码,并增加onClick监听。

  1. Row({space:10}) {
  2. Button("登陆")
  3. .type(ButtonType.Normal)
  4. .backgroundColor('#FF7F00')
  5. .onClick(() => {
  6. this.onLoginButtonClicked()
  7. })
  8. }

c)处理逻辑代码。

  1. /**
  2. * 点击登陆
  3. */
  4. onLoginButtonClicked() {
  5. // 登陆认证
  6. this.emailLogin(this.email, this.password).then(user => {
  7. // 使用AppStorage存储用户认证数据以便后续使用(应用级状态共享)
  8. AppStorage.Set<AgUser>('user', user);
  9. console.log("Logged in succesfully.");
  10. router.pushUrl({
  11. url:"pages/Index"
  12. })
  13. }).catch((err) => {
  14. console.log("Logged in failed " + JSON.stringify(err));
  15. AlertDialog.show({
  16. title: '异常',
  17. message: '登陆失败!',
  18. });
  19. });
  20. }
  1. public async emailLogin(email: string, password: string): Promise<AgUser> {
  2. return new Promise((resolve, reject) => {
  3. // 登陆email用户
  4. cloud.auth().signIn({
  5. autoCreateUser: false,
  6. credentialInfo: {
  7. kind: 'email',
  8. password: this.password,
  9. email: this.email
  10. }
  11. }).then(async (ret) => { // ret <==> user
  12. //登录成功
  13. console.log("用户登陆成功..");
  14. // @ts-ignore
  15. let user = ret.getUser();
  16. let userExtra = await ret.getUser().getUserExtra();
  17. // 创建认证用户实体
  18. let loginRes = new AgUser(
  19. user.getUid(),
  20. user.getPhotoUrl(),
  21. user.getPhone(),
  22. user.getEmail(),
  23. user.getDisplayName(),
  24. userExtra.getCreateTime(),
  25. userExtra.getLastSignInTime())
  26. console.log('---'+user.getUid()+'---l@');
  27. // 返回认证用户
  28. resolve(loginRes);
  29. }).catch(error => {
  30. //登录失败
  31. console.log("Error: ", error);
  32. reject(error);
  33. });
  34. })
  35. }

 用户登陆页面完整代码

  1. /**
  2. * 登陆 Serverless 认证功能
  3. */
  4. import router from '@ohos.router'
  5. import cloud from '@hw-agconnect/cloud';
  6. import { isEmail} from '../../common/auth/EmailReg'
  7. import { Log } from '../../common/Log';
  8. import { AgUser } from '../../services/Auth';
  9. const TAG = "[AGCAuth]";
  10. @Entry
  11. @Component
  12. struct LoginByEmail {
  13. // 是否可以登陆
  14. @State canLogin: boolean = true;
  15. @State email: string = ''
  16. @State password: string = ''
  17. // email校验
  18. @State emailTipColor: string = '#F5F5F5'
  19. @State emailRightColor: string = '#F5F5F5'
  20. @State emailWrongColor: string = '#FF7F00'
  21. // 输入密码校验
  22. @State passwordTipColor: string = '#F5F5F5'
  23. @State passwordRightColor: string = '#F5F5F5'
  24. @State passwordWrongColor: string = '#FF7F00'
  25. /**
  26. * 是否可以点击登陆
  27. * @returns
  28. */
  29. canLoginEmail(): boolean {
  30. return isEmail(this.email) && this.password.length>4
  31. }
  32. public async emailLogin(email: string, password: string): Promise<AgUser> {
  33. return new Promise((resolve, reject) => {
  34. // 登陆email用户
  35. cloud.auth().signIn({
  36. autoCreateUser: false,
  37. credentialInfo: {
  38. kind: 'email',
  39. password: this.password,
  40. email: this.email
  41. }
  42. }).then(async (ret) => { // ret <==> user
  43. //登录成功
  44. Log.info(TAG, "用户登陆成功..");
  45. // @ts-ignore
  46. let user = ret.getUser();
  47. let userExtra = await ret.getUser().getUserExtra();
  48. let loginRes = new AgUser(
  49. user.getUid(),
  50. user.getPhotoUrl(),
  51. user.getPhone(),
  52. user.getEmail(),
  53. user.getDisplayName(),
  54. userExtra.getCreateTime(),
  55. userExtra.getLastSignInTime())
  56. Log.info(TAG, '---'+user.getUid()+'---l@');
  57. resolve(loginRes);
  58. }).catch(error => {
  59. //登录失败
  60. Log.error(TAG, "Error: ", error);
  61. reject(error);
  62. });
  63. })
  64. }
  65. /**
  66. * 点击登陆
  67. */
  68. onLoginButtonClicked() {
  69. // 登陆认证
  70. this.canLogin = false;
  71. this.emailLogin(this.email, this.password).then(user => {
  72. AppStorage.Set<AgUser>('user', user);
  73. Log.info(TAG, "Logged in succesfully.");
  74. this.canLogin = true;
  75. // this.controller?.close(); ?
  76. router.pushUrl({
  77. url:"pages/Index"
  78. })
  79. }).catch((err) => {
  80. this.canLogin = true;
  81. Log.error(TAG, "Logged in failed " + JSON.stringify(err));
  82. AlertDialog.show({
  83. title: '异常',
  84. message: '登陆失败!',
  85. });
  86. });
  87. }
  88. build() {
  89. Column({space:10}) {
  90. Row(){
  91. Text("Email登陆")
  92. .fontSize(28)
  93. }
  94. Row(){
  95. TextInput({placeholder:'请输入Email'})
  96. .type(InputType.Email)
  97. .width('60%')
  98. .borderRadius(0)
  99. .border({width:1,color:this.emailTipColor})
  100. .backgroundColor('#FFFFFF')
  101. .maxLength(36)
  102. .onChange((value)=>{
  103. this.email = value;
  104. if(isEmail(this.email)){
  105. this.emailTipColor = this.emailRightColor
  106. }
  107. })
  108. .onBlur(()=>{
  109. if(isEmail(this.email)){
  110. this.emailTipColor = this.emailRightColor
  111. }else{
  112. this.emailTipColor = this.emailWrongColor
  113. }
  114. })
  115. }
  116. Row(){
  117. TextInput({placeholder:'请输入密码'})
  118. .type(InputType.Password)
  119. .width('60%')
  120. .borderRadius(0)
  121. .border({width:1,color:this.passwordTipColor})
  122. .backgroundColor('#FFFFFF')
  123. .maxLength(20)
  124. .onChange((value)=>{
  125. this.password = value;
  126. })
  127. }
  128. Row({space:10}){
  129. Button("登陆")
  130. .type(ButtonType.Normal)
  131. .backgroundColor('#FF7F00')
  132. .enabled(this.canLoginEmail())
  133. .onClick(()=>{
  134. this.onLoginButtonClicked()
  135. })
  136. Button("注册")
  137. .type(ButtonType.Normal)
  138. .backgroundColor('#336699')
  139. .onClick(()=>{
  140. router.pushUrl({
  141. url:"pages/auth/RegisterByEmail"
  142. })
  143. })
  144. }
  145. Row(){
  146. Button("匿名登陆")
  147. .type(ButtonType.Normal)
  148. .border({width:1,color:'#F5F5F5'})
  149. .backgroundColor('#FFFFFF')
  150. .fontColor('#000000')
  151. .onClick(()=>{
  152. cloud.auth().signInAnonymously().then(user => {
  153. //匿名登录成功
  154. console.log("匿名登陆成功-----")
  155. console.log(user.getUser().getUid())
  156. console.log(user.getUser().getDisplayName())
  157. console.log("-----")
  158. router.pushUrl({
  159. url:"pages/auth/anonymous/Anonymous",
  160. params:{
  161. src:user.getUser().getUid()
  162. }
  163. })
  164. }).catch(error => {
  165. //匿名登录失败
  166. console.log("匿名登陆失败-----")
  167. console.log("-----")
  168. });
  169. })
  170. }
  171. }
  172. .height('100%')
  173. .width('100%')
  174. .justifyContent(FlexAlign.Center)
  175. }
  176. }

4.首页展示用户信息

        1)首页

        UI组件布局

  1. build() {
  2. Column() {
  3. Row(){
  4. Text('首页')
  5. Text(' | ')
  6. Text('MySpring.cc')
  7. Text(' | ')
  8. Text(' 登陆 ')
  9. }.padding(10)
  10. .width('100%')
  11. .justifyContent(FlexAlign.Center)
  12. }
  13. .height('100%')
  14. }

        2)定义user来接受用户登陆/注册的认证信息

  1. // 状态共享 用户登陆后的认证信息保存在这里
  2. @StorageLink('user')
  3. user:AgUser = null

        3)如果是登陆/注册成功跳转到首页展示用户信息和登出 

  1. build() {
  2. Column() {
  3. Row(){
  4. Text('首页')
  5. Text(' | ')
  6. Text('MySpring.cc')
  7. Text(' | ')
  8. // 登陆后显示用户名字或者uuid
  9. if(this.user){
  10. // 如果有用户名称展示用户名称
  11. if(this.user.getDisplayName()){
  12. Text(this.user.getDisplayName()+'')
  13. // 否则如果有用户uuid展示用户名称
  14. }else if(this.user.getUid()){
  15. Text(this.user.getUid()+'')
  16. // 如果没有登陆用户,显示'登陆'
  17. }else{
  18. Text(' 登陆 ')
  19. .onClick(()=>{
  20. router.pushUrl({
  21. url:"pages/auth/LoginByEmail"
  22. })
  23. })
  24. }
  25. //如果user为空
  26. }else{
  27. Text(' 登陆 ')
  28. .onClick(()=>{
  29. router.pushUrl({
  30. url:"pages/auth/LoginByEmail"
  31. })
  32. })
  33. }
  34. // 如果user认证通过
  35. if(this.user){
  36. if(this.user.getUid()){
  37. Text(' 登出 ')
  38. }
  39. }
  40. }.padding(10)
  41. .width('100%')
  42. .justifyContent(FlexAlign.Center)
  43. }
  44. .height('100%')
  45. }

5.用户登出

        a)登出按钮增加onClick监听

  1. if(this.user){
  2. if(this.user.getUid()){
  3. Text(' 登出 ')
  4. .onClick(()=>{
  5. this.onLogoutButtonClicked()
  6. })
  7. }
  8. }

         b)处理逻辑代码

  1. // 点击登出
  2. async onLogoutButtonClicked() {
  3. await this.logout().then((res) => {
  4. if (res) {
  5. // 检查是否登出 测试
  6. cloud.auth().getCurrentUser().then((user)=>{
  7. if(user){
  8. console.log("Logout after."+user.getUid());
  9. }else{
  10. console.log("Logout after...");
  11. }
  12. })
  13. // 重置user(相当于清除)
  14. AppStorage.Set<AgUser>('user', new AgUser());
  15. // AppStorage.Set<AgUser>('user',null) // 这了不能仅仅设置为null
  16. router.pushUrl({
  17. url:"pages/Index"
  18. })
  19. }
  20. })
  21. }
  1. // 登出
  2. public async logout(): Promise<boolean> {
  3. return new Promise<boolean>((resolve, reject) => {
  4. // 认证登出
  5. cloud.auth().signOut().then(() => {
  6. resolve(true);
  7. }).catch((error) => {
  8. console.log("error", error);
  9. reject(error);
  10. });
  11. });
  12. }

 首页完整代码

  1. import router from '@ohos.router'
  2. import cloud from '@hw-agconnect/cloud';
  3. import { AgUser } from '../services/Auth';
  4. import { Log } from '../common/Log';
  5. const TAG = "[AGCAuth]";
  6. @Entry
  7. @Component
  8. struct Index {
  9. @State message: string = 'Hello World'
  10. // 是否可以登出
  11. @State canLogOut: boolean = true;
  12. // 状态共享 用户登陆后的认证信息保存在这里
  13. @StorageLink('user')
  14. user:AgUser = null
  15. // 如果名字太长,截取前部分字符串
  16. minNameOrUUID(nameOrId:String):String{
  17. if(nameOrId.length<6){
  18. return nameOrId
  19. }else{
  20. return nameOrId.substring(0,4)+'..'
  21. }
  22. }
  23. // 登出
  24. public async logout(): Promise<boolean> {
  25. return new Promise<boolean>((resolve, reject) => {
  26. // 认证登出
  27. cloud.auth().signOut().then(() => {
  28. resolve(true);
  29. }).catch((error) => {
  30. Log.error(TAG, "error", error);
  31. reject(error);
  32. });
  33. });
  34. }
  35. // 点击登出
  36. async onLogoutButtonClicked() {
  37. this.canLogOut = false
  38. await this.logout().then((res) => {
  39. if (res) {
  40. // 检查是否登出 测试
  41. cloud.auth().getCurrentUser().then((user)=>{
  42. if(user){
  43. Log.info(TAG, "Logout after."+user.getUid());
  44. }else{
  45. Log.info(TAG, "Logout after...");
  46. }
  47. })
  48. // 重置user
  49. AppStorage.Set<AgUser>('user', new AgUser());
  50. // AppStorage.Set<AgUser>('user',null) // 无法设置为null
  51. this.canLogOut = true
  52. router.pushUrl({
  53. url:"pages/Index"
  54. })
  55. }
  56. })
  57. }
  58. build() {
  59. Column() {
  60. Row(){
  61. Text('首页')
  62. .onClick(()=>{
  63. // 测试
  64. router.pushUrl({
  65. url:"pages/auth/ThreePage"
  66. })
  67. })
  68. Text(' | ')
  69. Text('MySpring.cc')
  70. Text(' | ')
  71. // 登陆后显示用户名字或者uuid
  72. if(this.user){
  73. if(this.user.getDisplayName()){
  74. Text(' '+this.minNameOrUUID(this.user.getDisplayName())+' ')
  75. }else if(this.user.getUid()){
  76. Text(' '+this.minNameOrUUID(this.user.getUid())+' ')
  77. }else{ // 如果没有登陆用户,显示'登陆'
  78. Text(' 登陆 ')
  79. .onClick(()=>{
  80. router.pushUrl({
  81. url:"pages/auth/LoginByEmail"
  82. })
  83. })
  84. }
  85. }else{
  86. Text(' 登陆 ')
  87. .onClick(()=>{
  88. router.pushUrl({
  89. url:"pages/auth/LoginByEmail"
  90. })
  91. })
  92. }
  93. if(this.user){
  94. if(this.user.getUid()){
  95. Text(' 登出 ')
  96. .enabled(this.canLogOut)
  97. .onClick(()=>{
  98. this.onLogoutButtonClicked()
  99. })
  100. }
  101. }
  102. }.padding(10)
  103. .width('100%')
  104. .justifyContent(FlexAlign.Center)
  105. }
  106. .height('100%')
  107. }
  108. }

   

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/102569
推荐阅读
相关标签
  

闽ICP备14008679号