目录
一、前言
在十三大神的博客界面的基础上,我又加上了GayHub上的一个My Login界面,很漂亮有兴趣的朋友可以自己去GayHub上搜索或者在本文末尾我的GitHub中查找。其实本来不打算添加这些登录注册功能的,毕竟也没啥人来看我的博客,但是又觉得既然做了,那就把所有的内容都做好才能行,所以趁今天加班把这个完成
二、添加前端界面
将下载好的代码放到自己创建好的文件夹,把css文件和一些图片放到对应的文件夹中,我习惯将html文件改为jsp文件
代码放完后要记住修改一些代码中的路径,否则会造成找不到css或者图标素材之类的问题
也有可能发生经过路径跳转后,相对路径错误的问题,所以我们这里统一改成绝对路径
现在以index.jsp为例
修改controller,测试界面
界面正常
三、邮件发送工具
1.引入java.mail
<!-- javax.mail -->
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.6.0</version>
</dependency>
2.邮箱开启POP3/SMTP/IMAP
开启SMTP功能会要求设置同行码,记录下来,下一步会用到
3.设置相关参数
新建config.properties,将相关参数写入
mail.smtp.auth=true
#mail.transport.protocol=smtp
mail.send.charset=UTF-8
mail.smtp.port=465
#mail.is.ssl=true
mail.host=smtp.163.com
[email protected]
#授权码
mail.auth.password=wy********
mail.smtp.timeout=5000
4.EmailUtil.java类
新建EmailUtil.java类,并导入邮箱参数
package cn.yzstu.common.utils.email;
import cn.yzstu.common.utils.Configration;
import org.springframework.context.annotation.Configuration;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Properties;
/**
* \* Created with IntelliJ IDEA.
* \* User: Baldwin
* \* E_Mail: [email protected] || [email protected]
* \* Date: 2019/12/16
* \* Time: 16:22
* \* To change this template use File | Settings | File Templates.
* \* Description:
* \
*/
public class EmailUtil {
// 发件人的 邮箱 和 密码(替换为自己的邮箱和密码)
// PS: 某些邮箱服务器为了增加邮箱本身密码的安全性,给 SMTP 客户端设置了独立密码(有的邮箱称为“授权码”),
// 对于开启了独立密码的邮箱, 这里的邮箱密码必需使用这个独立密码(授权码)。
public static String myEmailAccount = Configration.getInstance("config").getValue("mail.auth.name");
public static String myEmailPassword = Configration.getInstance("config").getValue("mail.auth.password");
// 发件人邮箱的 SMTP 服务器地址, 必须准确, 不同邮件服务器地址不同, 一般(只是一般, 绝非绝对)格式为: smtp.xxx.com
// 网易163邮箱的 SMTP 服务器地址为: smtp.163.com
public static String myEmailSMTPHost = Configration.getInstance("config").getValue("mail.host");
//端口
public static int myEmailSMTPPort = Integer.valueOf(Configration.getInstance("config").getValue("mail.smtp.port"));
//chartset
public static String myEmailCharset = Configration.getInstance("config").getValue("mail.send.charset");
/**
* spring方式发送
*
* @param content
* @param addr
*/
private void sendByAdds(String content, String title, String addr[]) {
// 创建邮件发送服务器
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
mailSender.setHost(myEmailSMTPHost);
mailSender.setPort(myEmailSMTPPort);
mailSender.setUsername(myEmailAccount);
mailSender.setPassword(myEmailPassword);
mailSender.setDefaultEncoding(myEmailCharset);
// 加认证机制
Properties javaMailProperties = new Properties();
javaMailProperties.setProperty("mail.smtp.auth", "true");// 开启认证
javaMailProperties.setProperty("mail.debug", "true");// 启用调试
javaMailProperties.setProperty("mail.smtp.timeout", "1000");// 设置链接超时
javaMailProperties.setProperty("mail.smtp.port", Integer.toString(myEmailSMTPPort));// 设置端口
javaMailProperties.setProperty("mail.smtp.socketFactory.port", Integer.toString(myEmailSMTPPort));// 设置ssl端口
javaMailProperties.setProperty("mail.smtp.socketFactory.fallback", "false");
javaMailProperties.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
mailSender.setJavaMailProperties(javaMailProperties);
// 创建邮件内容
SimpleMailMessage message = new SimpleMailMessage();
message.setFrom(myEmailAccount);
for (int i = 0; i < addr.length; i++) {
String email = addr[i];
message.setTo(email);
message.setSubject(title);
message.setText(content);
// 发送邮件
mailSender.send(message);
}
}
public static void sendEmail(String content, String title, String addr[]) {
// 配置发送邮件的环境属性
final Properties props = new Properties();
// 表示SMTP发送邮件,需要进行身份验证
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.host", myEmailSMTPHost);
// 如果使用ssl,则去掉使用25端口的配置,进行如下配置,
props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
props.put("mail.smtp.socketFactory.port", "465");
props.put("mail.smtp.port", "465");
// 发件人的账号
props.put("mail.user", myEmailAccount);
// 访问SMTP服务时需要提供的密码
props.put("mail.password", myEmailPassword);
// 构建授权信息,用于进行SMTP进行身份验证
Authenticator authenticator = new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
// 用户名、密码
String userName = props.getProperty("mail.user");
String password = props.getProperty("mail.password");
return new PasswordAuthentication(userName, password);
}
};
// 使用环境属性和授权信息,创建邮件会话
Session mailSession = Session.getInstance(props, authenticator);
// mailSession.setDebug(true);
// 创建邮件消息
MimeMessage message = new MimeMessage(mailSession);
try {
for (int j = 0; j < addr.length; j++) {
// 设置发件人
InternetAddress from = new InternetAddress(myEmailAccount);
message.setFrom(from);
// Address[] a = new Address[1];
// a[0] = new InternetAddress("***");
// message.setReplyTo(a);
// 设置收件人
InternetAddress to = new InternetAddress(addr[j]);
message.setRecipient(MimeMessage.RecipientType.TO, to);
// 设置邮件标题
message.setSubject(title);
// 设置邮件的内容体
message.setContent(content, "text/html;charset=UTF-8");
// 发送邮件
Transport.send(message);
}
} catch (MessagingException e) {
e.printStackTrace();
// 在这里处理message内容, 格式是固定的
System.out.println(e.getMessage());
}
}
public static void main(String[] args) {
String content = "用户密码:123455";
EmailUtil emailUtil = new EmailUtil();
emailUtil.sendEmail(content, "我是测试title", new String[]{"[email protected]"});
}
}
5.测试
这里在EmaiUtil.java中写一个main函数来测试,直接运行main函数
邮箱接收到邮件
四、注册功能
引用大佬的前端模板,做一下小小的修改,添加了几个需要填入的参数
点击Create One进入注册界面
输入完成后点击Register会请求/user/regist.action,这个请求地址是写在UserController.java里的,我们来看下相关的代码
@RequestMapping(value = "/regist.action")
public ModelAndView userRegist(HttpServletRequest request) {
ModelAndView mv = new ModelAndView();
String userEmail = request.getParameter("email");
//6位随机验证码
String emailVerifyCode = RandomUtil.getRandomString(6);
//发送验证码
try {
EmailUtil.sendEmail(Constants.EMAIL_VERIFY_CONTANTS_PREFIX + emailVerifyCode + Constants.EMAIL_VERIFY_CONTANTS_SUFFIX, Constants.EMAIL_VERIFY_TITLE, userEmail);
} catch (SendFailedException e) {//捕获错误的邮箱格式或其他原因导致的异常
request.setAttribute("msg", "发送验证码失败,请检查邮箱格式或稍后重新发送!");
mv.setViewName("forward:/login/register.jsp");
}
//String emailVerfyKey = userEmail ;
//验证码存入redis,设置三分钟内过期,等待验证
//打算把验证码设置成一天只能发一次,防止邮件攻击
redisUtil.set(userEmail, emailVerifyCode, 180);
//请求转发到验证界面
mv.setViewName("forward:/login/verify.jsp");
return mv;
}
我们这里做了四件事:生成验证码、验证码发送、验证码存入Redis(key=email),转发请求到验证页面
虽然我能保证这个邮箱验证功能没啥问题,但是这个验证码不是我邮件收到的,而是我从Redis库里拿到的,原因是坑爹的网易云邮箱禁止了我这种穷逼程序员用他的STMP服务,第一次发送邮件的时候我收到了网站发来的邮件,但是第一次过后我就再也收不到了,这是这个原因导致我这篇文章晚了两天才发布,这两天一直在尝试找一个免费使用的STMP服务商,但大多数比较坑,现在准备自己搭建一个邮箱服务器
我们用的request请求转发,但是我们需要在verify.jsp让user自己输入验证码,输入验证码再请求服务器时,注册时的参数都丢失了,所以我们需要在verify.jsp中将参数隐性的放到request里,如下
<form method="POST" class="my-login-validation" novalidate="" action="/user/emailVerify.action">
<input type="hidden" id="nickName" name="nickName" value="<%=request.getParameter("nickName")%>">
<input type="hidden" id="password" name="password" value="<%=request.getParameter("password")%>">
<input type="hidden" id="name" name="name" value="<%=request.getParameter("name")%>">
<input type="hidden" id="email" name="email" value="<%=request.getParameter("email")%>">
<input type="hidden" id="phone" name="phone" value="<%=request.getParameter("phone")%>">
<input type="hidden" id="detail" name="detail" value="<%=request.getParameter("detail")%>">
<div class="form-group">
<label for="emailVerify">Email Verify Code</label>
<input id="emailVerify" type="text" class="form-control" name="emailVerify"
required
data-eye>
<div class="invalid-feedback">
Password is required
</div>
</div>
<div class="form-group m-0">
<button type="submit" class="btn btn-primary btn-block">
Register
</button>
</div>
<div class="mt-4 text-center">
Already have an account? <a href="<%=basePath%>login/index.jsp">Login</a>
</div>
</form>
在form标签中加入几个type为hidden的input标签,将上一个请求的参数写入request,然后请求/user/emailVerify.action,相关代码如下
/**
* @param request
* @return
*/
@RequestMapping(value = "/emailVerify.action")
public ModelAndView sendMail(HttpServletRequest request) {
ModelAndView mv = new ModelAndView();
Map<String, String[]> paramMap = RequestUtil.getRequestParamMap(request);
String userMail = paramMap.containsKey("email") ? paramMap.get("email")[0] : "nothing";
String verifyCode = (String) redisUtil.get(userMail);
if (null == verifyCode) {//验证码不存在===》失效
request.setAttribute("msg", "验证码失效,请重新发送!");
mv.setViewName("forward:/login/register.jsp");
return mv;
}
String userCode = paramMap.get("emailVerify")[0];
if (!verifyCode.equalsIgnoreCase(userCode)) {
request.setAttribute("msg", "验证码错误,请重新输入!");
mv.setViewName("forward:/login/register.jsp");
return mv;
}
User user = new User(paramMap);
int target = userService.insert(user);
mv.setViewName("forward:/login/index.jsp");
return mv;
}
在这个接口里,我们做了四件事:验证验证码是否失效、验证验证码、OK则写入数据库(注册已完成)、跳转到登录界面
有朋友或许注意到了,我将request的param封装在了一个map里,这样是为了容易进行一些判定操作,我也不知道这样是否合适,如果有懂这个的朋友,还请指点一下
五、总结
其实这个功能不算麻烦,设计思路也很近简单,但是拖了两天才发出来,就是因为STMP服务那个问题,一开始完全没有想到是服务商的问题,找了很久自己代码的毛病,但是第一次发送其实是成功的,所以困扰了很久,后来是在网上看到了一篇抱怨网易邮箱的文章才忽然想明白的。
总之,垃圾网易、毁我青春(滑稽脸)
上一篇:从零开始,SpringBoot+Redis+MySQL搭建个人博客(四)-----利用互联网工具一天内快速完成一套博客前端界面
下一篇:从零开始,SpringBoot+Redis+MySQL搭建个人博客(六)-----添加登录功能并实现访问网址即跳转主页