1. 修改用户信息从threadLocal中获取

2. 把用户信息写入到cookie中
3. 下载的图片或者pdf添加水印
jinan_dev
xueqingkun 5 months ago
parent b9fcbb5153
commit d24bf731e0

@ -187,6 +187,18 @@
<version>1.2.83_noneautotype</version>
</dependency>
<!--pdf水印-->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.10</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
</dependencies>

@ -6,6 +6,7 @@ import cn.hutool.json.JSONUtil;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTUtil;
import com.supervision.utils.TokenUtil;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
@ -28,7 +29,7 @@ public class JwtInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
//请求消息头获取用户ID
String token = request.getHeader("token");
String token = findTokenInRequest(request);
if (StrUtil.isBlank(token)) {
// 如果是swagger来的接口,说明这里是测试的,会伪造一个用户
String referer = request.getHeader("Referer");
@ -36,13 +37,24 @@ public class JwtInterceptor implements HandlerInterceptor {
cacheAuth(JWTUtil.parseToken(devActiveUser()));
return true;
} else {
// throw new BusinessException("当前用户未登录", HttpStatus.UNAUTHORIZED.value());
throw new BusinessException("当前用户未登录", HttpStatus.UNAUTHORIZED.value());
}
}
// JWT jwt = JWTUtil.parseToken(token);
JWT jwt = JWTUtil.parseToken(token);
// 校验token是否过期,如果过期了,需要提示过期重新登录
// checkTokenExpire(jwt);
// cacheAuth(jwt);
boolean expire = checkTokenExpire(jwt);
if (expire){
throw new BusinessException("用户登录已过期,请重新登录", HttpStatus.UNAUTHORIZED.value());
}
String cookieToken = findTokenInCookie(request.getCookies());
if (!StrUtil.equals(cookieToken, token)){
Cookie tokenCookie = new Cookie("token", token);
tokenCookie.setMaxAge((int) TokenUtil.EXPIRE_TIME);
tokenCookie.setPath("/");
tokenCookie.setAttribute("SameSite", "Lax");
response.addCookie(tokenCookie);
}
cacheAuth(jwt);
return true;
}
@ -55,15 +67,38 @@ public class JwtInterceptor implements HandlerInterceptor {
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
private String findTokenInRequest(HttpServletRequest request) {
String token = request.getHeader("token");
if (StrUtil.isEmpty(token)) {
// 尝试从cookie中获取token数据
token = findTokenInCookie(request.getCookies());
}
return token;
}
private void checkTokenExpire(JWT jwt) {
private String findTokenInCookie(Cookie[] cookies) {
if (cookies != null) {
for (Cookie cookie : cookies) {
if (cookie.getName().equals("token")) {
return cookie.getValue();
}
}
}
return null;
}
/**
* token
* @param jwt jwt
* @return true ,false
*/
private boolean checkTokenExpire(JWT jwt) {
Object expireTime = jwt.getPayload("expireTime");
long l = Long.parseLong(String.valueOf(expireTime));
// 校验是否比当前时间大
long currentTimeMillis = System.currentTimeMillis();
if (currentTimeMillis > l) {
throw new BusinessException("用户登录已过期,请重新登录", HttpStatus.UNAUTHORIZED.value());
}
return currentTimeMillis > l;
}

@ -27,7 +27,7 @@ public class WebConfig implements WebMvcConfigurer {
paths.add("/error");
paths.add("/favicon.ico");
paths.add("/user/login");
paths.add("/minio/downloadFile");
// paths.add("/minio/downloadFile");
paths.add("/minio/uploadFile");
paths.add("/user/changePassWord");
paths.add("/fileManage/downloadFile");

@ -17,6 +17,8 @@ public interface MinioService {
void downloadFile(String fileId, HttpServletResponse response);
void downloadFileWithWatermark(String fileId, String fileType, String waterMarkName, HttpServletResponse response);
R<?> delFile(String fileId);
InputStream getObjectInputStream(String fileId);

@ -1,23 +1,32 @@
package com.supervision.minio.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.itextpdf.text.DocumentException;
import com.supervision.common.domain.R;
import com.supervision.common.utils.StringUtils;
import com.supervision.minio.client.MinioTemplate;
import com.supervision.minio.domain.MinioFile;
import com.supervision.minio.mapper.MinioFileMapper;
import com.supervision.minio.service.MinioService;
import com.supervision.utils.UserUtil;
import com.supervision.utils.WatermarkUtil;
import io.minio.StatObjectResponse;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
@Slf4j
@Service
@RequiredArgsConstructor
public class MinioServiceImpl implements MinioService {
@ -60,7 +69,42 @@ public class MinioServiceImpl implements MinioService {
public void downloadFile(String fileId, HttpServletResponse response) {
MinioFile minioFile = minioFileMapper.selectById(fileId);
String fileType = minioFile.getFileType();
minioTemplate.getObject(bucketName, fileId, fileType, response);
this.downloadFileWithWatermark(fileId, fileType, UserUtil.getUser().getUserName(), response);
}
@Override
public void downloadFileWithWatermark(String fileId, String fileType, String waterMarkName, HttpServletResponse response) {
try {
InputStream inputStream = minioTemplate.getObjectInputStream(bucketName,fileId);
StatObjectResponse statObjectResponse = minioTemplate.statObject(bucketName, fileId);
String fileName = fileId + "." + fileType;
response.setHeader("Content-Disposition", "inline;filename=" + fileName);
response.setCharacterEncoding("UTF-8");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
if (StrUtil.equalsIgnoreCase("pdf", fileType)){
WatermarkUtil.pdfByText(inputStream, baos, waterMarkName, Map.of());
response.setContentLengthLong(baos.size());
response.setContentType(statObjectResponse.contentType());
response.getOutputStream().write(baos.toByteArray());
}else if (StrUtil.equalsAnyIgnoreCase(fileType,"jpg", "jpeg", "png","bmp")){
WatermarkUtil.ImageByText(waterMarkName, inputStream, baos, Map.of("formatName", fileType));
response.setContentType(statObjectResponse.contentType());
response.setContentLengthLong(baos.size());
response.getOutputStream().write(baos.toByteArray());
}else {
response.setContentLengthLong(statObjectResponse.size());
response.setContentType(statObjectResponse.contentType());
IoUtil.copy(inputStream, response.getOutputStream());
}
baos.close();
inputStream.close();
}catch (IOException | DocumentException e){
log.error("文件下载失败", e);
}
}
@Override

@ -2,6 +2,7 @@ package com.supervision.police.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.itextpdf.text.DocumentException;
import com.supervision.common.domain.R;
import com.supervision.police.domain.EvidenceDirectory;
import com.supervision.police.dto.*;
@ -16,6 +17,8 @@ import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.util.List;
@ -195,7 +198,7 @@ public class CaseEvidenceController {
}
@GetMapping("/downloadEvidence")
public void downloadEvidence(@RequestParam String evidenceId, HttpServletResponse response) {
public void downloadEvidence(@RequestParam String evidenceId, HttpServletResponse response) throws DocumentException, IOException {
caseEvidenceService.downloadEvidence(evidenceId, response);
}

@ -2,6 +2,7 @@ package com.supervision.police.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.itextpdf.text.DocumentException;
import com.supervision.police.domain.CaseEvidence;
import com.supervision.police.domain.EvidenceDirectory;
import com.supervision.police.domain.EvidenceFile;
@ -11,6 +12,8 @@ import com.supervision.police.vo.EvidenceDirectoryReqVO;
import com.supervision.police.vo.VerifyEvidenceReqVO;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Map;
@ -165,5 +168,5 @@ public interface CaseEvidenceService extends IService<CaseEvidence> {
void redoExtractAttributes(String caseId, List<CaseEvidence> caseEvidences);
void downloadEvidence(String evidenceId, HttpServletResponse response);
void downloadEvidence(String evidenceId, HttpServletResponse response) throws IOException, DocumentException;
}

@ -13,6 +13,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itextpdf.text.DocumentException;
import com.supervision.common.constant.EvidenceConstants;
import com.supervision.common.constant.IndexRuleConstants;
import com.supervision.minio.domain.MinioFile;
@ -23,6 +24,8 @@ import com.supervision.police.mapper.CaseEvidenceMapper;
import com.supervision.police.service.*;
import com.supervision.police.vo.EvidenceDirectoryReqVO;
import com.supervision.police.vo.VerifyEvidenceReqVO;
import com.supervision.utils.UserUtil;
import com.supervision.utils.WatermarkUtil;
import com.supervision.utils.ZipFileUtil;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
@ -34,6 +37,8 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
@ -956,15 +961,25 @@ public class CaseEvidenceServiceImpl extends ServiceImpl<CaseEvidenceMapper, Cas
}
@Override
public void downloadEvidence(String evidenceId, HttpServletResponse response) {
public void downloadEvidence(String evidenceId, HttpServletResponse response) throws IOException, DocumentException {
List<EvidenceFileDTO> evidenceFileDTOList = evidenceFileService.listFileInfo(List.of(evidenceId));
Map<String, InputStream> fileInputStreamMap = new HashMap<>();
evidenceFileDTOList.forEach(evidenceFileDTO -> {
for (EvidenceFileDTO evidenceFileDTO : evidenceFileDTOList) {
MinioFile minioFile = minioService.getMinioFile(evidenceFileDTO.getFileId());
if (null != minioFile) {
fileInputStreamMap.put(minioFile.getFilename(), minioService.getObjectInputStream(minioFile));
if (StrUtil.equalsAnyIgnoreCase(minioFile.getFileType(), "pdf")) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
WatermarkUtil.pdfByText(minioService.getObjectInputStream(minioFile), bos, UserUtil.getUser().getUserName(), Map.of());
fileInputStreamMap.put(minioFile.getFilename(), new ByteArrayInputStream(bos.toByteArray()));
} else if (StrUtil.equalsAnyIgnoreCase(minioFile.getFileType(), "jpg", "png", "jpeg", "bmp")) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
WatermarkUtil.ImageByText(UserUtil.getUser().getUserName(), minioService.getObjectInputStream(minioFile), bos, Map.of("formatName", minioFile.getFileType()));
fileInputStreamMap.put(minioFile.getFilename(), new ByteArrayInputStream(bos.toByteArray()));
} else {
fileInputStreamMap.put(minioFile.getFilename(), minioService.getObjectInputStream(minioFile));
}
}
});
}
try {
ZipFileUtil.createZipAndDownload(response, getById(evidenceId).getEvidenceName(), fileInputStreamMap);
} catch (IOException e) {

@ -8,11 +8,13 @@ import cn.hutool.jwt.signers.JWTSignerUtil;
public class TokenUtil {
public static final long EXPIRE_TIME = 60 * 60 * 24;
public static String creatToken(String userInfo){
final JWTSigner signer = JWTSignerUtil.hs256("~~||DDEdfdfee33s6$$".getBytes());
JSONObject info = JSONUtil.parseObj(userInfo);
// 过期时间一天,同时这个字段也作为单点登录使用
info.putOnce("expireTime",System.currentTimeMillis() + 1000 * 60 * 60 * 24);
info.putOnce("expireTime",System.currentTimeMillis() + 1000 * EXPIRE_TIME);
info.putOnce("issueTime",System.currentTimeMillis());
return JWTUtil.createToken(info, signer);
}

@ -1,32 +1,16 @@
package com.supervision.utils;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTUtil;
import com.supervision.config.ThreadCache;
import com.supervision.police.dto.user.UserInfoDTO;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
public class UserUtil {
public static UserInfoDTO getUser() {
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
Assert.notNull(requestAttributes, "未获取到用户信息");
HttpServletRequest request = requestAttributes.getRequest();
String token = request.getHeader("token");
if (StrUtil.isBlank(token)) {
token = (String) request.getAttribute("token");
}
Assert.notEmpty(token, "未获取到用户token信息");
JWT jwt = JWTUtil.parseToken(token);
JSONObject claimsJson = jwt.getPayload().getClaimsJson();
UserInfoDTO bean = JSONUtil.toBean(claimsJson.toString(), UserInfoDTO.class);
String userString = ThreadCache.USER.get();
UserInfoDTO bean = JSONUtil.toBean(userString, UserInfoDTO.class);
Assert.notNull(bean, "未获取到用户信息");
return bean;
}

@ -0,0 +1,184 @@
package com.supervision.utils;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.pdf.*;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
public class WatermarkUtil {
private final static Map<String,Object> imageConfig = getImgDefaultConfig();
private final static Map<String,Object> pdfConfig = getPdfDefaultConfig();
public static Map<String,Object> getImgDefaultConfig(){
Map<String, Object> config = new HashMap<>();
config.put("alpha",0.5f); // 水印透明度
config.put("fontSize",28); // 水印文字大小
config.put("font",new Font("微软雅黑", Font.PLAIN, 28)); // 水印文字字体
config.put("color",Color.gray); // 水印文字颜色
config.put("xMove",80); // 水印之间的间隔
config.put("yMove",80); // 水印之间的间隔
config.put("degree",-40);// 旋转角度
config.put("formatName","JPG");
return config;
}
public static Map<String,Object> getPdfDefaultConfig(){
Map<String, Object> config = new HashMap<>();
try {
config.put("baseFont",BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED));
} catch ( IOException|DocumentException e) {
throw new RuntimeException(e);
}
config.put("fillOpacity",0.3f);// 填充透明度
config.put("strokeOpacity",0.4f);// 笔划不透明度
config.put("fontSize",16);//字体大小
config.put("interval",-15);// 水印间隔
config.put("rotation",30);// 旋转角度
return config;
}
/**
* 1:12:1
*/
private static int getTextLength(String text) {
int length = text.length();
for (int i = 0; i < text.length(); i++) {
String s = String.valueOf(text.charAt(i));
if (s.getBytes().length > 1) {
length++;
}
}
length = length % 2 == 0 ? length / 2 : length / 2 + 1;
return length;
}
public static void pdfByText(InputStream inputStream, OutputStream outputStream, String waterMarkName,Map<String,Object> config) throws DocumentException, IOException {
PdfReader reader = new PdfReader(inputStream);
PdfStamper stamper = new PdfStamper(reader, outputStream);
try {
BaseFont base = (BaseFont) config.getOrDefault("baseFont",pdfConfig.get("baseFont"));
com.itextpdf.text.Rectangle pageRect;
PdfGState gs = new PdfGState();
gs.setFillOpacity((Float) config.getOrDefault("fillOpacity",pdfConfig.get("fillOpacity")));
gs.setStrokeOpacity((Float) config.getOrDefault("strokeOpacity",pdfConfig.get("strokeOpacity")));
int total = reader.getNumberOfPages() + 1;
JLabel label = new JLabel();
FontMetrics metrics;
int textH;
int textW;
label.setText(waterMarkName);
metrics = label.getFontMetrics(label.getFont());
textH = metrics.getHeight();
textW = metrics.stringWidth(label.getText());
PdfContentByte under;
int interval = (int) config.getOrDefault("interval", pdfConfig.get("interval"));
int rotation = (int) config.getOrDefault("rotation", pdfConfig.get("rotation"));
int fontSize = (int) config.getOrDefault("fontSize", pdfConfig.get("fontSize"));
for (int i = 1; i < total; i++) {
pageRect = reader.getPageSizeWithRotation(i);
under = stamper.getOverContent(i);
under.saveState();
under.setGState(gs);
under.beginText();
under.setFontAndSize(base, fontSize);
for (int height = interval + textH; height < pageRect.getHeight(); height = height + textH * 3) {
for (int width = interval + textW; width < pageRect.getWidth() + textW; width = width + textW * 2) {
under.showTextAligned(Element.ALIGN_LEFT
, waterMarkName, width - textW, height - textH, rotation);
}
}
// 添加水印文字
under.endText();
}
} finally {
stamper.close();
reader.close();
}
}
/**
*
* @param logoText
* @param inputStream
* @param outputStream
*/
public static void ImageByText(String logoText, InputStream inputStream, OutputStream outputStream, Map<String, Object> config) throws IOException {
// 源图片
Image srcImg = ImageIO.read(inputStream);
// 原图宽度
int width = srcImg.getWidth(null);
// 原图高度
int height = srcImg.getHeight(null);
BufferedImage buffImg = new BufferedImage(srcImg.getWidth(null), srcImg.getHeight(null), BufferedImage.TYPE_INT_RGB);
// 构建画笔对象
Graphics2D g = buffImg.createGraphics();
try {
// 设置对线段的锯齿状边缘处理
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.drawImage(srcImg.getScaledInstance(srcImg.getWidth(null), srcImg.getHeight(null), Image.SCALE_SMOOTH), 0, 0, null);
// 设置水印旋转
Integer degree = (Integer) config.getOrDefault("degree", imageConfig.get("degree"));
if (null != degree) {
g.rotate(Math.toRadians(degree), (double) buffImg.getWidth() / 2, (double) buffImg.getHeight() / 2);
}
// 设置水印文字颜色
g.setColor((Color) config.getOrDefault("color", imageConfig.get("color")));
// 设置水印文字Font
g.setFont((Font) config.getOrDefault("font", imageConfig.get("font")));
// 设置水印文字透明度
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, (Float) config.getOrDefault("alpha", imageConfig.get("alpha"))));
int x = -width / 2;
int y;
// 字体高度
int markHeight = (int) config.getOrDefault("fontSize", imageConfig.get("fontSize"));
// 字体长度
int markWidth = markHeight * getTextLength(logoText);
// 循环添加水印
while (x < width * 1.5) {
y = -height / 2;
while (y < height * 1.5) {
g.drawString(logoText, x, y);
y += markHeight + (int) config.getOrDefault("yMove", imageConfig.get("yMove"));
}
x += markWidth + (int) config.getOrDefault("xMove", imageConfig.get("xMove"));
}
} finally {
// 释放资源
g.dispose();
}
// 生成图片
ImageIO.write(buffImg, (String) config.getOrDefault("formatName", imageConfig.get("formatName")), outputStream);
}
}

@ -12,7 +12,7 @@ import org.springframework.boot.test.context.SpringBootTest;
import java.io.*;
import java.util.HashMap;
import java.io.IOException;
@Slf4j
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class WordRenderTest {
@ -23,7 +23,7 @@ public class WordRenderTest {
@Autowired
private ModelService modelService;
public static void main(String[] args) throws FileNotFoundException {
public static void main1(String[] args) throws FileNotFoundException {
HashMap<String, Object> data = new HashMap<>();
data.put("name", "张三");
@ -42,6 +42,86 @@ public class WordRenderTest {
}
//裴金禄涉嫌合同诈骗案详情-v0.docx
public static void main(String[] args) {
}
/*ublic static void main(String[] args) {
try {
//水印文字
String str = "裴金禄";
// 原图片的路径
File inputImage = new File("F:\\tmp\\1\\赵耀文第一次\\赵耀文第一次-1.jpg");
// 输出图片的路径
File outputImage = new File("F:\\tmp\\1\\赵耀文第一次\\赵耀文第一次-水印.jpg");
// 构建一个image对象
BufferedImage img = ImageIO.read(inputImage);
int width = img.getWidth();
int height = img.getHeight();
// 计算字体大小
int fontSize = (width + height) / 80;
Graphics2D g = img.createGraphics();
g.setFont(new Font("黑体", Font.PLAIN, fontSize));
g.setColor(new Color(0, 0, 0, 30));
// 旋转角度
g.rotate(-0.6);
// 间隔
int split = fontSize * 2;
// 文字占用的宽度
int xWidth = getStrWidth(str, fontSize);
// x,y可以绘制的数量,多加一个补充空白
int xCanNum = width / xWidth + 1;
int yCanNum = height / fontSize + 1;
for (int i = 1; i <= yCanNum; i++) {
int y = fontSize * i + split * i;
for (int j = 0; j < xCanNum; j++) {
int x = xWidth * j + split * j;
g.drawString(str, x, y - (fontSize + split) * j);
}
}
g.dispose();
ImageIO.write(img, "png", outputImage);
} catch (Exception e) {
e.printStackTrace();
}
}*/
/**
*
*
* @param str
* @param fontSize
* @return
*/
public static int getStrWidth(String str, int fontSize) {
char[] chars = str.toCharArray();
int fontSize2 = fontSize / 2;
int width = 0;
for (char c : chars) {
int len = String.valueOf(c).getBytes().length;
// 汉字为3,其余1
// 可能还有一些特殊字符占用2 等等,统统计为汉字·
if (len != 1) {
width += fontSize;
} else {
width += fontSize2;
}
}
return width;
}
@Test
public void test() throws FileNotFoundException {
CaseScoreDetailDTO caseScoreDetailDTO = modelService.caseScoreDetail("1810902613967384577");

Loading…
Cancel
Save