Bladeren bron

资料系统

plf 4 jaren geleden
bovenliggende
commit
a685e0a84b

+ 27 - 0
pom.xml

@@ -106,6 +106,33 @@
             <version>1.2.6</version>
         </dependency>
 
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>servlet-api</artifactId>
+            <version>2.5</version>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>commons-codec</groupId>
+            <artifactId>commons-codec</artifactId>
+            <version>${commons-codec.version}</version>
+        </dependency>
+
+        <!--手机短信-->
+        <dependency>
+            <groupId>caimei</groupId>
+            <artifactId>smsClient</artifactId>
+            <version>1.0</version>
+        </dependency>
+
+        <!--对象存储oss-->
+        <dependency>
+            <groupId>com.aliyun.oss</groupId>
+            <artifactId>aliyun-sdk-oss</artifactId>
+            <version>3.10.2</version>
+        </dependency>
+
     </dependencies>
 
 

+ 76 - 0
src/main/java/com/caimei/www/controller/authorized/document/DocumentAuthController.java

@@ -0,0 +1,76 @@
+package com.caimei.www.controller.authorized.document;
+
+import com.caimei.www.pojo.JsonModel;
+import com.caimei.www.service.page.DocumentAuthService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.util.StringUtils;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * Description
+ *
+ * @author : plf
+ * @date : 2020/11/10
+ */
+@RestController
+@RequestMapping("/document")
+public class DocumentAuthController {
+
+    private DocumentAuthService documentAuthService;
+
+    @Autowired
+    public void setDocumentAuthService(DocumentAuthService documentAuthService) {
+        this.documentAuthService = documentAuthService;
+    }
+
+    /**
+     * 获取cookie数据,判断是否登录
+     */
+    @GetMapping("authorization")
+    public JsonModel getAuthorizationCookie() {
+        return documentAuthService.getAuthorizationCookie();
+
+    }
+
+    /**
+     * 获取图形验证码
+     */
+    @GetMapping("/getImgVerifyCode")
+    public JsonModel getImgVerifyCode() {
+        return documentAuthService.getImgVerifyCode();
+    }
+
+    /**
+     * oss短信登录,发送短信验证
+     */
+    @PostMapping("/note")
+    public JsonModel ossNote(String mobile, String imgCode, String token) {
+        if (StringUtils.isEmpty(mobile) || StringUtils.isEmpty(imgCode) || StringUtils.isEmpty(token)) {
+            return JsonModel.error("参数异常");
+        }
+        return documentAuthService.ossNote(mobile, imgCode, token);
+    }
+
+    /**
+     * oss手机短信验证码登录
+     */
+    @PostMapping("/mobileCodeLogin")
+    public JsonModel mobileCodeLogin(String mobile, String code) {
+        if (StringUtils.isEmpty(mobile) || StringUtils.isEmpty(code)) {
+            return JsonModel.error("参数异常");
+        }
+        return documentAuthService.mobileCodeLogin(mobile, code);
+    }
+
+    /**
+     * 资料列表
+     */
+    @GetMapping("/dataList")
+    public JsonModel dataList(String name, Integer pageNum, Integer pageSize) {
+        return documentAuthService.dataList(name, pageNum, pageSize);
+    }
+
+}

+ 42 - 0
src/main/java/com/caimei/www/mapper/DocumentAuthDao.java

@@ -0,0 +1,42 @@
+package com.caimei.www.mapper;
+
+import com.caimei.www.pojo.document.OssArchive;
+import com.caimei.www.pojo.document.OssArchivePdf;
+import com.caimei.www.pojo.document.OssAuthorization;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+/**
+ * Description
+ *
+ * @author : plf
+ * @date : 2020/11/10
+ */
+@Mapper
+public interface DocumentAuthDao {
+
+    /**
+     * 判断手机号是否有权限
+     *
+     * @param mobile
+     * @return
+     */
+    OssAuthorization findOssAuthorizationByMobile(String mobile);
+
+    /**
+     * 查询资料列表
+     *
+     * @param name 商品名称,资料库名称,资料名称
+     * @return
+     */
+    List<OssArchive> findOssArchive(String name);
+
+    /**
+     * 查询该资料库下的所有文件
+     *
+     * @param archiveId 资料库id
+     * @return
+     */
+    List<OssArchivePdf> findOssArchivePdf(Integer archiveId);
+}

