狠狠色丁香婷婷综合尤物/久久精品综合一区二区三区/中国有色金属学报/国产日韩欧美在线观看 - 国产一区二区三区四区五区tv

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發文檔 其他文檔  
 
網站管理員

用戶注冊這樣玩,保你平安

freeflydom
2023年12月1日 12:0 本文熱度 586

前言

基本上每個系統系統都包含用戶注冊、發送驗證碼等基本操作。在前些年,我還記得我在逛 csdn、貼吧、網易新聞等網站的時候是可以不登陸也能瀏覽完網頁內容的,但是近幾年這些網站已經改成了不登陸不讓用,瀏覽網頁時不時提醒你要進行登錄,對于一些不喜歡注冊的用戶造成了相當大的困擾。

但是不知道大家有沒有想過這里面的深層邏輯,就是為什么前些年什么 csdn、貼吧、網易新聞等明明不進行登錄瀏覽網頁體驗還行,現在要改成這樣子?

這里面涉及的因素有很多,比如互聯網發展到頭、變現困難、存量環境加劇內卷等。

當公司盈利壓力變大,老板眼看收益日趨降低,便開始拉領導開會,領導開完會開始 PUA 員工,一層一層遞進,輔以績效、okr 等工具制定目標結果。于是公司底層員工的想法從努力賺錢、升職加薪變成保住飯碗、養活一家老小,對于業務上的月度、季度營收要求自然是各種促進用戶付費的手段應上齊上。

這里面提升付費有一個非常重要的前提就是用戶,只要有了用戶就有付費希望。

如果用戶不注冊,不留下手機號、郵箱等個人信息,互聯網運營又怎么給這些用戶發送營銷短信和郵件。所以說強制注冊本質上是為了公司利益。

只要把用戶留下來,留在自己的 APP 里,收集用戶信息,后續各種運營活動、支付彈窗、短信找回、活動抽獎一起上,何愁沒有用戶 😜。

用戶信息記錄的意義是為了聚集 C 端用戶、收集信息,為后續運營活動(提升付費)做準備。就拿淘寶舉例,個性化推薦、千人千面、雙 11 活動等,這一系列運營活動說到底都是為了提升淘寶的付費金額,提升淘寶平臺的 GMV。什么個性化推薦、千人千面說白了就是收集你的個人信息,你的商品點擊、瀏覽、下單等操作都會被淘寶采集,進而通過算法模型進行商品推薦,選出你可能感興趣的商品展示,從而提升淘寶付費金額。

OK,到這里題外話說多了,雖然說用戶注冊是一個很基本的邏輯,但是很多人一不小心就會掉坑里。這里我給大家介紹下 waynboot-mall 項目中用戶注冊是怎么玩的,為什么說可以保你平安。

waynboot-mall 項目是由我開源的一套 H5 商城項目,包含運營后臺、H5 商城前臺和服務端接口。實現了商城所需的首頁展示、商品分類、商品詳情、商品 sku、分詞搜索、購物車、結算下單、支付寶/微信支付、收單評論以及完善的后臺管理等一系列功能。 技術上基于最新得 Springboot3.0 框架開發而來,整合了 MySql、Redis、RabbitMQ、ElasticSearch 等常用中間件。商城模塊劃分合理、代碼質量較高、易于部署,非常適合大家拿來學習使用。

github 地址:https://github.com/wayn111/waynboot-mall

用戶注冊

在 waynboot-mall 項目中,商城注冊頁面截圖如下。

/captcha 生成圖形驗證碼接口

@ResponseBody

@RequestMapping("/captcha")

public R captcha() {

    // 1. 創建驗證碼對象,定義驗證碼圖形的長、寬、以及字數

    SpecCaptcha specCaptcha = new SpecCaptcha(80, 32, 4);

    // 2. 生成驗證碼

    String verCode = specCaptcha.text().toLowerCase();

    // 3. 生成驗證碼唯一key

    String captchaKey = IdUtil.getUid();

    // 4. 存入redis并設置過期時間為30分鐘

    redisCache.setCacheObject(captchaKey, verCode, SysConstants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);

    // 5. 將key和base64返回給前端

    return R.success().add("captchaKey", captchaKey).add("image", specCaptcha.toBase64());

}

驗證碼接口基本是每個系統都有的接口,驗證碼主要是為了防止別人直接調用接口進行注冊操作,是一個安全措施。現在市面上流行的有圖形驗證碼、滑塊驗證碼、點選驗證碼等,waynboot-mall 項目中使用的圖形驗證碼,大家有興趣可以了解 tianai-captcha 這個項目,包含滑塊驗證碼、點選驗證碼等。現在我們對驗證碼接口進行講解,

  • 第一步,創建驗證碼對象,定義驗證碼圖形的長、寬、以及字數(這里創建的 SpecCaptcha 對象來自 easy-captcha 項目)

  • 第二步,生成驗證碼 verCode

  • 第三步,為驗證碼生成唯一 captchaKey

  • 第四步,將 captchaKey 作為 key, verCode 作為 value,存入 redis 并設置過期時間

  • 第五步,將 captchaKey 以及驗證碼圖像的 base64 編碼返回給前端

