顾老师新作“带着ChatGPT玩转软件开发”将于今年底明年初出版
尽信书不如无书——《孟子·尽心下》
第四章找回密码
4.1 ChatGPT生成找回密码的代码
需求
019买家通过手机短信找回密码。
•功能描述:买家输入手机号,系统发送验证码短信,验证通过后允许重置密码。
•输入
Ø手机号。
Ø验证码。
Ø新密码(遵循注册密码规则)。
Ø新密码确认。
•输出
Ø验证码发送状态。
Ø密码重置成功或失败提示。
•处理逻辑
Ø校验手机号是否注册。
Ø生成验证码并发送短信。
Ø验证用户输入验证码是否正确及有效期内。
Ø校验新密码复杂度。
Ø更新密码至数据库。
•异常处理
Ø手机号未注册,提示用户。
Ø验证码错误或过期,提示重新获取。
Ø新密码与新密码确认不一致,提示用户。
Ø密码不符合规则,提示修改。
020买家通过Email地址找回密码
•功能描述:买家输入Email,系统发送重置密码链接或验证码邮件,验证后允许重置密码。
•输入
ØEmail地址。
Ø邮件验证码或链接激活。
Ø新密码。
Ø新密码确认。
•输出
Ø邮件发送状态。
Ø重置密码结果。
•处理逻辑
Ø校验Email是否注册。
Ø发送带验证码或重置链接的邮件。
Ø验证邮件验证码或链接有效性。
Ø新密码与新密码确认不一致,提示用户。
Ø校验密码规则,更新密码。
•异常处理
ØEmail未注册,提示用户。
Ø邮件验证码错误或超时,提示用户重新发送。
Ø新密码与确认密码不一致,提示用户。
Ø密码不符合规则,提示用户进行修改。
注解。
•本版本不考虑验证码的有效期。
4.1.1 ChatGPT生成前端代码
1.申请找回密码前端代码
提示词
基于登录前端,加入超链“通过手机短信或Email找回密码”链接,要求美观好看。
参考代码3-1 login.html
另外,请设计找回密码前端HTML页面,包括手机或邮箱输入框,【发送验证码】按钮。然后呈现新密码输入框、新密码确认输入框以及【确定】按钮。该页面与登录保证一致的风格。目前CSS文件index.css如下。
参考代码2-2 index.css
2.找回密码前端代码回复
ChatGPT回答
根据您的要求,我将为登录页面添加“通过手机短信或Email找回密码”超链接,并设计一个找回密码的前端HTML页面,确保与现有的登录页面风格一致。
1)登录页面
增加找回密码链接。在登录页面的<form>标签之后,添加两个超链接。以下是更新后的HTML代码。
代码4-1 login.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<link rel="stylesheet" href="../css/index.css">
<script src="../js/crypto-js.min.js" type="text/javascript"></script>
<script src="../js/core.js" type="text/javascript"></script>
<script src="../js/sha256.js" type="text/javascript"></script>
<script src="../js/index.js" type="text/javascript"></script>
<title>登录页面</title>
</head>
<body>
<div class="container">
<h2>登录</h2>
<form id="loginForm" name="loginForm" method="POST" action="LoginPage.jsp" onsubmit="return validateLoginForm();">
<input type="hidden" id="csrftoken" name="csrftoken" value="MdYouuYEAtGayaTikTZeH7wq1tuIoxUEQY3xMVOSOi8SVmPvaOFiuNtim0N0n8xxltN3mosCcZVNTVh6rp1FPZP8YsuNwjZmL7t5">
<div>
<label for="username">账号:</label>
<input type="text" id="username" name="username" placeholder="输入账号" autocomplete="username" required>
<div id="usernameError" class="error"></div>
</div>
<div>
<label for="password">密码:</label>
<input type="password" id="password" name="password" placeholder="输入密码" autocomplete="current-password" required>
<div id="passwordError" class="error"></div>
</div>
<button type="submit">登录</button>
</form>
<div id="loginError" class="error"></div>
<div class="links">
<a href="recover.html" class="link">通过手机短信或Email找回密码</a>
</div>
</div>
</body>
</html>注解:修改
<a href="recover.html" class="link">通过手机短信或Email找回密码</a>为
<a href="VeriCodePage.jsp" class="link">通过手机短信或Email找回密码</a>2)找回密码页面
以下是找回密码的HTML页面,包含手机或邮箱输入框、发送验证码按钮、新密码输入框、新密码确认输入框以及确定按钮,且与登录页面保持一致的风格。
代码4-2 VeriCodePage.html/RecoverPage.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<link rel="stylesheet" href="../css/index.css">
<title>找回密码</title>
</head>
<body>
<div class="container">
<h2>找回密码</h2>
<form id="recoverForm" name="recoverForm" method="POST" action="RecoverPage.jsp">
<div>
<label for="contact">手机号码或电子邮箱:</label>
<input type="text" id="contact" name="contact" placeholder="输入手机号码或邮箱" required>
<div id="contactError" class="error"></div>
</div>
<button type="button" id="sendCode">发送验证码</button>
<div>
<label for="newPassword">新密码:</label>
<input type="password" id="newPassword" name="newPassword" placeholder="输入新密码" required>
<div id="newPasswordError" class="error"></div>
</div>
<div>
<label for="confirmPassword">确认新密码:</label>
<input type="password" id="confirmPassword" name="confirmPassword" placeholder="确认新密码" required>
<div id="confirmPasswordError" class="error"></div>
</div>
<button type="submit">确定</button>
</form>
<div id="recoverError" class="error"></div>
</div>
</body>
</html>注解:将上面代码分解为两个代码:VeriCodePage.jsp和RecoverPage.jsp。
代码4-3 VeriCodePage.jsp
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<link rel="stylesheet" href="../css/index.css">
<script src="../js/index.js" type="text/javascript"></script>
<title>输入手机号码或电子邮箱入</title>
</head>
<body>
<div class="container">
<h2>输入手机号码或电子邮箱入</h2>
<form id=“VeriCodeError” name="VeriCode" method="POST" action="VeriCodePage.jsp" onsubmit="return validateVeriCodeForm();">
<input type="hidden" id="csrftoken" name="csrftoken" value="<%=csrftoken%>">
<div>
<label for="contact">手机号码或电子邮箱:</label>
<input type="text" id="contact" name="contact" placeholder="输入手机号码或邮箱" required>
<div id="contactError" class="error"></div>
</div>
<button type="submit" id="sendCode">发送验证码</button>
</form>
</form>
<div id=“VeriCodeError” class="error"></div>
</div>
</body>
</html>代码4-4 RecoverPage.jsp
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<link rel="stylesheet" href="../css/index.css">
<script src="../js/index.js" type="text/javascript"></script>
<title>找回密码</title>
</head>
<body>
<div class="container">
<h2>找回密码</h2>
<form id="recover" name="recover" method="POST" action="RecoverPage.jsp" onsubmit="return validateRecoverForm();">
<input type="hidden" id="csrftoken" name="csrftoken" value="<%=csrftoken%>">
<div>
<label for="identifyingCode">验证码:</label>
<input type="text" id="identifyingCode" name="identifyingCode" placeholder="输入验证码" required>
<div id="identifyingCodeError" class="error"></div>
</div>
<div>
<label for="newPassword">新密码:</label>
<input type="password" id="newPassword" name="newPassword" placeholder="输入新密码" required>
<div id="newPasswordError" class="error"></div>
</div>
<div>
<label for="confirmPassword">确认新密码:</label>
<input type="password" id="confirmPassword" name="confirmPassword" placeholder="确认新密码" required>
<div id="confirmPasswordError" class="error"></div>
</div>
<button type="submit">确定</button>
</form>
<div id="recoverError" class="error"></div>
</div>
</body>
</html>3)CSS样式
在index.css中,您已经定义了样式规则,这些样式将自动应用于新添加的元素。确保a.link的样式良好,可以添加以下样式来美化链接。
代码4-5 index.css
.links{
text-align:center;
margin-top:15px;
}
.link{
color:#4CAF50;/*与按钮颜色一致 */
text-decoration:none;
font-size:14px;
}
.link:hover{
text-decoration:underline;/*悬停时添加下划线 */
}总结
以上代码为登录页面添加了找回密码链接,并设计了一个找回密码的页面。所有页面都保持一致的风格,确保用户体验良好。您可以根据需要调整链接的href属性,以指向相应的处理页面。
4)更新JavaScript代码
在index.js中建立如下代码。
代码4-6 index.js
…
function checkRecover(identifyingCode,newPassword,confirmPassword){
let isValid=true;
clearErrorMessages("recover");
const identifyingCodePattern=/^\d{6}$/;
const newPasswordPattern=/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[\W_]).{5,30}$/;
isValid=CheckField(identifyingCodePattern,identifyingCode,'identifyingCodeError','账号必须是5-20位的字母或数字',isValid);
isValid=CheckField(newPasswordPattern,newPassword,'newPasswordError','密码必须包含大小写字母、数字和特殊字符,长度在5-30之间');
if(newPassword!==confirmPassword){
document.getElementById('confirmPasswordError').innerText='密码确认不一致';
isValid=false;
}
return hash256(isValid,document.forms["recover"]["password"],'注册成功!');
}
//验证注册页面输入数据
function validateRegisterForm(){
const username=document.getElementById('username')? document.getElementById('username').value:'';
const password=document.getElementById('password')? document.getElementById('password').value:'';
const confirmPassword=document.getElementById('confirmPassword')? document.getElementById('confirmPassword').value:'';
const phone=document.getElementById('phone')? document.getElementById('phone').value:'';
const email=document.getElementById('email')? document.getElementById('email').value:'';
return checkRegister(username,password,confirmPassword,phone,email);
}
//验证登录页面输入数据
function validateLoginForm(){
const username=document.getElementById('username')? document.getElementById('username').value:'';
const password=document.getElementById('password')? document.getElementById('password').value:'';
return checkLogin(username,password);
}
//验证输入获取验证码页面输入数据
function validateVeriCodeForm(){
const contact=document.getElementById('contact')? document.getElementById('contact').value:'';
return checkVeriCode(contact);
//验证重置密码页面输入数据
function validateRecoverForm(){
const identifyingCode=document.getElementById('identifyingCode')? document.getElementById('identifyingCode').value:'';
const newPassword=document.getElementById('newPassword')? document.getElementById('newPassword').value:'';
const confirmPassword=document.getElementById('confirmPassword')? document.getElementById('confirmPassword').value:'';
return checkRecover(identifyingCode,newPassword,confirmPassword);
}
…
//用于清空所有错误信息
function clearErrorMessages(sign){
if(sign==="reg"){
document.getElementById('usernameError').innerText='';
document.getElementById('passwordError').innerText='';
document.getElementById('confirmPasswordError').innerText='';
document.getElementById('phoneError').innerText='';
document.getElementById('emailError').innerText='';
}else if(sign==="log"){
document.getElementById('usernameError').innerText='';
document.getElementById('passwordError').innerText='';
}else if(sign==="contact"){
document.getElementById('contactError').innerText='';
}else if(sign==="recover"){
document.getElementById('identifyingCodeError').innerText='';
document.getElementById('newPasswordError').innerText='';
document.getElementById('confirmPasswordError').innerText='';
}else{
console.log("sig for clearErrorMessages is error");
}
}
//验证获取验证码时输入的信息(手机或Email)
function checkVeriCode(contact){
let isValid=true;
clearErrorMessages("contact");
const phonePattern=/^1[3-9]\d{9}$/;
const emailPattern=/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
isValid=CheckField(phonePattern,contact,'contactError','请输入有效的中国手机号或Email',isValid);
if(!isValid){
isValid=CheckField(emailPattern,contact,'contactError','请输入有效的中国手机号或Email',isValid);
}
return isValid;
}注解:将正则表达式合并为全局变量,并改造相关代码,最终实现如下功能。
代码4-7 index.js
const passwordPattern=/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[\W_]).{5,30}$/;
const phonePattern=/^1[3-9]\d{9}$/;
const emailPattern=/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
const identifyingCodePattern=/^\d{6}$/;
const newPasswordPattern=/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[\W_]).{5,30}$/;
//检查注册、登录以及输入手机或Email的表单值是否符合正则表达式Pattern。如果符合,isValid返回true;否则返回false,并在field中显示message信息。
function CheckField(Pattern,value,field,message,isValid){
if(!Pattern.test(value)){
showError(field,message);
isValid=false;//修改 isValid
}
return isValid;//返回 isValid
}
//检查输入手机或Email的表单值是否符合正则表达式Pattern。如果符合,isValid返回true;否则返回false。
function CheckFieldByVeriCode(Pattern,value,isValid){
if(!Pattern.test(value)){
isValid=false;//修改 isValid
}
return isValid;//返回 isValid
}
//在isValid为true的情况下,对passwordField中的密码进行加密,并将加密后的密码存passwordField中。
function hash256(isValid,passwordField){
if(isValid){
let password=passwordField.value;//从密码字段获取值
let hashedPassword=CryptoJS.SHA256(password).toString(CryptoJS.enc.Base64);
passwordField.value=hashedPassword;
}
return isValid;
}
//检查注册表单中的账号、密码、密码确认、手机和Email的有效性。
function checkRegister(username,password,confirmPassword,phone,email){
let isValid=true;
clearErrorMessages("reg");
isValid=CheckField(usernamePattern,username,'usernameError','账号必须是5-20位的字母或数字',isValid);
isValid=CheckField(passwordPattern,password,'passwordError','密码必须包含大小写字母、数字和特殊字符,长度在5-30之间',isValid);
isValid=CheckField(phonePattern,phone,'phoneError','请输入有效的中国手机号',isValid);
isValid=CheckField(emailPattern,email,'emailError','请输入有效的Email地址',isValid);
if(password!==confirmPassword){
document.getElementById('confirmPasswordError').innerText='密码确认不一致';
isValid=false;
}
return hash256(isValid,document.forms["myForm"]["password"]);
}
//检查登录表单中的账号和密码。
function checkLogin(username,password){
let isValid=true;
clearErrorMessages("log");
isValid=CheckField(usernamePattern,username,'usernameError','账号必须是5-20位的字母或数字',isValid);
isValid=CheckField(passwordPattern,password,'passwordError','密码必须包含大小写字母、数字和特殊字符,长度在5-30之间',isValid);
return hash256(isValid,document.forms["loginForm"]["password"]);
}
//检查发送验证码表单中的手机或Email。
function checkVeriCode(contact){
let isValid=true;
clearErrorMessages("contact");
phone=CheckFieldByVeriCode(phonePattern,contact,isValid);
email=CheckFieldByVeriCode(emailPattern,contact,isValid);
if(!(phone)&&!(email)){
showError("contactError","请输入有效的中国手机号或Email");
return false;
}else{
return true;
}
}
//检查重置密码表单中的验证码、新密码和新密码确认。
function checkRecover(identifyingCode,newPassword,confirmPassword){
let isValid=true;
clearErrorMessages("recover");
isValid=CheckField(identifyingCodePattern,identifyingCode,'identifyingCodeError','验证码必须是6位数字',isValid);
isValid=CheckField(passwordPattern,newPassword,'newPasswordError','密码必须包含大小写字母、数字和特殊字符,长度在5-30之间',isValid);
if(newPassword!==confirmPassword){
document.getElementById('confirmPasswordError').innerText='密码确认不一致!';
isValid=false;
}
return hash256(isValid,document.forms["recover"]["newPassword"]);
}
//验证注册表单中的数据。
function validateRegisterForm(){
const username=document.getElementById('username')? document.getElementById('username').value:'';
const password=document.getElementById('password')? document.getElementById('password').value:'';
const confirmPassword=document.getElementById('confirmPassword')? document.getElementById('confirmPassword').value:'';
const phone=document.getElementById('phone')? document.getElementById('phone').value:'';
const email=document.getElementById('email')? document.getElementById('email').value:'';
return checkRegister(username,password,confirmPassword,phone,email);
}
//验证登录表单中的数据。
function validateLoginForm(){
const username=document.getElementById('username')? document.getElementById('username').value:'';
const password=document.getElementById('password')? document.getElementById('password').value:'';
return checkLogin(username,password);
}
//验证输入手机或Email表单中的数据。
function validateVeriCodeForm(){
const contact=document.getElementById('contact')? document.getElementById('contact').value:'';
return checkVeriCode(contact);
}
//验证重置密码表单中的数据。
function validateRecoverForm(){
const identifyingCode=document.getElementById('identifyingCode')? document.getElementById('identifyingCode').value:'';
const newPassword=document.getElementById('newPassword')? document.getElementById('newPassword').value:'';
const confirmPassword=document.getElementById('confirmPassword')? document.getElementById('confirmPassword').value:'';
return checkRecover(identifyingCode,newPassword,confirmPassword);
}
//
//在指定的elementId中显示错误信息message
function showError(elementId,message){
document.getElementById(elementId).innerText=message;
}
/*清空不同表单中的所有错误信息。
sign==="reg":清空注册表单的错误信息。
sign==="log":清空登录表单的错误信息。
sign==="contact":清空输入手机或Email表单的错误信息。
sign==="recover":清空重置密码表单的错误信息。*/
function clearErrorMessages(sign){
if(sign==="reg"){
document.getElementById('usernameError').innerText='';
document.getElementById('passwordError').innerText='';
document.getElementById('confirmPasswordError').innerText='';
document.getElementById('phoneError').innerText='';
document.getElementById('emailError').innerText='';
}else if(sign==="log"){
document.getElementById('usernameError').innerText='';
document.getElementById('passwordError').innerText='';
}else if(sign==="contact"){
document.getElementById('contactError').innerText='';
}else if(sign==="recover"){
document.getElementById('identifyingCodeError').innerText='';
document.getElementById('newPasswordError').innerText='';
document.getElementById('confirmPasswordError').innerText='';
}else{
console.log("sign for clearErrorMessages is error");
}
}输入手机号码或电子邮箱的界面如图4-1所示,重置新密码的界面如图4-2所示。

图4-1 输入手机号码或电子邮箱

图4-2 重置密码
顾翔凡言:人工智能未来的发展瓶颈在于对知识的更新。唯一不变的是变化,知识发生了变化,人工智能软件能否及时跟进变化,可能阻碍人工智能的使用。