发表于: 2019-12-05 23:44:02
1 1158
今天完成的事:
1、使用SendCloud邮箱验证。
将邮箱接口的基本参数纳入spring管理。
工具类(构造方法注入):
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
public class SendMailUtil {
private static Logger logger = Logger.getLogger(SendMailUtil.class);
private String url;
private String apiKey;
private String apiUser;
private JedisUtil jedisUtil = new JedisUtil();
public SendMailUtil(String url, String apiKey, String apiUser) {
this.url = url;
this.apiKey = apiKey;
this.apiUser = apiUser;
}
public boolean sendMailCode(String mail) {
// 随机4位验证码
int code = (int) ((Math.random() * 8999) + 1000);
// DefaultHttpClient()已过时,替换如下
HttpClient httpclient = HttpClientBuilder.create().build();
HttpPost httpost = new HttpPost(url);
List params = new ArrayList();
// 您需要登录SendCloud创建API_USER,使用API_USER和API_KEY才可以进行邮件的发送。
params.add(new BasicNameValuePair("apiUser", apiUser));
params.add(new BasicNameValuePair("apiKey", apiKey));
// 发件人地址,为了更高的送达率,建议from域名后缀与发信域名一致。
params.add(new BasicNameValuePair("from", "service@sendcloud.im"));
// 发件人名称
params.add(new BasicNameValuePair("fromName", ""));
// 收件人地址,多个地址使用';'分隔
params.add(new BasicNameValuePair("to", mail));
// 标题,不能为空
params.add(new BasicNameValuePair("subject", "来自jnshu的验证码!"));
// 邮件的内容,邮件格式为 text/html
params.add(new BasicNameValuePair("html", "您的验证码为:" + code + ",请及时注册。"));
try {
httpost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
// 请求
HttpResponse response = httpclient.execute(httpost);
// 处理响应
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { // 正常返回
// 将手机号为key,验证码为value,存储缓存,设置过期时间2分钟
String redis = jedisUtil.setex(mail,120,String.valueOf(code));
if("OK".equals(redis)){
logger.info("邮箱、验证码缓存成功");
}
logger.info("验证码:" + code);
// 读取xml文档
String result = EntityUtils.toString(response.getEntity());
logger.info("验证结果为:" + result);
return true;
} else {
logger.error("出现错误!error!");
}
} catch (UnsupportedEncodingException e) {
logger.error("出现异常1,异常为:" + e.getMessage());
} catch (ClientProtocolException e) {
logger.error("出现异常2,异常为:" + e.getMessage());
} catch (IOException e) {
logger.error("出现异常3,异常为:" + e.getMessage());
}
httpost.releaseConnection();
return false;
}
}
spring全局配置文件:
<!--发送邮件的初始化设置,有参构造注入属性 -->
<bean id="sendMailUtil" class="com.jnshu.util.SendMailUtil">
<constructor-arg name="apiKey" value="JgKQDmUpPcMpTfSL"></constructor-arg>
<constructor-arg name="apiUser" value="basketboy_test_BgIc4q"></constructor-arg>
<constructor-arg name="url" value="http://api.sendcloud.net/apiv2/mail/send"></constructor-arg>
</bean>
测试方法:
// 测试有参构造方法注入参数,纳入spring管理
@Autowired
private SendMailUtil sendMailUtil;
@Test
public void testSendMailUtil() {
String mail="zhangheng@jnshu.com";
boolean i = sendMailUtil.sendMailCode(mail);
if(i){
System.out.println("获取邮箱验证码成功");
}else {
System.out.println("获取邮箱验证码失败");
}
}
测试成功。
2、修改容联短信验证工具类。
因SDK的jar包没有纳入maven管理,所以tomcat运行时会报错无法找到jar包,所以这里修改工具类,调整为组装http请求,进行短信验证。
这里仅放工具类,参数注入和测试方法不变。
import com.alibaba.fastjson.JSONObject;
//import com.cloopen.rest.sdk.CCPRestSmsSDK;
import org.apache.log4j.Logger;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.util.DigestUtils;
import org.springframework.web.client.RestTemplate;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Date;
public class SMSUtil {
private static Logger logger = Logger.getLogger(SMSUtil.class);
private String serverIP;
private String serverPort;
private String accountSid;
private String accountToken;
private String appId;
private JedisUtil jedisUtil = new JedisUtil();
// set方法注入
public void setServerIP(String serverIP) {
this.serverIP = serverIP;
}
public void setServerPort(String serverPort) {
this.serverPort = serverPort;
}
public void setAccountSid(String accountSid) {
this.accountSid = accountSid;
}
public void setAccountToken(String accountToken) {
this.accountToken = accountToken;
}
public void setAppId(String appId) {
this.appId = appId;
}
public boolean sendTelCode(String tel) {
// 获取第三方要求格式的当前时间
SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
String date = df.format(new Date());
// 使用Base64编码(开发者主账号ACCOUNT SID + 冒号 + 时间戳)其中账户Id 根据url的验证级别对应主账户
String Authorization = accountSid + ":" + date;
// 随机四位验证码,直接 String.valueOf() 会有小数,不是整数
int code = (int) ((Math.random() * 8999) + 1000);
// 使用MD5加密(账户Id + 账户授权令牌 + 时间戳)
// 其中账户Id和账户授权令牌根据url的验证级别对应主账户,toUpperCase()将字母转为大写字母
String SigParameter = DigestUtils.md5DigestAsHex((accountSid +
accountToken + date).getBytes()).toUpperCase();
// 业务URL格式:/2013-12-26/Accounts/{accountSid}/SMS/TemplateSMS?sig={SigParameter}
String URL = "https://app.cloopen.com:8883/2013-12-26/Accounts/"+ accountSid +"/SMS/TemplateSMS?sig=";
//获取头消息
HttpHeaders headers = new HttpHeaders();
//设置请求头信息
headers.add("Accept", "application/json;charset=utf-8");
headers.add("Content-Type", "application/json;charset=utf-8");
headers.add("Authorization", Base64.getEncoder().encodeToString(Authorization.getBytes()));
//设置请求体信息
JSONObject msg = new JSONObject();
// 短信接收端手机号码集合,用英文逗号分开,每批发送的手机号数量不得超过200个
msg.put("to", tel);
// 应用Id,官网控制台应用列表获取
msg.put("appId", appId);
// 模板Id,官网控制台模板列表获取,测试模板id是1
// 测试模板的内容是:【云通讯】您使用的是云通讯短信模板,您的验证码是{1},请于{2}分钟内正确输入
msg.put("templateId", "1");
// 内容数据外层节点,模板如果没有变量,此参数可不传
msg.put("datas", new String[]{'\t' + Integer.toString(code), '\t' + "2"});
//组装并发送
HttpEntity<JSONObject> request = new HttpEntity<>(msg, headers);
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate.postForEntity(
URL + SigParameter, request, String.class);
logger.info("响应为:" + response.getStatusCode() + '\n' + response.getBody());
logger.info(String.valueOf(response.getStatusCode()) + '\n' + SigParameter);
// 请求状态码,取值000000(成功),返回验证码
if (response.getStatusCode().is2xxSuccessful() && response.getBody().contains("000000")) {
// 将手机号为key,验证码为value,存储缓存,设置过期时间2分钟
String result = jedisUtil.setex(tel, 120, String.valueOf(code));
if ("OK".equals(result)) {
logger.info("手机号、验证码缓存成功");
}
return true;
} else {
logger.info("验证码发送失败");
return false;
}
}
}
3、使用阿里云OSS上传文件。
首先,添加依赖。

