- 浏览: 18499 次
文章分类
最新评论
"忘记密码"功能过程及其实现细节
对于忘记密码功能,一般都是通过2种方式找回:一种是通过预留电话号码发送验证码找回,另一个是通过设定邮箱找回。对于具体的找回流程,参见:http://www.yixieshi.com/ucd/9207.html。
这里结合目前做的项目,详细的说明一下密码找回的过程。这里用的是邮箱找回。根据一般的忘记密码的流程来说明。我采用的流程是:
- 流程
【登录】 --> 【点击忘记密码】 --> 【输入个人邮箱和验证码】 --> 【系统发送邮箱验证】 --> 【用户在限定时间内登录邮箱,点击链接,进入重置密码页面】 --> 【重置密码完毕,点击进入登录界面】。
- 登录页面
先给出我做的登录界面,其中包含"忘记密码"功能
一般登录界面都有“忘记密码”选项,这里不多说。
- "忘记密码"页面
点击"忘记密码"选项后,这时,页面会跳向一个新页面,即“忘记密码”页面。首先给出"忘记密码"按钮对应的跳转代码片段:
<a href = "" style = "padding:0px 0px 0px 18px" onclick = "window.open('forgetPassword.jsp')">忘记密码?</a> <!-- 打开新窗口 -->
在点击后,跳到新页面:
这里的界面设计是模仿的网页163邮箱的忘记密码,给出链接:http://reg.163.com/getpasswd/RetakePassword.jsp?from=mail163。
该界面中,有几个关键点:一个是验证码的生成,一个是邮箱发送的功能,还一个就是点击确定后的反馈界面。主要包含这3个方面的内容,这3点以下将会详细介绍。
1、验证码生成功能
关键是jsp和servlet的交互。上面的链接中,主要使用了作者贴出的serlvet代码片段,即随机生成四位0~9的数字,然后生成一些干扰线,最后将生成的图片发送到jsp页面。
下面给出部分后台servlet代码片段:
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("生成验证码"); // 清空缓冲区 response.reset(); // 注意这里的MIME类型 response.setContentType("image/png"); // 设置页面不缓存 response.setHeader("Pragma", "No-cache"); response.setHeader("Cache-Control", "no-cache"); response.setDateHeader("Expires", 0); // 创建一个图像,验证码显示的图片大小 BufferedImage image = new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB); // 获取图形上下文 Graphics g = image.getGraphics(); // 设置背景 g.setColor(getRandColor(200,250)); g.fillRect(0, 0, width, height); for (int i = 0; i < 4; i++) { drawCode(g, i); } //添加干扰线 drawNoise(g, 12); // 绘制边框 //g.setColor(Color.gray); //g.drawRect(0, 0, width - 1, height - 1); // 将验证码内容保存进session中,用于验证用户输入是否正确时使用 HttpSession session = request.getSession(true); session.removeAttribute("rand"); session.setAttribute("rand", codeNumbers); // 重设字符串 codeNumbers = ""; // 利用ImageIO类的write方法对图像进行编码 ServletOutputStream sos = response.getOutputStream(); ImageIO.write(image, "PNG", sos); sos.close(); }从上面的代码可以看出,基本步骤是:生成4位0~9的随机数,然后设置数字的大小,颜色等;接着设置干扰线,根数,颜色等,然后创建出一个BufferedImage对象,就是验证码的背景图片大小、颜色等;最后将生成好的验证码传送到前台。
注意:这里要将验证码(即图片)传送到前台的jsp界面,需要三个方面的设置:
①设置传送到前台的内容类型,可以是text/html,也可以是image/png。由于这里传送的是验证码,所以设置为后一种。
// 注意这里的MIME类型 response.setContentType("image/png");②在servlet中,还要考虑用什么方法对图像进行编码。
// 利用ImageIO类的write方法对图像进行编码 ServletOutputStream sos = response.getOutputStream(); ImageIO.write(image, "PNG", sos); sos.close();
③在jsp页面部分:
<img id="code" src="codeMakerServlet" title="看不清点击刷新验证码" style="cursor : pointer;" onclick="return refreshcode()"/>对应的js函数:
function refreshcode(){ document.getElementById("code").src="codeMakerServlet?a="+Math.random()+100; return true; }
其实就是每次点击,都运行一次对应的servlet,servlet在运行后,都会发送一个验证码图片到前台,也就是所谓的"刷新"。
2、填写内容检查
这里用到了一个js库:jquery.validate.min.js。这个只能判断输入的内容是否符合规则。
由于要输入用户的登录邮箱,规则正确只是第一步,还要查看输入的邮箱在数据库中是否存在,如果不存在,是不能允许发送密码重置邮件的。所以对邮箱正确性的检查,需要调用一次$.getJSON();进行验证;
对于验证码的验证,由于在验证码生成的servlet中,已经设置了
// 将验证码内容保存进session中,用于验证用户输入是否正确时使用 HttpSession session = request.getSession(true); session.removeAttribute("rand"); session.setAttribute("rand", codeNumbers);所以这时候还要进行一次后台通讯,查看是否验证码输入正确。但是,有个问题我还没来得急了解:这个验证码的作用是什么?这个也是我在后期需要进行追加的内容。
3、邮件发送功能
参考文章:http://www.iteye.com/topic/352753。
需要用到的jar包:mail.jar。
需要用到的jar包:mail.jar。
在上面的参考文章中,作者详细的给出了3段主要的代码,这里也不多说了,说实话,我还真没怎么看其内部的实现原理,只是把别人写好的代码,直接调用接口使用。
注意:作者在最后给出了几个经验,其中一个就是不能用新申请的邮箱,否则无法发送成功,我试了下,确实是这样,但是这个是不是所有的邮箱都是这样,我也没有试过。
另外,需要特别提出的是,发送内容的方式分为两种,一个是按照文本发送,一个是按照html发送。
先给出示例代码:
在代码的最后,有两种发送方式,一般都会采用第二种方式,如果要给对方邮箱发送一些超链接等,就需要用html格式发送,这样,<a href = "****"></a>就能自动识别成超链接。下图是用文本方式发送的上面代码中的内容:
从上图中,我们可以看出,对应的<a>标签是当做文本处理的,下图是用html格式发送的内容:
两种效果还是不同的,由于发送验证邮件需要用到链接,所以项目中采用html格式。
public static void main(String[] args){ //这个类主要是设置邮件 MailSenderInfo mailInfo = new MailSenderInfo(); mailInfo.setMailServerHost("smtp.163.com"); mailInfo.setMailServerPort("25"); mailInfo.setValidate(true); mailInfo.setUserName("tianzhihensu@163.com"); mailInfo.setPassword("********");//您的邮箱密码 mailInfo.setFromAddress("tianzhihensu@163.com"); mailInfo.setToAddress("sacevmproject@163.com"); mailInfo.setSubject("设置邮箱标题,sfsfdfdff"); mailInfo.setContent("<a href = \"http://write.blog.csdn.net/postlist\">http://write.blog.csdn.net/postlist</a>"); //这个类主要来发送邮件 SimpleMailSender sms = new SimpleMailSender(); sms.sendTextMail(mailInfo);//发送文体格式 SimpleMailSender.sendHtmlMail(mailInfo);//发送html格式 }
在代码的最后,有两种发送方式,一般都会采用第二种方式,如果要给对方邮箱发送一些超链接等,就需要用html格式发送,这样,<a href = "****"></a>就能自动识别成超链接。下图是用文本方式发送的上面代码中的内容:
从上图中,我们可以看出,对应的<a>标签是当做文本处理的,下图是用html格式发送的内容:
两种效果还是不同的,由于发送验证邮件需要用到链接,所以项目中采用html格式。
4、邮件中的链接
对于这个链接,还有一个重要的部分,那就是链接要链向哪里?需要哪些参数?这个链接怎么保证时效性(每个密码找回链接都是有时效性的)?咱们首先看一下成熟的例子。学信网的密码找回链接如下:
现在能够确定的一点是:链接是指向某个servlet的,但是对应的参数就是一串没有规律的数字。这个key中隐含着什么样的信息?我认为包括两个部分:
①一部分是用户的用户名等可以辨识用户的内容,否则在用户点击链接后无法得知用户是谁;
②还一部分是邮件发送时的时间,因为只有参数中含有时间信息,才能使得该链接具有时效性(具体时效性可以是多
少,指向 的后台servlet中需要设定的部分)。
知道了以上的内容,还剩下最后一个问题,这个key值的乱码是怎么得来的?首先想到的就是加密。对的!就是加密得来的。否则以明文传送,不太安全。
至于这个加密的部分,就放在下面去讲。这里先来大体说一下加密:输入就是一串数,出来的就是一堆乱码,而且,这里的加密必须要是可逆的,否则点击链接后,不能还原成明文还是不顶用啊。既然知道了输入就是一个字符串,那么可以把时间和用户名串起来,这样就形成了一个字符串,然后在后台再解析出来。
5、点击确定后的信息回馈
首先来看一下【学信网】是怎么回馈的:
用户点击"确定"按钮,当邮件发送成功后,会显示"邮件发送成功",然后下面跟出一些提示性的语言blablabla....但是,若由于某些原因,导致邮件发送失败时,也要给出相应的提醒。
模仿上述反馈界面,我用了如下界面:
内部实现原理如下:
①在用户点击"确认"按钮后,后台首先获得当前的系统时间(按照ms计算),然后从前台得到了用户输入的登录邮箱,在两者之间加入一个"@"符连接起来为一个字符串(目的:便于在转变为明文的时候将两者区分开来,因为邮箱的第一个字母是不允许使用"@"符的,所以加入该符号不会引起歧义)。然后将该字符串加密成一串密文,这就是key值。前面再配上某个servlet的固定连接,就是完成了link链接;
②调用邮箱发送接口,实现邮箱转发。本系统中使用的邮箱接口如下:
/** * 发送信息到用户的登录邮箱 * * @param userEmail * @return */ public Boolean sendMail(String userEmail) { Boolean flag = false; try { // 获取当前系统时间 Date now = new Date(); String currentTime = "" + now.getTime(); String urlString = "http://localhost:8080/EVM/forgetPasswordAction?method=resetPassword&key="; CodeEncryption cEncryption = new CodeEncryption(); String encryptedCode = cEncryption.encryptCode(currentTime + "@" + userEmail); String link = urlString + encryptedCode; String adminMailAddress = "admin@126.com"; String contents = this.setContents(userEmail, link, adminMailAddress); //邮箱配置 String serverHost = "smtp.163.com"; String serverPort = "25"; Boolean isValidate = true; String userName = "blablalbablabla@163.com"; String password = "blablabla"; String toMailAddress = userEmail; String subtitle = "科研数据管理平台注册账号密码找回 "; this.setMail(serverHost, serverPort, isValidate, userName, password, toMailAddress, subtitle, contents); flag = true; } catch (Exception e) { e.printStackTrace(); } return flag; }
上面的函数会返回一个布尔值,如果邮箱发送成功,则返回true,否则返回false。该函数是在service层,得到的布尔值将会返回到调用该函数的servlet层。这里面有个setMail函数,里面有很多参数,下面也给出对应的setMail函数:
/** * 邮箱发送前的配置 * @param serverHost * @param serverPort * @param isValidate * @param userName * @param password * @param toMailAddress * @param subtitle * @param contents */ public void setMail(String serverHost, String serverPort, Boolean isValidate, String userName, String password, String toMailAddress, String subtitle, String contents) { // 这个类主要是设置邮件 MailSenderInfo mailInfo = new MailSenderInfo(); mailInfo.setMailServerHost(serverHost); mailInfo.setMailServerPort(serverPort); mailInfo.setValidate(isValidate); mailInfo.setUserName(userName); mailInfo.setPassword(password);// 您的邮箱密码 mailInfo.setFromAddress(userName); mailInfo.setToAddress(toMailAddress); mailInfo.setSubject(subtitle); mailInfo.setContent(contents); // 这个类主要来发送邮件 SimpleMailSender sms = new SimpleMailSender(); // sms.sendTextMail(mailInfo);// 发送文体格式 SimpleMailSender.sendHtmlMail(mailInfo);// 发送html格式 }
若邮件发送失败,servlet会接收到false的信息。先来看一下对应的servlet层是怎么做的:
/** * 密码忘记,发送信息到邮箱 * @param request * @param response */ public void passwordForgotten(HttpServletRequest request, HttpServletResponse response) { String userEmail = request.getParameter("userEmailInput"); ForgetPasswordService fPasswordService = new ForgetPasswordService(); Boolean flag = fPasswordService.sendMail(userEmail); try { if (flag) { RequestDispatcher rDispatcher = request.getRequestDispatcher("fpEmailSended.jsp"); String str1 = userEmail.substring(0, 3); String str2 = userEmail.substring(userEmail.indexOf("@")); String str3 = str1 + "***" + str2; request.setAttribute("userEmail", str3); request.setAttribute("flag", "true"); rDispatcher.forward(request, response); } else { RequestDispatcher rDispatcher = request.getRequestDispatcher("fpEmailSended.jsp"); String str1 = userEmail.substring(0, 3); String str2 = userEmail.substring(userEmail.indexOf("@")); String str3 = str1 + "***" + str2; request.setAttribute("userEmail", str3); request.setAttribute("flag", false); rDispatcher.forward(request, response); } } catch (Exception e) { e.printStackTrace(); } }
这里,flag出现了2个分支:在正确的情况下,给出"邮箱发送成功"的反馈界面,并由 RequestDispatcher指向一个新的jsp页面,即点击确认的那个页面和信息回馈的页面不是同一个页面。
若flag为true,则走第一个分支,结果如下:
flag为false,则走第二个分支,结果如下:
下面我们来看一下发送成功的情况,这样在邮箱285***@qq.com中就出现了一封邮件:
6、点击邮箱链接触发的操作
点击链接后,会进入到指定的servlet。从链接中可以看到,进入到的是一个名称叫forgetPasswordAction的servlet中。后面跟着两个参数:method----指定servlet触发什么操作,key----包含有发送时间(ms计算)和用户名信息,在servlet中会转化为明文。其中,"发送时间"用于判断用户点击链接的时候,该链接是否已经过时,"用户名"用于servlet跳转到jsp页面的前端显示。
下面看一下指定的servlet中的相关内容:
/** * 用户在点击邮箱里的链接后,进入该函数 * @param request * @param response */ public void resetPassword(HttpServletRequest request, HttpServletResponse response) { String key = request.getParameter("key"); ForgetPasswordService fService = new ForgetPasswordService(); List<String> datasList = new ArrayList<String>(); datasList = fService.getExplicitCode(key); String time = datasList.get(0); String userEmail = datasList.get(1); Boolean timeFlag = fService.judgeOfTime(time); //判断用户点击链接的时间是否过期 String flag = "false"; if (timeFlag) { flag = "true"; } List<String> resultList = new ArrayList<String>(); resultList.add(flag); resultList.add(userEmail); try { RequestDispatcher rDispatcher = request.getRequestDispatcher("resetPassword.jsp"); request.setAttribute("datasList", resultList); rDispatcher.forward(request, response); } catch (Exception e) { e.printStackTrace(); } }
7、重置密码页面
首先判断时间是否过期,并将标记发送到jsp中。下面给出resetPassword.jsp中的部分内容:
首先获得后台传过来的参数:
<% List<String> datasList = (List<String>) request.getAttribute("datasList"); String flag = datasList.get(0); //链接是否过期 // flag = "false"; String userEmail = datasList.get(1); //用户登录邮箱 %>得到flag,将flag设置到隐藏的input中:
<input type = "hidden" id = "hiddenInput" name = "hiddenInput" value = "<%=flag %>" >在本jsp页面中,有两个大的div,分别对应flag的不同标记。若flag的标记为true,则显示一个div的内容,隐藏另一个div,若flag为false,则反过来。
flag为true时显示的内容:
<form action="forgetPasswordAction" class="form-horizontal" role="form" method="POST" style="border: 1px dotted silver;" id="resetPasswordForm"> <br> <div class="form-group"> <div class = "col-lg-3 col-lg-offset-1 col-md-3 col-md-offset-1 col-sm-4 col-xs-4 text-right"> <label>用户名</label> </div> <div class = "col-lg-8 col-md-8 col-sm-7 col-xs-8 text-left"> <b style = "color:#FF0000;font-size:10px;">*</b> <label><%=userEmail %></label> <input type = "hidden" name = "userEmailInput" id = "userEmailInput" value = "<%=userEmail %>"> </div> </div> <div class="form-group"> <div class = "col-lg-3 col-lg-offset-1 col-md-3 col-md-offset-1 col-sm-4 col-xs-4 text-right"> <label>密 码</label> </div> <div class = "col-lg-8 col-md-8 col-sm-7 col-xs-8 text-left"> <b style = "color:#FF0000;font-size:10px;">*</b> <input type = "password" name = "password1" id = "password1" value = ""> <label>注:密码长度至少6位</label> </div> </div> <div class="form-group"> <div class = "col-lg-3 col-lg-offset-1 col-md-3 col-md-offset-1 col-sm-4 col-xs-4 text-right"> <label>确认密码</label> </div> <div class = "col-lg-8 col-md-8 col-sm-7 col-xs-8 text-left"> <b style = "color:#FF0000;font-size:10px;">*</b> <input type = "password" name = "password2" id = "password2" value = ""> </div> </div> <input type="hidden" name="method" value="resetPasswordComplete"> <div class="form-group"> <div class = "col-12 col-md-12 col-sm-12 col-xs-12 text-center"> <button type = "submit" class = "btn btn-primary btn-sm" onclick = "return resetPasswordConfirm()">确定</button> </div> </div> </form>
对应的页面如下:
若flag为false,即链接已过期,对应的html代码如下;
<div class = "col-lg-8 col-lg-offset-2 col-md-8 col-md-offset-2 col-sm-12 col-sm-12 text-left" id = "failureDivId"> <i class="fa fa-warning fa-lg" style="color: #FF0000;"></i><b style="font-family: arial; color: #00A600; font-size: 18px;">重置密码链接已过期</b> <p></p> <p></p> <p style="font-family: arial; font-size: 14px;"> 没有收到重置密码邮件,您可以到邮件垃圾箱里找找。 <br>或者点击:<a href = "/EVM/forgetPassword.jsp">【重新发送重置密码邮件】</a>。 </p> </div>
对应的页面如下:
jsp中的js控制代码:
var flag = $("#hiddenInput").val(); if(flag == "true") { $("#failureDivId").hide(); $("#resetPasswordForm").show(); } else { $("#resetPasswordForm").hide(); $("#failureDivId").show(); }
- 重置界面
进入重置页面,用户页面已自动填充(根据邮箱链接中的key值可得到用户名),用户这时候可进行密码重置。这里需要说明的一点是:一般的找回密码流程,最后都会让用户重新设置密码,不会把原来用户忘记的密码发送给用户。
其实,在重置密码页面,主要需要说明的就是密码的加密过程。
1、加密算法
我这里用到的是3DES密码加密,相关链接可以直接搜索3DES百度百科,里面有示例代码。这里我贴出相关的代码片段:
byte[] encoded = encryptMode(keyBytes, szSrc.getBytes()); System.out.println("加密后的字符串:" + new String(encoded)); byte[] srcBytes = decryptMode(keyBytes, encoded); System.out.println("解密后的字符串:" + (new String(srcBytes)));
这里可以看出来,加密之后的密文是一个byte数组,难就难在这个数组上,虽然可以使用new String(),转化为字符串,但是这个字符串是乱码,我试过,无论使用什么编码格式,转化出来的字符串都是乱码,这是一个问题,另一个问题是,转化后的字符串是无法再回退到byte数组的,即这个过程是不可逆的。基于以上两点缺陷,不能将得到的密文byte数组直接转化为字符串。
为了解决这个问题,我想到了另外一种方式,很巧妙的化解了byte数组的显示问题,而且,此种方式,在一定程度上还算是对byte数组的再次加密,方法如下:
/** * 将明文字符串加密成密文,然后以字符串的形式返回. * 说明:在将字符串明文加密后,得到的是一个byte[]数组,这时候如果将byte[]数组转化为字符串,是乱码。解决方式如下: * 步骤1:对于byte[]数组中的每个元素,因为范围都在-128~127之间,所以为了方便表达,统一加上128,都转化为0或者正数; * 步骤2: 利用Integer.toBinaryString()函数,将每个元素转化为16进制,结果若为单个的,用g在右侧补成2位的; * 步骤3:将所有的结果统一串成一个整个的字符串,作为结果返回。 * @param explicitPassword * @return */ public String encryptCode(String explicitString) { Security.addProvider(new com.sun.crypto.provider.SunJCE()); String implicitString = ""; byte[] encoded = encryptMode(keyBytes, explicitString.getBytes()); List<String> codeArrTemp = new ArrayList<String>(); for (int i = 0; i < encoded.length; i++) { codeArrTemp.add(String.valueOf(Integer.toHexString((int) encoded[i] + 128))); } List<String> codeArr = new ArrayList<String>(); for (int i = 0; i < codeArrTemp.size(); i++) { if (codeArrTemp.get(i).length() == 1) { String temp = codeArrTemp.get(i) + "g"; codeArr.add(temp); } else { codeArr.add(codeArrTemp.get(i)); } } for (int i = 0; i < codeArr.size(); i++) { implicitString += codeArr.get(i); } return implicitString; }注释中,已经给出了我的转化步骤,下面再给出与上面加密配套的解密代码:
/** * 对密文解密,返回明文 * @param implicitString * @return */ public String deEncryptCode(String implicitString) { Security.addProvider(new com.sun.crypto.provider.SunJCE()); String explicitString = null; byte[] encoded = null; //根据implicitString得到encoded List<String> codeArrTemp = new ArrayList<String>(); for (int i = 0; i < implicitString.length(); i += 2) { codeArrTemp.add(implicitString.substring(i, i + 2)); } List<String> codeArr = new ArrayList<String>(); for (int i = 0; i < codeArrTemp.size(); i++) { if (codeArrTemp.get(i).contains("g")) { codeArr.add(codeArrTemp.get(i).substring(0, 1)); } else { codeArr.add(codeArrTemp.get(i)); } } encoded = new byte[codeArr.size()]; for (int i = 0; i < codeArr.size(); i++) { encoded[i] = (byte) (Integer.parseInt(codeArr.get(i), 16) - 128); } byte[] srcBytes = decryptMode(keyBytes, encoded); explicitString = new String(srcBytes); return explicitString; }以上,就完成了字符串的加/解密过程,上面的代码可以直接拿过来用。其中,以上两个函数中,用到了原来的加/解密接口,这里顺便也把代码贴出来:
3DES加密:
// DES,DESede,Blowfish // keybyte为加密密钥,长度为24字节 // src为被加密的数据缓冲区(源) public static byte[] encryptMode(byte[] keybyte, byte[] src) { try { // 生成密钥 SecretKey deskey = new SecretKeySpec(keybyte, Algorithm); // 加密 Cipher c1 = Cipher.getInstance(Algorithm); c1.init(Cipher.ENCRYPT_MODE, deskey); return c1.doFinal(src); } catch (java.security.NoSuchAlgorithmException e1) { e1.printStackTrace(); } catch (javax.crypto.NoSuchPaddingException e2) { e2.printStackTrace(); } catch (java.lang.Exception e3) { e3.printStackTrace(); } return null; }3DES解密:
// keybyte为加密密钥,长度为24字节 // src为加密后的缓冲区 public static byte[] decryptMode(byte[] keybyte, byte[] src) { try { // 生成密钥 SecretKey deskey = new SecretKeySpec(keybyte, Algorithm); // 解密 Cipher c1 = Cipher.getInstance(Algorithm); c1.init(Cipher.DECRYPT_MODE, deskey); return c1.doFinal(src); } catch (java.security.NoSuchAlgorithmException e1) { e1.printStackTrace(); } catch (javax.crypto.NoSuchPaddingException e2) { e2.printStackTrace(); } catch (java.lang.Exception e3) { e3.printStackTrace(); } return null; }以上3段代码就是整个加密、解密的过程。在我们数据库中的密码加密,也是用到了以上的方法。
2、"重置密码"点击"确定"后的信息反馈页面
这一步类似于前面的发送邮箱的确认,也是分为两支:成功还是失败。这里再次贴出重置密码的页面:
在用户点击"确定"后,后台将密码加密,然后存入数据库,等操作完成后,后台的servlet跳转到一个新页面:resetPassSuccOrFail.jsp,即给出信息反馈,表示是重置成功还是失败。
这里的操作和前面都是类似的,也就不多说了。下面给出两张分支的页面:
当修改密码失败时:
至此,"忘记密码"功能已实现完毕。
相关推荐
彩虹表是一种预先计算好大量明文密码及其对应MD5哈希值的数据库,通过与待破解的哈希值比较,可以快速找到对应的明文密码。由于盐值的随机性,相同的密码即使在彩虹表中存在,也无法匹配,因为其散列值与生成时的...
### 信息系统密码管理规定知识点详解 #### 一、引言 在当今数字化时代,信息安全已成为企业生存和发展的重要保障。...企业在实施过程中应注意细节操作,并结合实际情况灵活调整策略,以实现最佳的安全效果。
以下是系统的核心功能模块及其实现细节: 1. 功能选择模块:该模块为用户提供菜单式操作界面,根据用户输入的选项执行相应的功能。系统针对管理员和投票人设置不同的权限,分别在list1()和list2()函数中实现。 2. ...
本文将详述“路由密码查看,登陆备份配置软件”的核心功能及其相关知识点,旨在帮助用户更好地理解和操作这类工具。 首先,标题中的“路由密码查看”指的是能够查看路由器登录密码的工具。通常,路由器的管理员密码...
文章详述了如何正确插入、使用及格式化存储卡,同时也解释了存储卡的不同工作模式——‘程序卡’与‘传送卡’的区别,以及如何利用存储卡重置忘记的密码和恢复出厂设置。 适合人群:熟悉自动化设备操作的技术人员和...
Debian及其衍生版(如Ubuntu)中的root密码重置步骤与Red Hat/CentOS类似,但存在一些细节上的差异: 1. **启动到GRUB菜单:** - 重启计算机。 - 在GRUB启动菜单中选择内核并按`e`键编辑启动选项。 2. **进入...
在登录界面中,我们可能用它来实现“记住我”或“忘记密码”等功能,用户点击后可以触发相应的功能,如自动保存登录状态或跳转到重置密码页面。 在实现这些组件的交互时,我们需要使用到Android的布局文件(如...
- 忘记密码功能:提供找回密码的方法,通常通过电子邮件确认。 - 非法用户登录限制:防止恶意用户频繁尝试登录,比如设置登录失败次数上限。 2. **模块流程分析**: - **登录页面** (`login.aspx`):提供用户...
3. **忘记密码**:设置找回密码功能,通过绑定的手机号或邮箱发送重置链接或验证码。 4. **安全问题**:对于高价值账户,可能需要设置安全问题,增加账户安全性。 5. **登录失败处理**:提供清晰的错误提示,如密码...
### 订单系统(Asp.net+SQL server 2008) #### 登录(管理员与普通用户登录...通过对上述各个模块的详细介绍,我们可以清晰地了解到每个部分的功能及其实现方式,这对于后续系统维护和功能扩展都具有重要的参考价值。
- 用户密码复位功能可以在用户忘记密码时帮助其重新设置密码。 **8.7 地址访问授权** - 地址访问授权功能可以为不同用户设定不同的访问权限,确保敏感信息的安全。 #### 配置 **9.1 配置KE** - 配置KE是指为...
- **《Applied Cryptography》**:Bruce Schneier 的这本经典之作深入探讨了密码学的实际应用,对于理解密码学原理及其在现实世界中的应用至关重要。 **在线社区** - **Reddit 的 r/netsec 和 r/cybersecurity 子...
- **重置密码**:若用户忘记密码,可以通过邮箱或手机号找回密码。 ##### 2. 资源管理 - **添加资源**:管理员可以添加新的资源,如文档、图片等。 - **修改资源**:可编辑已存在的资源信息。 - **删除资源**:支持...
登录过程应支持记住密码和忘记密码的功能,同时提供安全的账户保护措施,如二次验证。 3. 非功能性需求 非功能性需求通常涉及系统的性能、安全性、可用性、可维护性等方面。例如,系统应能处理大量并发用户,保证...
- **功能**:基于静态密码进行认证。 - **步骤**:使用“authentication-mode password”命令。 - **5.4.2 配置AAA验证** - **功能**:使用认证服务器进行认证。 - **步骤**:使用“authentication-mode aaa”...
2. **密码功能**: 详细讲解了BIOS中的密码功能,包括不同类型的密码(如管理员密码和用户密码)、如何设置、忘记密码后的处理方式以及密码的修改或删除等。 3. **BIOS消息列表**: 提供了一系列BIOS可能显示的信息...
根据提供的文件信息,我们...通过以上内容,我们可以清楚地了解到BBS论坛系统的主要功能和技术实现细节。这些知识对于系统开发人员、产品经理以及其他相关人员来说都非常重要,有助于确保项目的顺利进行和最终的成功。
- **存储过程**:使用存储过程(`CREATE PROCEDURE`)来封装一系列复杂的SQL操作,可以有效地实现诸如选课、调课等功能。 - **游标和临时表**:利用游标(`CURSOR`)和临时表(`TEMPORARY TABLE`)来处理复杂的数据操作...