本周的主要工作为工程性上的工作:完成网页注册登录模块的前后端。
主要内容为:
- 实现注册登录功能
- 实现验证码验证功能
- 注册邮箱验证部分
其中验证码部分的实现为随机在预设的列表中选择一个字符已经相应的字体、背景颜色,循环四次,之后这四个图片进行拼接。然后存储下随机选出的字符,等待用户提交后进行比对。 完成的页面如下图所示:

html代码
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8"/>
<title>系统登录</title>
<link rel="stylesheet" type="text/css" href="/css/reset.css"/>
<link rel="stylesheet" type="text/css" href="/css/login.css"/>
<script type="text/javascript" src="/js/jquery.js"></script>
<script src="/js/login.js"></script>
<!-- <script src="js/jquery-1.11.1.js"></script>
<script src="js/login.js"></script>
<link href="css/style.css" rel="stylesheet" type="text/css" />-->
</head>
<body>
<div class="main">
<div class="loginheader">
<div class="logintitle"><h1>Ctrl_I<br/>用户登录</h1></div>
</div>
<form action = "/checkLogin" method="post">
<div class="loginform">
<div class="loginform_row">
<label>用户名:</label>
<input type="text" class="loginform_input" name="username" />
</div>
<div class="loginform_row">
<label>密码:</label>
<input type="password" class="loginform_input" name="password" />
</div>
<div class = "loginform_row">
<label>验证码:</label>
<input type = "text" class="loginform_input_validationCode" name = "validationCode"/>
<img class = "validationCode_img" src="/flight_order/getVerify?+1"/>
</div>
<div class="loginform_row">
<span class = "returnInfo"></span>
<input type="submit" class="loginform_submit" value="登录" />
</div>
<div class="loginform_row">
<a href="register">注册账号</a>
</div>
<div class="clear"></div>
</div>
</form>
</div>
</body>
</html>
html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,dl,dt,dd,ol,nav ul,nav li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video{margin:0;padding:0;border:0;font-size:100%;font:inherit;vertical-align:baseline;}
article, aside, details, figcaption, figure,footer, header, hgroup, menu, nav, section {display: block;}
ol,ul{list-style:none;margin:0px;padding:0px;}
blockquote,q{quotes:none;}
blockquote:before,blockquote:after,q:before,q:after{content:'';content:none;}
table{border-collapse:collapse;border-spacing:0;}
/* start editing from here */
a{text-decoration:none;}
.txt-rt{text-align:right;}/* text align right */
.txt-lt{text-align:left;}/* text align left */
.txt-center{text-align:center;}/* text align center */
.float-rt{float:right;}/* float right */
.float-lt{float:left;}/* float left */
.clear{clear:both;}/* clear float */
.pos-relative{position:relative;}/* Position Relative */
.pos-absolute{position:absolute;}/* Position Absolute */
.vertical-base{ vertical-align:baseline;}/* vertical align baseline */
.vertical-top{ vertical-align:top;}/* vertical align top */
nav.vertical ul li{ display:block;}/* vertical menu */
nav.horizontal ul li{ display: inline-block;}/* horizontal menu */
img{max-width:100%;}
/*end reset*/
/****-----start-body----****/
body{
/*background:#F7DA55;*/
background: #f7423d;
font-family: 'Open Sans', sans-serif;
}
.main {
background:#eee;
width: 26%;
margin:9% auto 4% auto;
position: relative;
-webkit-border-radius: 0.4em;
-o-border-radius: 0.4em;
-moz-border-radius: 0.4em;
}
.head {
position: absolute;
top:-15%;
left: 35%;
}
.head img {
border-radius:50%;
-webkit-border-radius:50%;
-o-border-radius:50%;
-moz-border-radius:50%;
border:6px solid rgba(221, 218, 215, 0.23);
}
.main{
position:relative;
}
.main h1{
font-size:25px;
color:#676767;
font-family: 'Open Sans', sans-serif;
font-weight:400;
padding-top: 19%;
text-align: center;
}
.main form {
width: 80%;
margin: 0 auto;
padding: 6% 0 9% 0;
}
.main p {
text-align: center;
}
.main form p a {
color: #888;
font-family: 'Open Sans', sans-serif;
}
form p a:hover {
color:#21A957;
}
input[type="text"], input[type="password"]{
text-align:left;
position: relative;
width:92%;
padding:3%;
background:#D3D3D3;
margin-bottom: 6%;
font-family: 'Open Sans', sans-serif;
color: #676767;
font-weight:600;
font-size: 16px;
outline: none;
border: none;
border-radius: 5px;
border:1px solid #DED6D6;
-webkit-appearance:none;
}
input[type="text"]:hover, input[type="password"]:hover{
border:1px solid #949494;
transition:0.5s;
-webkit-transition:0.5s;
-moz-transition:0.5s;
-o-transition:0.5s;
-ms-transition: 0.5s;
}
input[type="submit"]{
width: 99%;
padding: 3%;
margin-bottom: 8%;
background: #21A957;
font-family: 'Open Sans', sans-serif;
color: #ECECEC;
box-shadow: inset 0px 0px 10px #666464;
-webkit-text-shadow: 0px 0px 3px #000;
-moz-text-shadow: 0px 0px 3px #000;
-o-text-shadow: 0px 0px 3px #000;
-ms-text-shadow: 0px 0px 3px #000;
font-size: 20px;
outline: none;
border: none;
cursor: pointer;
font-weight:500;
border-radius: 5px;
transition: 0.5s;
-webkit-appearance:none;
-webkit-transition: 0.5s;
-moz-transition: 0.5s;
-o-transition: 0.5s;
-ms-transition: 0.5s;
}
input[type="submit"]:hover{
background:#128A42;
color:#fff;
}
登录格式验证部分
$(function(){
$(".loginform_submit").click(function(){
if(checkInput()) {
$("form").action("/LoginServlet");
}else{
return false;
}
});
$(".validationCode_img").click(function(){
$(".validationCode_img").attr("src","/flight_order/getVerify?"+Math.random());
});
function checkInput(){
//判断用户名
if($("input[name=username]").val() == null || $("input[name=username]").val() == ""){
alert("用户名不能为空");
$("input[name=username]").focus();
return false;
}
//判断密码
if($("input[name=password]").val() == null || $("input[name=password]").val() == ""){
alert("密码不能为空");
$("input[name=password]").focus();
return false;
}
//判断验证码
if($("input[name=validationCode]").val() == null || $("input[name=validationCode]").val() == ""){
alert("验证码不能为空");
$("input[name=validationCode]").focus();
return false;
}
return true;
}
});
注册格式验证部分
$(function(){
$(".loginform_submit").click(function(){
if(checkInput()) {
$("form").action("/RegisterServlet");
}else{
return false;
}
}
);
function checkInput(){
//判断用户名
if($("input[name=username]").val() == null || $("input[name=username]").val() == ""){
alert("用户名不能为空");
$("input[name=username]").focus();
return false;
}
//判断密码
if($("input[name=password]").val() == null || $("input[name=password]").val() == ""){
alert("密码不能为空");
$("input[name=password]").focus();
return false;
}
if($("input[name=password2]").val() == null || $("input[name=password2]").val() == ""){
alert("请再次输入密码");
$("input[name=password2]").focus();
return false;
}
if(!($("input[name=password2]").val() == $("input[name=password]").val())){
alert("两次输入的密码不一致");
return false;
}
//判断邮箱
if($("input[name=email]").val() == null || $("input[name=email]").val() == ""){
alert("邮箱不能为空");
$("input[name=email]").focus();
return false;
}
if(!isEmail($("input[name=email]").val())){
alert("邮箱格式不正确!")
return false;
}
return true;
}
function isEmail(str){
var reg = /^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/;
return reg.test(str);
}
});
java登录后台部分
import flight_order.dao.JDBC;
import flight_order.dao.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
@Controller
public class LoginServlet {
@Autowired
private JDBC jdbc;
@PostMapping("/checkLogin")
public String check_login(@RequestParam String username, @RequestParam String password, @RequestParam String validationCode ,
HttpSession session, HttpServletResponse response, Model model) throws IOException
{
User user = new User(username,password);
//先检查验证码,再检查用户名,再检查邮箱状态,再检查密码
String validation_code = (String)session.getAttribute("validation_code"); //存在session中的验证码
if(validation_code.equalsIgnoreCase(validationCode)){
if(jdbc.check_username(user)){
if(jdbc.check_userState(user)==1){
if(jdbc.check_userPassword(user)){
if(jdbc.check_admin(user)){
session.setAttribute("userInfo",username);
System.out.println(username);
return "admin_plane";
}
model.addAttribute("userInfo",username);
session.setAttribute("userInfo",username);
System.out.println(username);
return "index";
}
else {
return ShowAlert("密码错误",response);
}
}
else {
return ShowAlert("邮箱未激活",response);
}
}
else {
return ShowAlert("用户名不存在",response);
}
}
else {
return ShowAlert("验证码错误",response);
}
}
private String ShowAlert(String mes,HttpServletResponse response){
try{
response.setContentType("text/html; charset=utf-8");
PrintWriter out = response.getWriter();
out.print("<script>alert('"+mes+"');</script>");
//out.print("<script>location='/login';</script>");
//out.flush();//有了这个,下面的return就不会执行了
return"login_html";
}
catch (Exception e){
e.printStackTrace();
}
return "";
}
}
java注册后台部分
package flight_order;
import flight_order.dao.JDBC;
import flight_order.dao.User;
import flight_order.email.EmailSend;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
@Controller
public class RegisterServlet {
@Autowired
JDBC jdbc;
@PostMapping("/checkRegister")
public String check_Register(@RequestParam String username, @RequestParam String password, @RequestParam String email ,
HttpServletResponse response) throws Exception {
User user = new User(username,password,email);
//注册的时候先检查该用户名是否已经注册过,再检查邮箱是否已经使用过,没有的话插入新的数据
if(jdbc.check_username(user)){
return ShowAlert("该用户名已经注册过",response,0);
}
else {
if(jdbc.check_userEmail(user)){
return ShowAlert("邮箱已经被使用,请更换邮箱",response,0);
}
else {
user.setCode(user.getUser_email().hashCode()+"");
user.setState(0);
System.out.println(jdbc.insert_userInfo(user));
String link = "http://localhost:8080/confirm_email?code="+user.getUser_email().hashCode();
//String link = "http://255.255.255.0:8080/confirm_email?code="+user.getUser_email().hashCode();
EmailSend.send(user,link);
return ShowAlert("注册成功,请查收激活邮件",response,1);
}
}
}
//显示通知栏
private String ShowAlert(String message,HttpServletResponse response,int num){
try{
response.setContentType("text/html; charset=utf-8");
PrintWriter out = response.getWriter();
out.print("<script>alert('"+message+"');</script>");
if(num==0)
return"register";
if(num==1)
return "login_html";
}
catch (Exception e){
e.printStackTrace();
}
return "";
}
}
发送邮件部分
package flight_order.email;
import flight_order.dao.User;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.NewsAddress;
import java.util.Date;
import java.util.Properties;
public class EmailSend {
// 发件人的 邮箱 和 密码(替换为自己的邮箱和密码)
// PS: 某些邮箱服务器为了增加邮箱本身密码的安全性,给 SMTP 客户端设置了独立密码(有的邮箱称为“授权码”),
// 对于开启了独立密码的邮箱, 这里的邮箱密码必需使用这个独立密码(授权码)。
public static String myEmailAccount = "919480698@qq.com";
public static String myEmailPassword = "";
// 发件人邮箱的 SMTP 服务器地址, 必须准确, 不同邮件服务器地址不同, 一般(只是一般, 绝非绝对)格式为: smtp.xxx.com
// 网易163邮箱的 SMTP 服务器地址为: smtp.163.com
public static String myEmailSMTPHost = "smtp.qq.com";
// 收件人邮箱(替换为自己知道的有效邮箱)
public static String receiveMailAccount ;
public static void send(User item,String link) throws Exception {
receiveMailAccount=item.getUser_email();
// 1. 创建参数配置, 用于连接邮件服务器的参数配置
Properties props = new Properties(); // 参数配置
props.setProperty("mail.transport.protocol", "smtp"); // 使用的协议(JavaMail规范要求)
props.setProperty("mail.smtp.host", myEmailSMTPHost); // 发件人的邮箱的 SMTP 服务器地址
props.setProperty("mail.smtp.auth", "true"); // 需要请求认证
// PS: 某些邮箱服务器要求 SMTP 连接需要使用 SSL 安全认证 (为了提高安全性, 邮箱支持SSL连接, 也可以自己开启),
// 如果无法连接邮件服务器, 仔细查看控制台打印的 log, 如果有有类似 “连接失败, 要求 SSL 安全连接” 等错误,
// 打开下面 /* ... */ 之间的注释代码, 开启 SSL 安全连接。
// SMTP 服务器的端口 (非 SSL 连接的端口一般默认为 25, 可以不添加, 如果开启了 SSL 连接,
// 需要改为对应邮箱的 SMTP 服务器的端口, 具体可查看对应邮箱服务的帮助,
// QQ邮箱的SMTP(SLL)端口为465或587, 其他邮箱自行去查看)
final String smtpPort = "465";
props.setProperty("mail.smtp.port", smtpPort);
props.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
props.setProperty("mail.smtp.socketFactory.fallback", "false");
props.setProperty("mail.smtp.socketFactory.port", smtpPort);
// 2. 根据配置创建会话对象, 用于和邮件服务器交互
Session session = Session.getDefaultInstance(props);
session.setDebug(true); // 设置为debug模式, 可以查看详细的发送 log
// 3. 创建一封邮件
MimeMessage message = createMimeMessage(session, myEmailAccount, receiveMailAccount,link);
// 4. 根据 Session 获取邮件传输对象
Transport transport = session.getTransport();
// 5. 使用 邮箱账号 和 密码 连接邮件服务器, 这里认证的邮箱必须与 message 中的发件人邮箱一致, 否则报错
//
// PS_01: 成败的判断关键在此一句, 如果连接服务器失败, 都会在控制台输出相应失败原因的 log,
// 仔细查看失败原因, 有些邮箱服务器会返回错误码或查看错误类型的链接, 根据给出的错误
// 类型到对应邮件服务器的帮助网站上查看具体失败原因。
//
// PS_02: 连接失败的原因通常为以下几点, 仔细检查代码:
// (1) 邮箱没有开启 SMTP 服务;
// (2) 邮箱密码错误, 例如某些邮箱开启了独立密码;
// (3) 邮箱服务器要求必须要使用 SSL 安全连接;
// (4) 请求过于频繁或其他原因, 被邮件服务器拒绝服务;
// (5) 如果以上几点都确定无误, 到邮件服务器网站查找帮助。
//
// PS_03: 仔细看log, 认真看log, 看懂log, 错误原因都在log已说明。
transport.connect(myEmailAccount, myEmailPassword);
// 6. 发送邮件, 发到所有的收件地址, message.getAllRecipients() 获取到的是在创建邮件对象时添加的所有收件人, 抄送人, 密送人
transport.sendMessage(message, message.getAllRecipients());
// 7. 关闭连接
transport.close();
}
/**
* 创建一封只包含文本的简单邮件
*
* @param session 和服务器交互的会话
* @param sendMail 发件人邮箱
* @param receiveMail 收件人邮箱
* @return
* @throws Exception
*/
public static MimeMessage createMimeMessage(Session session, String sendMail, String receiveMail,String link) throws Exception {
// 1. 创建一封邮件
MimeMessage message = new MimeMessage(session);
// 2. From: 发件人
message.setFrom(new InternetAddress(sendMail, "ctrl_i", "UTF-8"));
// 3. To: 收件人(可以增加多个收件人、抄送、密送)
message.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress(receiveMail, "XX用户", "UTF-8"));
// 4. Subject: 邮件主题
message.setSubject("ctrl_i", "UTF-8");
// 5. Content: 邮件正文(可以使用html标签)
//link = "http://localhost:8080/login";
message.setContent("你好, 请点击链接验证邮箱:<a href="+link+">验证邮箱</a>", "text/html;charset=UTF-8");
// 6. 设置发件时间
message.setSentDate(new Date());
// 7. 保存设置
message.saveChanges();
return message;
}
// public static void main(String[] args) throws Exception{
// User item = new User("a","a","a");
// item.setUser_email("2629248255@qq.com");
// email.send(item,"http://localhost:8080/login");
// }
}
验证码部分
package flight_order;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Random;
@Controller
public class ValidationCode {
protected void GetValidation(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
int charsLength = codeChars.length();
resp.setHeader("ragma","No-cache");
resp.setHeader("Cache-Control","no-cache");
resp.setDateHeader("Expires",0);
int width = 90 ,height = 30;
BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics();
Random random =new Random();
g.setColor(getRandomColor(180,250));
g.fillRect(0,0,width,height);
g.setFont(new Font("Times New Roman",Font.ITALIC,height));
g.setColor(getRandomColor(120,180));
//用于保存最后生成的验证码
StringBuilder validationCode = new StringBuilder();
//验证码的随机字体
String[] fontNames = {"Times New Roman","Bookantiqua","Arial"};
//随机获得四个验证码
for (int i =0;i<4;i++){
//随机字体
g.setFont(new Font(fontNames[random.nextInt(3)],Font.ITALIC,height));
//随机字符
char codeChar = codeChars.charAt(random.nextInt(charsLength));
validationCode.append(codeChar);
g.setColor(getRandomColor(10,100));
g.drawString(String.valueOf(codeChar),16*i+random.nextInt(7),height-random.nextInt(6));
}
HttpSession session =req.getSession();
session.setMaxInactiveInterval(300);
session.setAttribute("validation_code",validationCode.toString());
String test =(String)session.getAttribute("validation_code");
System.out.println(test);
g.dispose();
OutputStream outS=resp.getOutputStream();
ImageIO.write(image,"JPEG",outS);
}
//图形验证码的字符集,系统将随机从这个字符串中选择一些字符作为验证码
private static String codeChars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
private static Color getRandomColor(int mincolor, int maxcolor){
Random random =new Random();
if(mincolor>255){
mincolor=255;
}
if(maxcolor>255){
maxcolor=255;
}
//r
int red = mincolor+random.nextInt(maxcolor-mincolor);
//g
int green = mincolor+random.nextInt(maxcolor-mincolor);
//b
int blue = mincolor+random.nextInt(maxcolor-mincolor);
return new Color(red,green,blue);
}
/**
* 生成验证码
*/
@RequestMapping(value = "/flight_order/getVerify")
public void getVerify(HttpServletRequest request, HttpServletResponse response) {
try {
response.setContentType("image/jpeg");//设置相应类型,告诉浏览器输出的内容为图片
//response.setHeader("Pragma", "No-cache");//设置响应头信息,告诉浏览器不要缓存此内容
//response.setHeader("Cache-Control", "no-cache");
// response.setDateHeader("Expire", 0);
ValidationCode randomValidateCode = new ValidationCode();
randomValidateCode.GetValidation(request, response);//输出验证码图片方法
} catch (Exception e) {
System.out.println("获取验证码失败>>>> ");
}
}
}
本周主要进行工程性工作,完成了网页注册登录模块的前后端开发。具体实现了注册登录、验证码验证、注册邮箱验证等功能,包含 HTML 代码编写,以及 Java 登录和注册后台开发,还有发送邮件和验证码部分。

363

被折叠的 条评论
为什么被折叠?



