IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 邮箱验证流程与token生成 -> 正文阅读

[移动开发]邮箱验证流程与token生成

该过程仅供参考,若有优化与建议,欢迎提出。

依赖

		<!-- 发送邮件依赖 -->
      	<dependency>
      		<groupId>javax.mail</groupId>
      		<artifactId>mail</artifactId>
      		<version>1.4.7</version>
    	</dependency>
		<!-- 谷歌缓存依赖 -->
      	<dependency>
    		<groupId>com.google.guava</groupId>
    		<artifactId>guava</artifactId>
    		<version>28.2-jre</version>
    	</dependency>

邮箱验证

邮箱工具类

此处用的是线程的方式,Callable更容易设置是否超时

import java.util.Date;
import java.util.Properties;
import java.util.concurrent.Callable;


import javax.mail.Message;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

public class SEmail implements Callable<Boolean>{
	private static String USERNAME = "";//邮箱地址XXX@XX.XX
	/*
	* POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务
	*需要给你的邮箱开启该功能,并填写相应信息
	*/
	private static String PASSWORD = "";//填写你的邮箱的授权码
	private static String HOST = "";//选择一个可用的服务器
	private String email;//目标邮箱
	private String code;//生成的验证码
	
	
	public SEmail(String email,String code){
		this.email = email;
		this.code = code;
	}
	public Boolean call() throws Exception{
		Transport transport = null;
		Properties prop = new Properties();
		prop.setProperty("mail.smtp.host", HOST);
		prop.setProperty("mai.transport.protocol", "smtp");
		prop.setProperty("mail.smtp.auth","true");
		Session session = Session.getDefaultInstance(prop);
		MimeMessage message = new MimeMessage(session);
		message.setFrom(new InternetAddress(USERNAME));
		message.setRecipient(Message.RecipientType.TO,new InternetAddress(email));
		message.setSentDate(new Date());
		message.setSubject("邮件验证码");
		String info = "<!DOCTYPE html>\r\n" + 
				"<html lang=\"en\"" + 
				"<head>\r\n" + 
				"	<meta charset=\"UTF-8\"/>\r\n" + 
				"	<title>验证码</title>\r\n" + 
				"</head>\r\n" + 
				"	<body>\r\n" + 
				"	<h1>欢迎您使用XXX,这是您的验证码,请于X分钟内输入激活码</h1>\r\n" + 
				"	<p>"+ code +"</p>"+
				"	</body>\r\n" + 
				"</html>";
		message.setContent(info,"text/html;charset=UTF-8");
		message.saveChanges();
		session.setDebug(false);
		transport = session.getTransport("smtp");
		transport.connect(USERNAME,PASSWORD);
		transport.sendMessage(message, message.getAllRecipients());
		return true;
	}
}

检查邮箱格式

public class CheckData {
    private static String NUM = ".*\\d+.*";
    private static String SMALL = ".*[a-zA-Z]+.*";
    private static String CAPTIAL= ".*[a-zA-Z]+.*";
    private static String SYMBOL = ".*([~!@#$%^&*()_+|<>,.?/:;'\\[\\]{\\\\}\\\"]){1,}+.*";
    private static String EMAIL = "(\\w+([-.][A-Za-z0-9]+)*){3,18}@\\w+([-.][A-Za-z0-9]+)*\\.\\w+([-.][A-Za-z0-9]+)*";
    /*
	*邮箱格式检查
	*/
	public static boolean checkEmail(String email) {
		 if (email != null) {
	            return email.matches(EMAIL);
	        }
		 return false;
	}
	/*
	*密码格式检查,此处是必须要有带小写+数字+不能有特殊符号
	*/
	public static boolean checkPass(String password) {
		if (password == null){
			return false;
		}
		int size = password.length();
		if(size < 6||size >16) {
			return false;
		}
		if(password.matches(SYMBOL)) {
			return false;
		}
	    int n =  (password.matches(SMALL) ? 1 : 0) + (password.matches(NUM) ? 1 : 0) + (password.matches(CAPTIAL) ? 1 : 0);
	    return n==3;  
	}
}

Cache缓存

使用谷歌的一款包

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import java.util.concurrent.TimeUnit;

public class VerifyCodeCache {
	/**
     * 5分钟的验证码缓存,保障线程安全
     */
    private static volatile Cache<String,String> codeCache;

    private VerifyCodeCache(){}

    public static Cache<String,String> getCodeCache() {
       	//单例,懒汉模式
    	//双验证+同步锁
        if (codeCache == null) {
            synchronized (VerifyCodeCache.class) {
                if (codeCache == null) {
                    codeCache = CacheBuilder.newBuilder()
                            .expireAfterAccess(5, TimeUnit.MINUTES)
                            .maximumSize(100)
                            .concurrencyLevel(50).build();
                }
            }
        }
        return codeCache;
    }
}



SendEmail方法

	/*
	 * 此处使用固定大小的线程池,限制可同时发送的数目
	 * 允许10个线程同时执行
	 * */
	private ExecutorService executor = Executors.newFixedThreadPool(10); 
	/*
	 * 验证码缓存,单例
	 */
	private Cache<String,String> codeCache = VerifyCodeCache.getCodeCache();
	@ResponseBody
	@RequestMapping("")
	public String sendEmail(String email){
		...
		if(!CheckData.checkEmail(email)) {
			resMessage.setAll(StatusCode.send_fail,"邮箱错误");
			...
		}
		StringBuilder builder = new StringBuilder();
		Random random = new Random();
		for(int i = 0 ; i<8;i++) {
			builder.append(random.nextInt(9));
		}
		Future<Boolean> future = executor.submit(new SEmail(email,builder.toString()));
		try {
			//等待30秒,未执行完成,抛出中断异常
			future.get(30, TimeUnit.SECONDS);
			//放入对应邮箱以及验证码
			codeCache.put(email, builder.toString());
			...
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.getStackTrace();
		} catch (ExecutionException e) {
			// TODO Auto-generated catch block
			e.getStackTrace();
		} catch (TimeoutException e) {
			// TODO Auto-generated catch block
			e.getStackTrace();
		}
		...
	}

token 生成

此处用的是Java自带的加密模式,以及自己的加密密钥
注意,UTF-8byteString 相互转换会不一样,因为无法表示,因此,使用的是ISO-8859-1

/*
*密钥
*/
 private final static Key SECRET_KEY = new SecretKeySpec("密钥内容".getBytes(),"AES");
	/*
	 * 生成key
	 * */
	public static String createToken(String uuid) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException {
		//获取当前时间
		long currentTimeMillis = System.currentTimeMillis();
		/*token中即为加密信息,可以自己随意设置
		 *此处为了方便,用的是uuid+有效时间
		 *TIME_OUT:为有时长,后通过比较,即可判断是否过期
		 */
		String token = uuid + ":"+(currentTimeMillis + TIME_OUT);
	    Cipher cipher = Cipher.getInstance("AES");
	    cipher.init(Cipher.ENCRYPT_MODE, SECRET_KEY);
	    return new String(cipher.doFinal(token.getBytes()),"ISO-8859-1");
	}
	/*
	 * 还原
	 * */
    public static String transferToken(String token) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException{
    	Cipher cipher = Cipher.getInstance("AES");
	    cipher.init(Cipher.DECRYPT_MODE, SECRET_KEY);
	    byte[] newData = cipher.doFinal(token.getBytes("ISO-8859-1"));
	    String res = new String(newData);
		return res;
    }
  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-05-10 12:02:43  更:2022-05-10 12:04:00 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 1:33:52-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码