将邮箱接口的基本参数纳入spring管理。
工具类(构造方法注入):
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import org.apache.log4j.Logger;
import org.springframework.web.multipart.MultipartFile;
import java.io.ByteArrayInputStream;
import java.util.UUID;
public class AliyunOSSUtil {
private static Logger logger = Logger.getLogger(AliyunOSSUtil.class);
private String endpoint;
private String accessKeyId;
private String accessKeySecret;
// Bucket用来管理所存储Object的存储空间,详细描述请参看“开发人员指南 > 基本概念 > OSS基本概念介绍”。
// Bucket命名规范如下:只能包括小写字母,数字和短横线(-),必须以小写字母或者数字开头,长度必须在3-63字节之间。
private static String bucketName = "jnshu-7012";
public AliyunOSSUtil(String endpoint, String accessKeyId, String accessKeySecret) {
this.endpoint = endpoint;
this.accessKeyId = accessKeyId;
this.accessKeySecret = accessKeySecret;
}
public String upPhoto(MultipartFile multipartFile){
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
// 使用 UUID 给图片重命名,并去掉四个“-”
String name = UUID.randomUUID().toString().replaceAll("-", "");
// 获取图片名称
String ext = multipartFile.getOriginalFilename();
// 获取图片的前缀名称 加 当前时间戳
// String prefix = ext.substring(0, ext.lastIndexOf(".")) + "_" + System.currentTimeMillis();
// 获取图片的后缀名称,含“.”
String suffix = ext.substring(ext.lastIndexOf("."));
String photoName = name + suffix ;
try {
// 判断Bucket是否存在。
if (ossClient.doesBucketExist(bucketName)) {
logger.info("您已经创建Bucket:" + bucketName + "。");
} else {
logger.info("您的Bucket不存在,创建Bucket:" + bucketName + "。");
// 创建Bucket。
ossClient.createBucket(bucketName);
}
// Object是OSS存储数据的基本单元,称为OSS的对象,也被称为OSS的文件。详细描述请参看“开发人员指南 > 基本概念 > OSS基本概念介绍”。
// Object命名规范如下:使用UTF-8编码,长度必须在1-1023字节之间,不能以“/”或者“\”字符开头。
// oss中没有文件夹的概念,如果想传到对应的目录下,可以在object名称前添加对应的路径。
String fileName = "minImage/" + photoName;
// 上传文件。<yourLocalFile>由本地文件路径加文件名包括后缀组成,例如/users/local/myfile.txt。
ossClient.putObject(bucketName,fileName,new ByteArrayInputStream(multipartFile.getBytes()));
// 关闭OSSClient。
ossClient.shutdown();
return "https://jnshu-7012.oss-cn-beijing.aliyuncs.com/" + fileName;
} catch (OSSException oe) {
logger.error("出现异常1,异常为:" + oe.getMessage());
} catch (ClientException ce) {
logger.error("出现异常2,异常为:" + ce.getMessage());
} catch (Exception e) {
logger.error("出现异常3,异常为:" + e.getMessage());
}
return null;
}
}
spring全局配置文件:
<!--阿里云OSS文件上传的初始化设置,有参构造注入属性 -->
<bean id="ossUtil" class="com.jnshu.util.AliyunOSSUtil">
<constructor-arg name="endpoint" value="http://oss-cn-beijing.aliyuncs.com"></constructor-arg>
<constructor-arg name="accessKeyId" value="LTAI4Fw68QGCDQCJEhkQBst8"></constructor-arg>
<constructor-arg name="accessKeySecret" value="Rm5Hc89aiA3fxJaMpAGUmUXn8VRm0b"></constructor-arg>
</bean>
这里因为oss中没有文件夹的概念,如果想传到对应的目录下,可以在object名称前添加对应的路径。代码如下。

