发表于: 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、添加验证接口,测试均成功。

返回列表 返回列表
评论

    分享到