前端在調用完 /captcha 接口后,會拿到 captchaKey 以及驗證碼圖像的 base64 編碼,之后前端就可以將 base64 編碼作為 img 標簽 src 屬性用作圖形驗證碼展示。

用戶輸入郵箱和圖形驗證碼后就可以點擊發送郵箱驗證碼了。

調用發送郵箱驗證碼接口時會將 captchaKey、驗證碼、手機號等信息一起傳給服務端。

/sendEmailCode 發送郵箱驗證碼接口

@PostMapping("/sendEmailCode")

public R sendEmailCode(@RequestBody RegistryObj registryObj) {

    String captchaKey = registryObj.getCaptchaKey();

    String captchaCode = registryObj.getCaptchaCode();

    String mobile = registryObj.getMobile();

    if (StringUtils.isBlank(captchaKey)) {

        return R.error(CUSTOM_ERROR.setMsg("圖形驗證碼錯誤"));

    }

    if (StringUtils.isBlank(captchaCode)) {

        return R.error(CUSTOM_ERROR.setMsg("圖形驗證碼為空"));

    }

    if (StringUtils.isBlank(mobile)) {

        return R.error(CUSTOM_ERROR.setMsg("手機號為空"));

    }

    String redisCode = redisCache.getCacheObject(captchaKey);

    // 判斷驗證碼code

    if (!redisCode.equals(captchaCode.trim().toLowerCase())) {

        return R.error(USER_CAPTCHA_CODE_ERROR);

    }

    // 驗證手機號是否唯一

    long count = iMemberService.count(Wrappers.lambdaQuery(Member.class).eq(Member::getMobile, mobile));

    if (count > 0) {

        return R.error(USER_PHONE_HAS_REGISTER_ERROR);

    }

    // 生成郵箱驗證碼code

    String emailCode = RandomUtil.randomString(6);

    // 生成郵箱驗證碼唯一key

    String emailKey = RedisKeyEnum.EMAIL_KEY_CACHE.getKey(IdUtil.getUid());

    // 存入redis并設置過期時間為20分鐘

    redisCache.setCacheObject(emailKey, emailCode + "_" + mobile,  RedisKeyEnum.EMAIL_KEY_CACHE.getExpireSecond());

    commonThreadPoolTaskexecutor.execute(() -> {

        EmailConfig emailConfig = mailConfigService.getById(1L);

        SendMailVO sendMailVO = new SendMailVO();

        sendMailVO.setSubject("mall商城注冊通知");

        sendMailVO.setContent("郵箱驗證碼:" + emailCode);

        sendMailVO.setTos(Collections.singletonList(registryObj.getEmail()));

        MailUtil.sendMail(emailConfig, sendMailVO, false, false);

    });

    return R.success().add("emailKey", emailKey);

}

一般商城系統中,發送郵箱驗證碼、短信驗證碼時都需要進行驗證碼輸入這一步驟,這是為了防止別人直接通過接口調用的形式,浪費我們系統的資源,特別是發送手機驗證碼、郵件這種資源。發送郵箱驗證碼接口講解如下,

  • 第一步,校驗 captchaKey、captchaCode、mobile 必傳參數

  • 第二步,根據 captchaKey 讀取 redis 中存放的驗證碼 code,與用戶輸入 captchaCode 進行比較

  • 第三步,驗證用戶手機號是否唯一

  • 第四步,生成六位郵箱驗證碼 emailCode

  • 第五步,生成郵箱驗證碼唯一 emailKey

  • 第六步,將 emailKey 作為 key, emailCode_mobile 作為 value,存入 redis 并設置過期時間(注意這一步將用戶手機號,也存入 Redis 是為了防止用戶在獲取完郵箱驗證碼后修改手機號,這一點很重要,很多開發同學都忘了這一步)

  • 第七步,使用線程池異步發送驗證碼郵件

前端在調用完 /sendEmailCode 接口后,就可以拿到 emailKey。

這樣等用戶輸入郵箱里的驗證碼后,點擊注冊按鈕,我們就可能正式開始注冊操作了。

/registry 用戶注冊

@PostMapping("/registry")