可以查看oss中的object,也可以直接进管理页面查看。
4、添加验证接口。
controller:
@Autowired
private SMSUtil smsUtil;
@Autowired
private SendMailUtil sendMailUtil;
@Autowired
private AliyunOSSUtil aliyunOSSUtil;
// 获取手机验证码
@RequestMapping(value = "/getTelCode", method = RequestMethod.POST)
public String getTelCode(String tel){
Map<String,String> map = new HashMap();
boolean flag = smsUtil.sendTelCode(tel);
if(flag){
map.put("code","1");
map.put("message","获取手机验证码成功");
logger.info("获取手机验证码成功");
}else {
map.put("code","0");
map.put("message","获取手机验证码失败");
logger.info("获取手机验证码失败");
}
return "login";
}
// 获取邮箱验证码
@RequestMapping(value = "/getMailCode", method = RequestMethod.POST)
public String getMailCode(String mail) {
Map<String,String> map = new HashMap();
boolean flag = sendMailUtil.sendMailCode(mail);
if(flag){
map.put("code","1");
map.put("message","获取邮箱验证码成功");
logger.info("获取邮箱验证码成功");
}else {
map.put("code","0");
map.put("message","获取邮箱验证码失败");
logger.info("获取邮箱验证码失败");
}
return "login";
}
// 上传头像
@RequestMapping(value = "/upPhoto", method = RequestMethod.POST)
public String upPhoto(MultipartFile multipartFile) {
Map<String,Object> map = new HashMap();
String photoPath = aliyunOSSUtil.upPhoto(multipartFile);
if( photoPath !=null && !"".equals(photoPath)){
map.put("code","1");
map.put("message","上传头像成功");
map.put("data",photoPath);
logger.info("头像地址:" + photoPath);
logger.info("上传头像成功");
}else {
map.put("code","0");
map.put("message","上传头像码失败");
map.put("data",null);
logger.info("上传头像失败");
}
return "login";
}
jsp:太low了。。
<form action="upPhoto" name="user" method="post" enctype="multipart/form-data">
用户名:<input type="text" name="name" />
密码:<input type="password" name="password" />
头像:<input type="file" name="multipartFile" />
<input type="submit" value="上传头像">
</form><hr>
<form action="getTelCode" method="post">
手机号:<input type="text" name="tel" />
<input type="submit" value="获取验证码">
</form><hr>
<form action="getMailCode" method="post">
邮箱:<input type="text" name="mail" />
<input type="submit" value="获取验证码">
</form><hr>
其中,邮箱验证会出现警告,但是不影响运行。
将过时的client方法替换,但是还有测试类中使用不安全的操作,这个没有理会。

将过时的client方法替换如下。
明天计划的事:
1、使用maven命令打包容联sdk的jar包。
2、学习ajax,简单建立验证所需页面。
3、学习另一种第三方文件上传,实现图片迁移。
遇到的问题:
无
收获:
1、使用SendCloud邮箱验证。
2、修改容联短信验证工具类。
3、使用阿里云OSS上传文件。
4、添加验证接口,测试均成功。
评论