+ 53 - 0
src/main/java/com/caimei/www/pojo/document/OssArchive.java

@@ -0,0 +1,53 @@
+package com.caimei.www.pojo.document;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * Description
+ *
+ * @author : plf
+ * @date : 2020/11/11
+ */
+@Data
+public class OssArchive implements Serializable {
+    private Integer id;
+
+    /**
+     * 资料库名称
+     */
+    private String name;
+
+    /**
+     * 对应商品表id
+     */
+    private Integer productId;
+
+    /**
+     * 添加时间
+     */
+    private Date addTime;
+
+    /**
+     * 商品主图
+     */
+    private String mainImage;
+
+    /**
+     * 商品名称
+     */
+    private String productName;
+
+    /**
+     * 供应商名称
+     */
+    private String shopName;
+
+    /**
+     * 资料库下PDF文件
+     */
+    private List<OssArchivePdf> pdfList;
+}

+ 52 - 0
src/main/java/com/caimei/www/pojo/document/OssArchivePdf.java

@@ -0,0 +1,52 @@
+package com.caimei.www.pojo.document;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * Description
+ *
+ * @author : plf
+ * @date : 2020/11/11
+ */
+@Data
+public class OssArchivePdf implements Serializable {
+    private Integer id;
+
+    /**
+     * 对应cm_oss_archive表id
+     */
+    private Integer archiveId;
+
+    /**
+     * 对应product表id
+     */
+    private Integer productId;
+
+    /**
+     * 资料名称
+     */
+    private String name;
+
+    /**
+     * oss存储名
+     */
+    private String ossName;
+
+    /**
+     * 文件唯一标识
+     */
+    private String md5Hex;
+
+    /**
+     * 上传时间
+     */
+    private Date uploadTime;
+
+    /**
+     * 访问pdf链接
+     */
+    private String url;
+}

+ 32 - 0
src/main/java/com/caimei/www/pojo/document/OssAuthorization.java

@@ -0,0 +1,32 @@
+package com.caimei.www.pojo.document;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * Description
+ *
+ * @author : plf
+ * @date : 2020/11/10
+ */
+@Data
+public class OssAuthorization implements Serializable {
+    private Integer id;
+
+    /**
+     * 姓名
+     */
+    private String name;
+
+    /**
+     * 手机号码
+     */
+    private String mobile;
+
+    /**
+     * 授权时间
+     */
+    private Date addTime;
+}

+ 51 - 0
src/main/java/com/caimei/www/service/page/DocumentAuthService.java

@@ -0,0 +1,51 @@
+package com.caimei.www.service.page;
+
+import com.caimei.www.pojo.JsonModel;
+
+/**
+ * Description
+ *
+ * @author : plf
+ * @date : 2020/11/10
+ */
+public interface DocumentAuthService {
+
+    /**
+     * 获取cookie数据,判断是否登录
+     */
+    JsonModel getAuthorizationCookie();
+
+    /**
+     * 获取图形验证码
+     */
+    JsonModel getImgVerifyCode();
+
+    /**
+     * oss短信登录,发送短信验证
+     *
+     * @param mobile  手机号
+     * @param imgCode 图形验证码
+     * @param token   图形token
+     * @return
+     */
+    JsonModel ossNote(String mobile, String imgCode, String token);
+
+    /**
+     * oss手机短信验证码登录
+     *
+     * @param mobile 手机号
+     * @param code   验证码
+     * @return
+     */
+    JsonModel mobileCodeLogin(String mobile, String code);
+
+    /**
+     * 资料列表
+     *
+     * @param name     商品名称,资料库名称,资料名称
+     * @param pageNum  分页参数
+     * @param pageSize 分页参数
+     * @return
+     */
+    JsonModel dataList(String name, Integer pageNum, Integer pageSize);
+}

+ 163 - 0
src/main/java/com/caimei/www/service/page/impl/DocumentAuthServiceImpl.java

