用戶注冊這樣玩,保你平安
當(dāng)前位置:點(diǎn)晴教程→知識管理交流
→『 技術(shù)文檔交流 』
前言基本上每個(gè)系統(tǒng)系統(tǒng)都包含用戶注冊、發(fā)送驗(yàn)證碼等基本操作。在前些年,我還記得我在逛 csdn、貼吧、網(wǎng)易新聞等網(wǎng)站的時(shí)候是可以不登陸也能瀏覽完網(wǎng)頁內(nèi)容的,但是近幾年這些網(wǎng)站已經(jīng)改成了不登陸不讓用,瀏覽網(wǎng)頁時(shí)不時(shí)提醒你要進(jìn)行登錄,對于一些不喜歡注冊的用戶造成了相當(dāng)大的困擾。 但是不知道大家有沒有想過這里面的深層邏輯,就是為什么前些年什么 csdn、貼吧、網(wǎng)易新聞等明明不進(jìn)行登錄瀏覽網(wǎng)頁體驗(yàn)還行,現(xiàn)在要改成這樣子? 這里面涉及的因素有很多,比如互聯(lián)網(wǎng)發(fā)展到頭、變現(xiàn)困難、存量環(huán)境加劇內(nèi)卷等。 當(dāng)公司盈利壓力變大,老板眼看收益日趨降低,便開始拉領(lǐng)導(dǎo)開會(huì),領(lǐng)導(dǎo)開完會(huì)開始 PUA 員工,一層一層遞進(jìn),輔以績效、okr 等工具制定目標(biāo)結(jié)果。于是公司底層員工的想法從努力賺錢、升職加薪變成保住飯碗、養(yǎng)活一家老小,對于業(yè)務(wù)上的月度、季度營收要求自然是各種促進(jìn)用戶付費(fèi)的手段應(yīng)上齊上。 這里面提升付費(fèi)有一個(gè)非常重要的前提就是用戶,只要有了用戶就有付費(fèi)希望。 如果用戶不注冊,不留下手機(jī)號、郵箱等個(gè)人信息,互聯(lián)網(wǎng)運(yùn)營又怎么給這些用戶發(fā)送營銷短信和郵件。所以說強(qiáng)制注冊本質(zhì)上是為了公司利益。 只要把用戶留下來,留在自己的 APP 里,收集用戶信息,后續(xù)各種運(yùn)營活動(dòng)、支付彈窗、短信找回、活動(dòng)抽獎(jiǎng)一起上,何愁沒有用戶 😜。
OK,到這里題外話說多了,雖然說用戶注冊是一個(gè)很基本的邏輯,但是很多人一不小心就會(huì)掉坑里。這里我給大家介紹下 waynboot-mall 項(xiàng)目中用戶注冊是怎么玩的,為什么說可以保你平安。
用戶注冊在 waynboot-mall 項(xiàng)目中,商城注冊頁面截圖如下。 /captcha 生成圖形驗(yàn)證碼接口@ResponseBody @RequestMapping("/captcha") public R captcha() { // 1. 創(chuàng)建驗(yàn)證碼對象,定義驗(yàn)證碼圖形的長、寬、以及字?jǐn)?shù) SpecCaptcha specCaptcha = new SpecCaptcha(80, 32, 4); // 2. 生成驗(yàn)證碼 String verCode = specCaptcha.text().toLowerCase(); // 3. 生成驗(yàn)證碼唯一key String captchaKey = IdUtil.getUid(); // 4. 存入redis并設(shè)置過期時(shí)間為30分鐘 redisCache.setCacheObject(captchaKey, verCode, SysConstants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES); // 5. 將key和base64返回給前端 return R.success().add("captchaKey", captchaKey).add("image", specCaptcha.toBase64()); } 驗(yàn)證碼接口基本是每個(gè)系統(tǒng)都有的接口,驗(yàn)證碼主要是為了防止別人直接調(diào)用接口進(jìn)行注冊操作,是一個(gè)安全措施?,F(xiàn)在市面上流行的有圖形驗(yàn)證碼、滑塊驗(yàn)證碼、點(diǎn)選驗(yàn)證碼等,waynboot-mall 項(xiàng)目中使用的圖形驗(yàn)證碼,大家有興趣可以了解 tianai-captcha 這個(gè)項(xiàng)目,包含滑塊驗(yàn)證碼、點(diǎn)選驗(yàn)證碼等。現(xiàn)在我們對驗(yàn)證碼接口進(jìn)行講解,
前端在調(diào)用完 /captcha 接口后,會(huì)拿到 captchaKey 以及驗(yàn)證碼圖像的 base64 編碼,之后前端就可以將 base64 編碼作為 img 標(biāo)簽 src 屬性用作圖形驗(yàn)證碼展示。 用戶輸入郵箱和圖形驗(yàn)證碼后就可以點(diǎn)擊發(fā)送郵箱驗(yàn)證碼了。 調(diào)用發(fā)送郵箱驗(yàn)證碼接口時(shí)會(huì)將 captchaKey、驗(yàn)證碼、手機(jī)號等信息一起傳給服務(wù)端。 /sendEmailCode 發(fā)送郵箱驗(yàn)證碼接口@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("圖形驗(yàn)證碼錯(cuò)誤")); } if (StringUtils.isBlank(captchaCode)) { return R.error(CUSTOM_ERROR.setMsg("圖形驗(yàn)證碼為空")); } if (StringUtils.isBlank(mobile)) { return R.error(CUSTOM_ERROR.setMsg("手機(jī)號為空")); } String redisCode = redisCache.getCacheObject(captchaKey); // 判斷驗(yàn)證碼code if (!redisCode.equals(captchaCode.trim().toLowerCase())) { return R.error(USER_CAPTCHA_CODE_ERROR); } // 驗(yàn)證手機(jī)號是否唯一 long count = iMemberService.count(Wrappers.lambdaQuery(Member.class).eq(Member::getMobile, mobile)); if (count > 0) { return R.error(USER_PHONE_HAS_REGISTER_ERROR); } // 生成郵箱驗(yàn)證碼code String emailCode = RandomUtil.randomString(6); // 生成郵箱驗(yàn)證碼唯一key String emailKey = RedisKeyEnum.EMAIL_KEY_CACHE.getKey(IdUtil.getUid()); // 存入redis并設(shè)置過期時(shí)間為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("郵箱驗(yàn)證碼:" + emailCode); sendMailVO.setTos(Collections.singletonList(registryObj.getEmail())); MailUtil.sendMail(emailConfig, sendMailVO, false, false); }); return R.success().add("emailKey", emailKey); } 一般商城系統(tǒng)中,發(fā)送郵箱驗(yàn)證碼、短信驗(yàn)證碼時(shí)都需要進(jìn)行驗(yàn)證碼輸入這一步驟,這是為了防止別人直接通過接口調(diào)用的形式,浪費(fèi)我們系統(tǒng)的資源,特別是發(fā)送手機(jī)驗(yàn)證碼、郵件這種資源。發(fā)送郵箱驗(yàn)證碼接口講解如下,
前端在調(diào)用完 /sendEmailCode 接口后,就可以拿到 emailKey。 這樣等用戶輸入郵箱里的驗(yàn)證碼后,點(diǎn)擊注冊按鈕,我們就可能正式開始注冊操作了。 /registry 用戶注冊@PostMapping("/registry") public R registry(@RequestBody RegistryObj registryObj) { // 驗(yàn)證兩次密碼輸入是否一致 if (!StringUtils.equalsIgnoreCase(registryObj.getPassword(), registryObj.getConfirmPassword())) { return R.error(USER_TWO_PASSWORD_NOT_SAME_ERROR); } // 驗(yàn)證用戶手機(jī)號是否唯一 long count = iMemberService.count(Wrappers.lambdaQuery(Member.class).eq(Member::getMobile, registryObj.getMobile())); if (count > 0) { return R.error(USER_PHONE_HAS_REGISTER_ERROR); } // 判斷圖形驗(yàn)證碼 String redisCaptchaCode = redisCache.getCacheObject(registryObj.getCaptchaKey()); if (registryObj.getCaptchaCode() == null || !redisCaptchaCode.equals(registryObj.getCaptchaCode().trim().toLowerCase())) { return R.error(USER_CAPTCHA_CODE_ERROR); } // 判斷郵箱驗(yàn)證碼 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]; // 判斷發(fā)送郵箱驗(yàn)證碼的手機(jī)號是否與用戶當(dāng)前傳入手機(jī)號一致 if (!StringUtils.equalsIgnoreCase(mobile, registryObj.getMobile())) { return R.error(ReturnCodeEnum.USER_REGISTER_MOBILE_ERROR); } // 判斷用戶輸入郵箱驗(yàn)證碼是否正確 if (registryObj.getEmailCode() == null || !redisEmailCode.equals(registryObj.getEmailCode().trim().toLowerCase())) { return R.error(ReturnCodeEnum.USER_EMAIL_CODE_ERROR); } // 刪除驗(yàn)證碼 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)); } 注冊接口,需要邏輯完善,所以這里的校驗(yàn)邏輯會(huì)比較多,因?yàn)橐粋€(gè)商城最重要的幾個(gè)接口就是注冊、登錄、下單、支付等。 除了能讓用戶正常注冊外,有時(shí)候還需要確保用戶一個(gè)手機(jī)號只能注冊一個(gè)賬號,完成對用戶手機(jī)號在商城的唯一性保障。除了先查詢用戶手機(jī)號是否已存在外,還需要對用戶 member 表的手機(jī)號字段設(shè)置唯一索引來完成。注冊接口講解如下,
最后聊兩句用戶注冊說簡單是很簡單,但是校驗(yàn)邏輯一定要做好!這是我的踩坑經(jīng)驗(yàn),現(xiàn)在我傳授給你,希望能幫你平安🤝。 作者:waynaqua 原文鏈接:https://www.cnblogs.com/waynaqua/p/17868631.html 該文章在 2023/12/1 14:18:52 編輯過 |
關(guān)鍵字查詢
相關(guān)文章
正在查詢... |