public R registry(@RequestBody RegistryObj registryObj) {

    // 驗證兩次密碼輸入是否一致

    if (!StringUtils.equalsIgnoreCase(registryObj.getPassword(), registryObj.getConfirmPassword())) {

        return R.error(USER_TWO_PASSWORD_NOT_SAME_ERROR);

    }

    // 驗證用戶手機號是否唯一

    long count = iMemberService.count(Wrappers.lambdaQuery(Member.class).eq(Member::getMobile, registryObj.getMobile()));

    if (count > 0) {

        return R.error(USER_PHONE_HAS_REGISTER_ERROR);

    }


    // 判斷圖形驗證碼

    String redisCaptchaCode = redisCache.getCacheObject(registryObj.getCaptchaKey());

    if (registryObj.getCaptchaCode() == null || !redisCaptchaCode.equals(registryObj.getCaptchaCode().trim().toLowerCase())) {

        return R.error(USER_CAPTCHA_CODE_ERROR);

    }


    // 判斷郵箱驗證碼

    String value = redisCache.getCacheObject(registryObj.getEmailKey());

    String[] split = value.split("_");

    if (split.length < 2) {

        return R.error(ReturnCodeEnum.USER_EMAIL_CODE_ERROR);

    }

    String redisEmailCode = split[0];

    String mobile = split[1];

    // 判斷發送郵箱驗證碼的手機號是否與用戶當前傳入手機號一致

    if (!StringUtils.equalsIgnoreCase(mobile, registryObj.getMobile())) {

        return R.error(ReturnCodeEnum.USER_REGISTER_MOBILE_ERROR);

    }

    // 判斷用戶輸入郵箱驗證碼是否正確

    if (registryObj.getEmailCode() == null || !redisEmailCode.equals(registryObj.getEmailCode().trim().toLowerCase())) {

        return R.error(ReturnCodeEnum.USER_EMAIL_CODE_ERROR);

    }

    // 刪除驗證碼

    redisCache.deleteObject(registryObj.getCaptchaKey());

    redisCache.deleteObject(registryObj.getEmailKey());

    Member member = new Member();

    long time = System.currentTimeMillis();

    member.setNickname("昵稱" + time / 1000);

    String avatar = SysConstants.DEFAULT_AVATAR;

    member.setAvatar(avatar);

    member.setMobile(registryObj.getMobile());

    member.setEmail(registryObj.getEmail());

    member.setPassword(SecurityUtils.encryptPassword(registryObj.getPassword()));

    member.setcreateTime(new Date());

    return R.result(iMemberService.save(member));

}

注冊接口,需要邏輯完善,所以這里的校驗邏輯會比較多,因為一個商城最重要的幾個接口就是注冊、登錄、下單、支付等。

除了能讓用戶正常注冊外,有時候還需要確保用戶一個手機號只能注冊一個賬號,完成對用戶手機號在商城的唯一性保障。除了先查詢用戶手機號是否已存在外,還需要對用戶 member 表的手機號字段設置唯一索引來完成。注冊接口講解如下,

唯一索引可以防止用戶重復點擊注冊按鈕,保證一個手機號只能注冊一個用戶。

  • 第一步,驗證用戶輸入兩次密碼是否一致

  • 第二步,驗證用戶輸入的手機號是否唯一

  • 第三步,驗證用戶輸入的圖形驗證碼是否于 Redis 中存儲一致

  • 第四步,驗證發送郵箱驗證碼的手機號是否于 Redis 中存儲一致

  • 第五步,驗證用戶輸入的郵箱驗證碼是否于 Redis 中存儲一致

  • 第六步,校驗通過,開始刪除圖形驗證碼、郵箱驗證碼

  • 第七步,啟動線程池,異步進行用戶保存操作

最后聊兩句

用戶注冊說簡單是很簡單,但是校驗邏輯一定要做好!這是我的踩坑經驗,現在我傳授給你,希望能幫你平安🤝。

作者:waynaqua

原文鏈接:https://www.cnblogs.com/waynaqua/p/17868631.html



該文章在 2023/12/1 14:18:52 編輯過
關鍵字查詢
相關文章
正在查詢...
點晴ERP是一款針對中小制造業的專業生產管理軟件系統,系統成熟度和易用性得到了國內大量中小企業的青睞。
點晴PMS碼頭管理系統主要針對港口碼頭集裝箱與散貨日常運作、調度、堆場、車隊、財務費用、相關報表等業務管理,結合碼頭的業務特點,圍繞調度、堆場作業而開發的。集技術的先進性、管理的有效性于一體,是物流碼頭及其他港口類企業的高效ERP管理信息系統。
點晴WMS倉儲管理系統提供了貨物產品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質期管理,貨位管理,庫位管理,生產管理,WMS管理系統,標簽打印,條形碼,二維碼管理,批號管理軟件。
點晴免費OA是一款軟件和通用服務都免費,不限功能、不限時間、不限用戶的免費OA協同辦公管理系統。
Copyright 2010-2025 ClickSun All Rights Reserved