@@ -0,0 +1,163 @@
+package com.caimei.www.service.page.impl;
+
+import com.aliyun.oss.OSS;
+import com.aliyun.oss.OSSClientBuilder;
+import com.caimei.www.mapper.DocumentAuthDao;
+import com.caimei.www.pojo.JsonModel;
+import com.caimei.www.pojo.document.OssArchive;
+import com.caimei.www.pojo.document.OssArchivePdf;
+import com.caimei.www.pojo.document.OssAuthorization;
+import com.caimei.www.service.page.DocumentAuthService;
+import com.caimei.www.service.redis.RedisService;
+import com.caimei.www.utils.RandomCodeGenerator;
+import com.caimei.www.utils.SMSUtils;
+import com.caimei.www.utils.VerifyCodeUtils;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import javax.annotation.Resource;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Description
+ *
+ * @author : plf
+ * @date : 2020/11/10
+ */
+@Slf4j
+@Service
+public class DocumentAuthServiceImpl implements DocumentAuthService {
+    @Resource
+    private DocumentAuthDao documentAuthDao;
+
+    @Resource
+    private RedisService redisService;
+
+    @Override
+    public JsonModel getAuthorizationCookie() {
+        String authorizationMobile = null;
+        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+        Cookie[] cookies = request.getCookies();
+        if (cookies != null && cookies.length > 0) {
+            for (Cookie cookie : cookies) {
+                if ("authorizationMobile".equals(cookie.getName())) {
+                    authorizationMobile = cookie.getValue();
+                }
+            }
+        }
+        if (!StringUtils.isEmpty(authorizationMobile)) {
+            OssAuthorization ossAuthorization = documentAuthDao.findOssAuthorizationByMobile(authorizationMobile);
+            if (ossAuthorization != null) {
+                return JsonModel.success(ossAuthorization);
+            }
+        }
+        return JsonModel.error();
+    }
+
+    @Override
+    public JsonModel getImgVerifyCode() {
+        Map<String, Object> jsonResult = new HashMap<>(2);
+        try {
+            VerifyCodeUtils.VerifyCode verifyCode = null;
+            String verifyCodeKey = "";
+            while (true) {
+                verifyCode = VerifyCodeUtils.createVerifyCode(200, 80, 4);
+                verifyCodeKey = "www:oss:" + verifyCode.getMd5Code();
+                boolean exists = redisService.exists(verifyCodeKey);
+                // 不存在,为了防止重复的图片验证码
+                if (!exists) {
+                    // 保存5分钟
+                    redisService.set(verifyCodeKey, verifyCode.getCode(), 5 * 60L);
+                    break;
+                }
+            }
+            jsonResult.put("baseImage", verifyCode.getBase64Image());
+            jsonResult.put("token", verifyCode.getMd5Code());
+            return JsonModel.success(jsonResult);
+        } catch (Exception e) {
+            return JsonModel.error("验证码获取失败");
+        }
+    }
+
+    @Override
+    public JsonModel ossNote(String mobile, String imgCode, String token) {
+        String code = (String) redisService.get("www:oss:" + token);
+        String mobileCode = RandomCodeGenerator.generateCodeInt(6);
+        //手机验证码,30分钟有效
+        redisService.set(mobile + ":mobileCode", mobileCode, 30 * 60L);
+        String content = "采美资料库访问授权验证码:" + mobileCode + ",30分钟内有效";
+        log.info("采美资料库访问授权验证码>>>>>" + mobileCode);
+        if (!StringUtils.isEmpty(code) && code.equals(imgCode)) {
+            boolean sms = SMSUtils.sendSms(mobile, content);
+            if (sms) {
+                return JsonModel.success();
+            }
+        } else {
+            boolean exists = redisService.exists(mobile + ":mobileCode");
+            if (exists) {
+                redisService.remove(mobile + ":mobileCode");
+            }
+        }
+        return JsonModel.error("验证码不正确");
+    }
+
+    @Override
+    public JsonModel mobileCodeLogin(String mobile, String code) {
+        String mobileCode = (String) redisService.get(mobile + ":mobileCode");
+        if (!StringUtils.isEmpty(mobileCode) && code.equals(mobileCode)) {
+            OssAuthorization ossAuthorization = documentAuthDao.findOssAuthorizationByMobile(mobile);
+            if (ossAuthorization != null) {
+                Cookie authorizationMobile = new Cookie("authorizationMobile", mobile);
+                authorizationMobile.setMaxAge(60 * 60 * 24 * 30);
+                HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
+                response.addCookie(authorizationMobile);
+                return JsonModel.success();
+            } else {
+                return JsonModel.error(-2, "登录失败");
+            }
+        } else {
+            return JsonModel.error("短信验证码不正确");
+        }
+    }
+
+    @Override
+    public JsonModel dataList(String name, Integer pageNum, Integer pageSize) {
+        String endpoint = "https://oss-cn-shenzhen.aliyuncs.com";
+        String accessKeyId = "LTAI4GBL3o4YkWnbKYgf2Xia";
+        String accessKeySecret = "dBjAXqbYiEPP6Ukuk2ZsXQeET7FVkK";
+        String bucketName = "caimei-oss";
+        pageNum = pageNum == null ? 1 : pageNum;
+        pageSize = pageSize == null ? 20 : pageSize;
+        PageHelper.startPage(pageNum, pageSize);
+        List<OssArchive> ossArchiveList = documentAuthDao.findOssArchive(name);
+        PageInfo<OssArchive> pageInfo = null;
+        if (ossArchiveList != null && ossArchiveList.size() > 0) {
+            OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
+            // 设置URL过期时间为1个小时
+            Date expiration = new Date(System.currentTimeMillis() + 3600L * 1000);
+            for (OssArchive ossArchive : ossArchiveList) {
+                List<OssArchivePdf> pdfList = documentAuthDao.findOssArchivePdf(ossArchive.getId());
+                if (pdfList != null && pdfList.size() > 0) {
+                    for (OssArchivePdf pdf : pdfList) {
+                        String url = ossClient.generatePresignedUrl(bucketName, pdf.getOssName(), expiration).toString();
+                        pdf.setUrl(url);
+                    }
+                }
+            }
+            pageInfo = new PageInfo<>(ossArchiveList);
+            ossClient.shutdown();
+        }
+        return JsonModel.success(pageInfo);
+    }
+}

