炫酷又实用的发送邮箱链接修改密码
第一次写博客就拿出纯干货,手把手教你解决如何通过邮箱发送链接修改密码,这个是我在工作中实际遇到的情况,经过多次调试,可靠好用。
目录
需求分析:
一、准备工作:
二、发送链接:
三、点击链接(不做234条的可以跳过)
四、最终修改密码
需求分析
最终目标:
实现用户点击找回密码,选择邮箱方式后,向用户邮箱中发送一个修改链接,用户点击链接跳转到修改密码页面,提交后修改密码成功。
细节:
1:需要保证链接的唯一性,同时因为无登陆状态,链接应该能准确指向当前修改用户。
2:(可选)安全考量,设置链接在某个时间段内有效,一般为10分钟;
3:(可选)安全考量,设置链接仅可点击一次,退出再进,或者重复进入,均应被拒绝。
4:(可选)安全考量,当用户点击多次,发送多个链接时,仅最后一次发送的链接有效。
为什么说2和3是可选的呢,因为笔者在考察其他网站业务时,发现有一些大型知名网站并没有此类限制,可能目前手机验证码改密才是主流,而邮箱改密则被轻视,随便做了。这个可以根据自己业务需求设置专业程度。(手机号验证码改密,有需要的话,后面也会出)。考虑到以上三点基本就可以做出一个可用性和安全性强的邮箱改密功能。
ps:做这个模块时候,经理曾说,你这个链接时谁点都能改吗,那不是很危险了。众所周知,产品经理是一种奇特的生物,他要求我在链接上加上身份验证,同学们,修改密码链接加上身份验证就意味着需要登录操作,用户密码都忘了怎么个登录法?最后在我据理力争下,经理放弃了他的想法和要求!
好了进入正题:
一、准备工作:
这个业务可以是登录也的忘记密码进入,也可以是个人中心的修改密码进入,可以根据自己需求加入对邮箱的验证,这个自己拿捏;
二、发送链接:
我们先参考一个其他公司的修改链接,做出分析:
无非就是一个固定链接后面加上一个或多个“随机”参数,固定地址指向跳转的页面,参数负责确定安全校验和提交后的身份确定。
于是我就大胆地开始了随机参数的准备,采用生成uuid作为随机参数,以该随机参数作为key,以用户信息和安全验证信息作为value,存入redis;代码如下:
//业务前缀,可以自己定义,我这里是提前定义的常量,可替换String key = KEY_RESET_PWD_REDIS;//对邮箱进行加密,作为拼接的key,保证用一个邮箱只存储一份信息String code = MD5Utils.md5(keyChecker);//uuid作为随参数,保证链接的唯一性,同时确保了多个链接仅最后一个有效,也可采用其他策略String checkCode = UUID.randomUUID().toString(true);//构建value的值HashMap<String, String> map = new HashMap<>();//用户id,用于指向修改用户map.put("id",studentId.toString());//随机验证码,保证链接的唯一性map.put("checkCode",checkCode);//邮箱也存储上去,可多重验证map.put("email",keyChecker);//字段限制链接只能访问一次//map.put(KEY_LINK_VISIT,LINK_CANUSE_TRUE);map.put("visit","0");//存入redis,设置过期时间redisTemplate.opsForHash().putAll(key+code,map);redisTemplate.expire(key+code,REDIS_LINK_TTL,TimeUnit.MINUTES);
上面为核心代码,下面我将发送链接业务全部代码贴下:
public Result<?> sendLinkWithEmail(String keyChecker) {//获取当前登陆用户idLong studentId = UserUtil.getUserDetails().getUserAuths().getUserId();//通过用户id去查询用户邮箱UserAuths userAuths = userAuthsService.getOne(new LambdaQueryWrapper<UserAuths>().eq(UserAuths::getUserId, studentId).eq(UserAuths::getIdentityType, IDENTITYTYPE_EMAIL));//验证keyChecker是否是用户绑定的邮箱if (Objects.isNull(userAuths) || !userAuths.getIdentifier().equals(keyChecker)){return Result.failed("邮箱非绑定邮箱");}/*准备发送前,验证用户请求频率*/if (!checkedRequestFrequency(keyChecker)){return Result.failed("请求过于频繁");}String key = KEY_RESET_PWD_REDIS;//在链接中加入随机uuid作为验证,只保证最后一次链接有效String code = MD5Utils.md5(keyChecker);String checkCode = UUID.randomUUID().toString(true);HashMap<String, String> map = new HashMap<>();map.put("id",studentId.toString());map.put("checkCode",checkCode);map.put("email",keyChecker);//字段限制链接只能访问一次map.put(KEY_LINK_VISIT,LINK_CANUSE_TRUE);redisTemplate.opsForHash().putAll(key+code,map);redisTemplate.expire(key+code,REDIS_LINK_TTL,TimeUnit.MINUTES);String link = RESET_PWD_LINK_PREFIX+"?code="+code+"&checkCode="+checkCode;//调用提前写好的发送邮件的工具类,将链接发送到用户邮箱内//因发送邮件不是核心业务,这里不再赘述,不会的可以参考其他博主资料,也可留言我会再出教程。 SendEmailUtil.sendHtmlMail(keyChecker,RESET_PWD_SUBJECT,SEND_LINK_RESET_PWD(link),EMAIL_FROM);return Result.succeed("email","修改链接已发送至邮箱");}
(需要邮件发送教程的请留言,或关注后续文章,比较简单,可能会出。)
三、点击链接(不做234条的可以跳过)
要保证链接只能点击一次,10分钟内有效等功能,需要在用户点击链接跳转的进入页面,页面尚未渲染前,发送一个验证请求,参数就是我们链接上的连个参数,验证通过,成功跳转,验证不通过则直接跳转到错误页面。
public String getInfoAndCheckLink(String code,String checkCode){String key = KEY_RESET_PWD_REDIS;//获取到上一步存储的信息Map entries = redisTemplate.opsForHash().entries(key + code);//验证存储的visit是否已访问,如果访问过一次则验证不通过if (entries.get(KEY_LINK_VISIT).toString().equals(LINK_CANUSE_FALSE)){return null;}//是第一次访问,则修改该值为 已访问 状态redisTemplate.opsForHash().put(key+code,KEY_LINK_VISIT,LINK_CANUSE_FALSE);//验证uuid随机字符串,保证链接是最后一次发送的链接(多次点击发送的话)if (checkCode.equals(entries.get("checkCode").toString())){return entries.get("email").toString();}return null;}
四、最终修改密码
所有验证都通过后,用户在前台提交新密码,进行修改操作。
public Result<?> resetPassWordByEmail(String password, String code, String checkCode) {String key = KEY_RESET_PWD_REDIS;//同样取出保存在redis的用户信息Map entries = redisTemplate.opsForHash().entries(key + code);//验证链接时间是否在有效期内if (entries.size()==0 || !entries.get("checkCode").equals(checkCode)){return Result.failed("链接已失效");}//新密码加密策略,根据自己业务需要决定// 重新生成盐值String salt = UUID.randomUUID().toString(true);// 加密password = SHA1Utils.sha1(password, salt);//修改密码boolean isSuccess = userAuthsService.update(new LambdaUpdateWrapper<UserAuths>().set(UserAuths::getPassword, password).set(UserAuths::getSalt,salt).eq(UserAuths::getUserId, entries.get("id")));if (isSuccess){redisTemplate.delete(key + code);return Result.succeed("修改成功");}return Result.failed("修改失败,请重试");}
至此,邮箱改密全部业务逻辑和业务代码搞定,你学会了吗?
炫酷又实用的发送邮箱链接修改密码相关推荐
- 企业邮箱怎么修改密码?企业邮箱安全中心,企业邮箱账号密码安全
使用TOM企业邮箱的会比较多,国内老牌的邮箱了,无限容量,供企业妥善保存重要资料,在邮件收发方面,管理员和员工密码安全管理,管理员密码只有服务商拿到企业授权才可修改,员工密码只有企业管理员可修改. 企 ...
- 办公邮箱如何修改密码?这些小知识你知道吗?
当我们拥有一份新的工作时,各种新鲜的事物也会随之而来:新的环境,新的信息数据,新的办公邮箱-当办公邮箱分配给我们时,HR会告诉我们:"修改你的邮箱密码."但是如果不熟悉的办公邮箱, ...
- 邮箱验证修改密码,通过邮箱找回密码
使用邮箱验证修改密码,在这里我是使用163免费邮进行测试 前台代码 1 <input type="text" name="Mail" id="M ...
- vscode必备插件,美化、炫酷、实用-留着防丢
1.Bracket Pair Colorizer: 给匹配的括号着色 2.Chinese (Simplified) Language Pack for Visual Studio Code: 适用于 ...
- 基于TP3.2的发送邮箱做找回密码
技术QQ交流群:294088839 //找回密码 public function reset(){ if(IS_POST){ $username=I( ...
- 分享一个可以批量换绑百度账号绑定邮箱+批量修改密码的软件
之前做过贴吧,经常需要入手大量的百度号,因此给账号换绑邮箱(防止扫号).修改密码就成了一件繁重的工作.也曾经因为偷懒,购买之后没有及时换绑邮箱,很快就被不良卖家把号扫回去了,损失惨重! 所以在网上各种 ...
- 10 个超炫酷后台控制面板(附 GitHub下载链接)
点击上方"朱小厮的博客",选择"设为星标" 做积极的人,而不是积极废人 Web 开发中几乎的平台都需要一个后台管理,但是从零开发一套后台控制面板并不容易,幸运的 ...
- outlook2016邮箱怎么修改密码
打开网页版的邮箱 右上角有设置按钮 点击设置 选择"我的账户" 向下拉选择 "更改您的密码"
- 炫酷实用的jQuery插件 涵盖菜单、按钮、图片
新的一周开始了,今天我们要为大家分享一些全新的jQuery插件和HTML5/CSS3应用,这些jQuery插件不仅非常炫酷,而且还挺实用,这次的分享包含jQuery菜单.CSS3按钮已经多种图片特效, ...
- html5怎么把图片做成按钮,炫酷实用的jQuery插件 涵盖菜单、按钮、图片 | HTML5资源教程...
新的一周开始了,今天我们要为大家分享一些全新的 1.CSS3书本翻页动画 书本翻页效果逼真 今天我们要分享一款炫酷而且实用的CSS3动画效果,它是模拟书本翻页的动画特效.当鼠标滑过书本右上角时,书本即 ...
最新文章
- ffmpeg函数调用失败--在编译自己的ffmpeg函数的时候显示ffmpeg函数undefined reference to `av_log_set_level(int)‘
- python首页展示业务逻辑_每日一程-4. PyQt5-实现显示和业务逻辑分离
- Linux select TCP并发服务器与客户端编程
- 安装Cornerstone3.1注意点
- 咱中国女人太贪钱? 其实真不怨她们
- Delphi 发送邮件 通过Office Outlook
- [luogu2054 AHOI2005] 洗牌 (数论)
- vscode多开远程链接矩池云服务器
- Linux在文件中查找the字样,Linux文件查找
- python_迭代器、生成器
- 服务器运行环境一般填什么,运行环境是什么意思
- java 生成水印_Java实现图片生成水印
- 浅谈音乐与计算机,浅析电脑音乐在音乐教育中的应用
- Qgis教程11:三维效果
- formality软件使用教程
- 浪漫主义和革命英雄主义的回忆
- 微服务分布式架构中,如何实现日志链路跟踪?
- html 布局缩放比例,css布局之百分比宽度布局的使用
- 论文阅读笔记:Recent Advances and Challenges in Task-oriented Dialog Systems
- day02:云计算解决方案学习笔记
热门文章
- 分享一些java学习网站网址
- adb和夜神模拟器安装
- unserialize():Error at offset 0 of 96 bytes是什么意思
- java 定时关机_win7电脑怎么设置定时关机_win7电脑设置定时关机的详细教程-win7之家...
- JavaScript学习笔记——基础部分
- 斐讯w2换表盘_【斐讯W2智能手表使用感受】表盘|屏幕|GPS|电量_摘要频道_什么值得买...
- 普通高等学校毕业生登记表 计算机水平,普通高等学校全日制毕业生登记表自我鉴定怎么写...
- 云知声发布多模态AI芯片战略,同步曝光三款在研芯片...
- 20155218 《Java程序设计》实验二(Java面向对象程序设计)实验报告
- 48个快速操作office技巧