+ 90 - 0
src/main/java/com/caimei/www/utils/Md5Util.java

@@ -0,0 +1,90 @@
+package com.caimei.www.utils;
+
+import java.security.MessageDigest;
+import java.util.UUID;
+
+/**
+ * md5加密工具类
+ *
+ * @author : Charles
+ * @date : 2020/1/17
+ */
+public class Md5Util {
+    /**
+     * md5加密
+     *
+     * @param s:待加密字符串
+     * @return 加密后16进制字符串
+     */
+    public static String md5(String s) {
+        try {
+            //实例化MessageDigest的MD5算法对象
+            MessageDigest md = MessageDigest.getInstance("MD5");
+            //通过digest方法返回哈希计算后的字节数组
+            byte[] bytes = md.digest(s.getBytes("utf-8"));
+            //将字节数组转换为16进制字符串并返回
+            return toHex(bytes);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * 获取随即盐
+     *
+     * @return
+     */
+    public static String salt() {
+        //利用UUID生成随机盐
+        UUID uuid = UUID.randomUUID();
+        //返回a2c64597-232f-4782-ab2d-9dfeb9d76932
+        String[] arr = uuid.toString().split("-");
+        return arr[0];
+    }
+
+    /**
+     * 字节数组转换为16进制字符串
+     *
+     * @return 16进制字符串
+     */
+    private static String toHex(byte[] bytes) {
+        final char[] HEX_DIGITS = "0123456789ABCDEF".toCharArray();
+        StringBuilder ret = new StringBuilder(bytes.length * 2);
+        for (int i = 0; i < bytes.length; i++) {
+            ret.append(HEX_DIGITS[(bytes[i] >> 4) & 0x0f]);
+            ret.append(HEX_DIGITS[bytes[i] & 0x0f]);
+        }
+        return ret.toString();
+    }
+
+    /**
+     * <p>Description: 16位的MD5值</p>
+     * <p>Company: caimei365</p>
+     *
+     * @param s
+     * @return
+     * @throws Exception
+     * @author dmeng
+     * @date 2015年12月17日 下午5:28:49
+     */
+    public static String MD5To16Bit(String s) throws Exception {
+        MessageDigest md = MessageDigest.getInstance("MD5");
+        md.update(s.getBytes());
+        byte b[] = md.digest();
+        int i;
+        StringBuffer buf = new StringBuffer("");
+        for (int offset = 0; offset < b.length; offset++) {
+            i = b[offset];
+            if (i < 0) {
+                i += 256;
+            }
+            if (i < 16) {
+                buf.append("0");
+            }
+            buf.append(Integer.toHexString(i));
+        }
+        return buf.toString().substring(8, 24);
+    }
+
+}
+

+ 89 - 0
src/main/java/com/caimei/www/utils/RandomCodeGenerator.java

@@ -0,0 +1,89 @@
+package com.caimei.www.utils;
+
+import java.util.Random;
+
+public class RandomCodeGenerator {
+
+    // TODO 与WWW的RandomCodeGenerator是重复的,后续需要删除www的RandomCodeGenerator
+    private static char codeSequence[] = {
+            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K',
+            'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
+            'W', 'X', 'Y', 'Z', '2', '3', '4', '5', '6', '7',
+            '8', '9'
+    };
+
+    private static char intSequence[] = {
+            '2', '3', '4', '5', '6', '7',
+            '8', '9'
+    };
+
+    private static char stringSequence[] = {
+            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K',
+            'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
+            'W', 'X', 'Y', 'Z'
+    };
+
+    private static char newStringSequence[] = {
+            'A', 'a', 'B', 'b', 'D', 'd', 'E', 'e', 'F', 'f', 'G', 'g', 'H', 'h',
+            'L', 'N', 'n', 'Q', 'q', 'R', 'r', 'T', 't', 'Y', 'y'
+    };
+//	C,i,j,k,M,O,P,S,U,V,W,X,Z,l
+
+    public static String generateCode(int length) {
+        StringBuffer sb = new StringBuffer();
+        Random random = new Random();
+        for (int i = 0; i < codeSequence.length && i < length; ++i) {
+            sb.append(codeSequence[random.nextInt(codeSequence.length)]);
+        }
+
+        return sb.toString();
+    }
+
+    public static String generateCodeInt(int length) {
+        StringBuffer sb = new StringBuffer();
+        Random random = new Random();
+        for (int i = 0; i < intSequence.length && i < length; ++i) {
+            sb.append(intSequence[random.nextInt(intSequence.length)]);
+        }
+
+        return sb.toString();
+    }
+
+    public static String generateCodeString(int length) {
+        StringBuffer sb = new StringBuffer();
+        Random random = new Random();
+        for (int i = 0; i < stringSequence.length && i < length; ++i) {
+            sb.append(stringSequence[random.nextInt(stringSequence.length)]);
+        }
+
+        return sb.toString();
+    }
+
+
+    public static String getRandomCharAndNumr(int length) {
+        String val = "";
+        Random random = new Random();
+        for (int i = 0; i < length; i++) {
+            // 输出字母还是数字
+            String charOrNum = random.nextInt(2) % 2 == 0 ? "char" : "num";
+            // 字符串
+            if ("char".equalsIgnoreCase(charOrNum)) {
+                // 取得大写字母还是小写字母
+                int choice = random.nextInt(2) % 2 == 0 ? 65 : 97;
+                val += (char) (choice + random.nextInt(26));
+            } else if ("num".equalsIgnoreCase(charOrNum)) { // 数字
+                val += String.valueOf(random.nextInt(10));
+            }
+        }
+        return val;
+    }
+
+    public static String generateAccount(int length) {
+        StringBuffer sb = new StringBuffer();
+        Random random = new Random();
+        for (int i = 0; i < newStringSequence.length && i < length; ++i) {
+            sb.append(newStringSequence[random.nextInt(newStringSequence.length)]);
+        }
+        return sb.toString();
+    }
+}

+ 19 - 0
src/main/java/com/caimei/www/utils/SMSUtils.java

@@ -0,0 +1,19 @@
+package com.caimei.www.utils;
+
+import com.ruanwei.interfacej.SmsClientSend;
+
+public class SMSUtils {
+    private static String url = "http://47.96.109.82:9999/sms.aspx";
+    private static String userid = "321";
+    private static String account = "0755cmxx";
+    private static String password = "CaimeiSMS999";
+
+    public static boolean sendSms(String mobile, String content) {
+        String res = SmsClientSend.sendSms(url, userid, account, password, mobile, content);
+        return res.indexOf("Success") != -1;
+    }
+
+    public static void main(String[] args) {
+        System.out.println(sendSms("13631650502", "您登录亲朋棋牌的手机短 信验证码是:7895,祝您游戏愉快!请确认账号是由本人操作"));
+    }
+}

+ 354 - 0
src/main/java/com/caimei/www/utils/VerifyCodeUtils.java

@@ -0,0 +1,354 @@
+package com.caimei.www.utils;
+
+import org.apache.commons.codec.binary.Base64;
+
+import javax.imageio.ImageIO;
+import java.awt.*;
+import java.awt.geom.AffineTransform;
+import java.awt.image.BufferedImage;
+import java.io.*;
+import java.util.Arrays;
+import java.util.Random;
+
+/**
+ * <p>Description: Copyright © 2014-2015 CAIMEI365.com All Rights Reserved</p>
+ *
+ * @author xun.zhang
+ * @date 2016年5月25日 上午10:18:35
+ */
+
+public class VerifyCodeUtils {
+
+    // 使用到Algerian字体,系统里没有的话需要安装字体,字体只显示大写,去掉了1,0,i,o几个容易混淆的字符
+    public static final String VERIFY_CODES = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ";
+    private static Random random = new Random();
+
+    /**
+     * <p>Description: </p>
+     * <p>Company: caimei365</p>
+     *
+     * @param w          验证码图片宽度
+     * @param h          验证码图片高度
+     * @param verifySize 验证码图片里面字符串位数
+     * @return
+     * @throws IOException
+     * @author xun.zhang
+     * @date 2016年5月25日 上午11:39:46
+     */
+    public static VerifyCode createVerifyCode(int w, int h, int verifySize) throws IOException {
+        String code = generateVerifyCode(verifySize);
+        ByteArrayOutputStream outPutStream = new ByteArrayOutputStream();
+        outputImage(w, h, outPutStream, code);
+
+        InputStream in = new ByteArrayInputStream(outPutStream.toByteArray());
+        byte[] data = null;
+        // 读取图片字节数组
+        try {
+            data = new byte[in.available()];
+            in.read(data);
+            in.close();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        // 对字节数组Base64编码
+        String base64 = Base64.encodeBase64String(data);
+
+        VerifyCode verifyCode = new VerifyCode(code, "data:image/jpg;base64," + base64);
+
+        return verifyCode;
+    }
+
+    /**
+     * 使用系统默认字符源生成验证码
+     *
+     * @param verifySize 验证码长度
+     * @return
+     */
+    public static String generateVerifyCode(int verifySize) {
+        return generateVerifyCode(verifySize, VERIFY_CODES);
+    }
+
+    /**
+     * 使用指定源生成验证码
+     *
+     * @param verifySize 验证码长度
+     * @param sources    验证码字符源
+     * @return
+     */
+    public static String generateVerifyCode(int verifySize, String sources) {
+        if (sources == null || sources.length() == 0) {
+            sources = VERIFY_CODES;
+        }
+        int codesLen = sources.length();
+        Random rand = new Random(System.currentTimeMillis());
+        StringBuilder verifyCode = new StringBuilder(verifySize);
+        for (int i = 0; i < verifySize; i++) {
+            verifyCode.append(sources.charAt(rand.nextInt(codesLen - 1)));
+        }
+        return verifyCode.toString();
+    }
+
+    /**
+     * 生成随机验证码文件,并返回验证码值
+     *
+     * @param w
+     * @param h
+     * @param outputFile
+     * @param verifySize
+     * @return
+     * @throws IOException
+     */
+    public static String outputVerifyImage(int w, int h, File outputFile, int verifySize) throws IOException {
+        String verifyCode = generateVerifyCode(verifySize);
+        outputImage(w, h, outputFile, verifyCode);
+        return verifyCode;
+    }
+
+    /**
+     * 输出随机验证码图片流,并返回验证码值
+     *
+     * @param w
+     * @param h
+     * @param os
+     * @param verifySize
+     * @return
+     * @throws IOException
+     */
+    public static String outputVerifyImage(int w, int h, OutputStream os, int verifySize) throws IOException {
+        String verifyCode = generateVerifyCode(verifySize);
+        outputImage(w, h, os, verifyCode);
+        return verifyCode;
+    }
+
+    /**
+     * 生成指定验证码图像文件
+     *
+     * @param w
+     * @param h
+     * @param outputFile
+     * @param code
+     * @throws IOException
+     */
+    public static void outputImage(int w, int h, File outputFile, String code) throws IOException {
+        if (outputFile == null) {
+            return;
+        }
+        File dir = outputFile.getParentFile();
+        if (!dir.exists()) {
+            dir.mkdirs();
+        }
+        try {
+            outputFile.createNewFile();
+            FileOutputStream fos = new FileOutputStream(outputFile);
+            outputImage(w, h, fos, code);
+            fos.close();
+        } catch (IOException e) {
+            throw e;
+        }
+    }
+
+    /**
+     * 输出指定验证码图片流
+     *
+     * @param w
+     * @param h
+     * @param os
+     * @param code
+     * @throws IOException
+     */
+    public static void outputImage(int w, int h, OutputStream os, String code) throws IOException {
+        int verifySize = code.length();
+        BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
+        Random rand = new Random();
+        Graphics2D g2 = image.createGraphics();
+        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+        Color[] colors = new Color[5];
+        Color[] colorSpaces = new Color[]{Color.WHITE, Color.CYAN, Color.GRAY, Color.LIGHT_GRAY, Color.MAGENTA,
+                Color.ORANGE, Color.PINK, Color.YELLOW};
+        float[] fractions = new float[colors.length];
+        for (int i = 0; i < colors.length; i++) {
+            colors[i] = colorSpaces[rand.nextInt(colorSpaces.length)];
+            fractions[i] = rand.nextFloat();
+        }
+        Arrays.sort(fractions);
+
+        g2.setColor(Color.GRAY);// 设置边框色
+        g2.fillRect(0, 0, w, h);
+
+        Color c = getRandColor(200, 250);
+        g2.setColor(c);// 设置背景色
+        g2.fillRect(0, 2, w, h - 4);
+
+        // 绘制干扰线
+        Random random = new Random();
+        g2.setColor(getRandColor(160, 200));// 设置线条的颜色
+        for (int i = 0; i < 20; i++) {
+            int x = random.nextInt(w - 1);
+            int y = random.nextInt(h - 1);
+            int xl = random.nextInt(6) + 1;
+            int yl = random.nextInt(12) + 1;
+            g2.drawLine(x, y, x + xl + 40, y + yl + 20);
+        }
+
+        // 添加噪点
+        float yawpRate = 0.05f;// 噪声率
+        int area = (int) (yawpRate * w * h);
+        for (int i = 0; i < area; i++) {
+            int x = random.nextInt(w);
+            int y = random.nextInt(h);
+            int rgb = getRandomIntColor();
+            image.setRGB(x, y, rgb);
+        }
+
+        shear(g2, w, h, c);// 使图片扭曲
+
+        g2.setColor(getRandColor(100, 160));
+        int fontSize = h - 4;
+        Font font = new Font("Algerian", Font.ITALIC, fontSize);
+        g2.setFont(font);
+        char[] chars = code.toCharArray();
+        for (int i = 0; i < verifySize; i++) {
+            AffineTransform affine = new AffineTransform();
+            affine.setToRotation(Math.PI / 4 * rand.nextDouble() * (rand.nextBoolean() ? 1 : -1),
+                    (w / verifySize) * i + fontSize / 2, h / 2);
+            g2.setTransform(affine);
+            g2.drawChars(chars, i, 1, ((w - 10) / verifySize) * i + 5, h / 2 + fontSize / 2 - 10);
+        }
+
+        g2.dispose();
+        ImageIO.write(image, "jpg", os);
+    }
+
+    private static Color getRandColor(int fc, int bc) {
+        if (fc > 255) {
+            fc = 255;
+        }
+        if (bc > 255) {
+            bc = 255;
+        }
+        int r = fc + random.nextInt(bc - fc);
+        int g = fc + random.nextInt(bc - fc);
+        int b = fc + random.nextInt(bc - fc);
+        return new Color(r, g, b);
+    }
+
+    private static int getRandomIntColor() {
+        int[] rgb = getRandomRgb();
+        int color = 0;
+        for (int c : rgb) {
+            color = color << 8;
+            color = color | c;
+        }
+        return color;
+    }
+
+    private static int[] getRandomRgb() {
+        int[] rgb = new int[3];
+        for (int i = 0; i < 3; i++) {
+            rgb[i] = random.nextInt(255);
+        }
+        return rgb;
+    }
+
+    private static void shear(Graphics g, int w1, int h1, Color color) {
+        shearX(g, w1, h1, color);
+        shearY(g, w1, h1, color);
+    }
+
+    private static void shearX(Graphics g, int w1, int h1, Color color) {
+
+        int period = random.nextInt(2);
+
+        boolean borderGap = true;
+        int frames = 1;
+        int phase = random.nextInt(2);
+
+        for (int i = 0; i < h1; i++) {
+            double d = (double) (period >> 1)
+                    * Math.sin((double) i / (double) period + (6.2831853071795862D * (double) phase) / (double) frames);
+            g.copyArea(0, i, w1, 1, (int) d, 0);
+            if (borderGap) {
+                g.setColor(color);
+                g.drawLine((int) d, i, 0, i);
+                g.drawLine((int) d + w1, i, w1, i);
+            }
+        }
+
+    }
+
+    private static void shearY(Graphics g, int w1, int h1, Color color) {
+
+        int period = random.nextInt(40) + 10; // 50;
+
+        boolean borderGap = true;
+        int frames = 20;
+        int phase = 7;
+        for (int i = 0; i < w1; i++) {
+            double d = (double) (period >> 1)
+                    * Math.sin((double) i / (double) period + (6.2831853071795862D * (double) phase) / (double) frames);
+            g.copyArea(i, 0, 1, h1, 0, (int) d);
+            if (borderGap) {
+                g.setColor(color);
+                g.drawLine(i, (int) d, i, 0);
+                g.drawLine(i, (int) d + h1, i, h1);
+            }
+
+        }
+
+    }
+
+    public static class VerifyCode {
+        /**
+         * 生成的字符串验证码
+         */
+        private String code;
+        /**
+         * 验证码字符串的加密
+         */
+        private String md5Code;
+        /**
+         * 验证码生成的图片(base64格式)
+         */
+        private String base64Image;
+
+        public VerifyCode(String code, String base64Image) {
+            this.code = code;
+            this.base64Image = base64Image;
+        }
+
+        public String getCode() {
+            return code;
+        }
+
+        public void setCode(String code) {
+            this.code = code;
+        }
+
+        public String getMd5Code() throws Exception {
+            if (this.code != null) {
+                md5Code = code;
+                for (int i = 0; i < 3; i++) {
+                    md5Code = Md5Util.MD5To16Bit(md5Code);
+                }
+            }
+            return md5Code;
+        }
+
+        public String getBase64Image() {
+            return base64Image;
+        }
+
+        public void setBase64Image(String base64Image) {
+            this.base64Image = base64Image;
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+
+        VerifyCode verifyCode = createVerifyCode(200, 80, 4);
+        System.out.println(verifyCode.getCode());
+        System.out.println(verifyCode.getMd5Code());
+        System.out.println(verifyCode.getBase64Image());
+    }
+
+}

+ 33 - 0
src/main/resources/mapper/DocumentAuthMapper.xml

@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.caimei.www.mapper.DocumentAuthDao">
+    <select id="findOssAuthorizationByMobile" resultType="com.caimei.www.pojo.document.OssAuthorization">
+        SELECT * FROM cm_oss_authorization WHERE mobile = #{mobile}
+    </select>
+
+    <select id="findOssArchive" resultType="com.caimei.www.pojo.document.OssArchive">
+        SELECT
+          coa.*,
+          p.name AS productName,
+          p.mainImage AS mainImage,
+          s.name AS shopName
+        FROM
+          cm_oss_archive coa
+          LEFT JOIN product p ON coa.productId = p.productID
+          LEFT JOIN shop s ON p.shopID = s.shopID
+          <if test="name != null and name != ''">
+              WHERE (coa.name LIKE CONCAT('%',#{name},'%')
+               OR p.name LIKE CONCAT('%',#{name},'%')
+               OR s.name LIKE CONCAT('%',#{name},'%'))
+          </if>
+        ORDER BY
+          coa.updateDate DESC
+    </select>
+
+    <select id="findOssArchivePdf" resultType="com.caimei.www.pojo.document.OssArchivePdf">
+        SELECT * FROM cm_oss_archive_pdf WHERE archiveId = #{archiveId} ORDER BY uploadTime DESC
+    </select>
+
+</mapper>