如何为数据库中的位图添加动态水印

许多数据库存储了以blob或文件形式保存的位图,其中包括照片、文档扫描、医学图像等。当这些位图被各种数据库客户端和应用程序检索时,为了日后的识别和追踪,有时需要在检索时为它们添加唯一的水印。在某些情况下,人们甚至希望这些水印是不可见的。

这种动态的位图操作可以很容易地通过可编程的数据库代理完成,无需对持久化存储的位图进行任何修改。

这种方法有以下好处:

  • 水印可以为每次检索进行定制,并可以包含有关日期、时间、用户身份、IP地址等信息。
  • 图像处理由代理完成,这样不会给数据库带来额外的负载。
  • 不需要更改数据库或数据库客户端。
最终结果

给定一个存储在数据库中的位图,例如下图:

可编程的数据库代理可以在发送到客户端的途中修改位图,以包含任何所需信息的水印,例如下图:

工作原理

这个架构很简单:它并不依赖于传统的数据库客户端与服务器之间的直接连接,而是采用了一种不同的方式:

客户端连接到代理,代理连接到服务器:

然后,代理可以在检索位图时根据需要处理这些位图。

例如,它只能为某些位图添加水印,也可以根据具体情况使用不同样式的水印。存储在数据库中的位图完全不受影响:它们在转发给客户端时被动态修改。

优点
  • 客户和数据库对此一无所知——这对他们来说是完全透明的。
  • 每当图像被检索时,都可以为其添加独特的水印(例如,日期/时间、用户名、客户端的IP地址等)。
  • 数据库服务器上不会增加额外的负载。
缺点
  • 由于添加了代理,系统变得更加复杂。
  • 延迟会增加(通常是适度的),主要取决于图像的大小,但应该与替代方案进行比较。
实例

使用代理,可以创建一个简单的过滤器,为某些位图添加水印。

如果假设数据库包含一个名为images的表,其中包含一个名为bitmap的列,类型为blob或varbinary(取决于数据库),可以在代理中使用以下参数创建一个结果集过滤器:

Query pattern: regex:select.*from.*images.*

以下一些JavaScript代码(也使用底层Java引擎):

JavaScript 
 // Get the value of the bitmap column as a byte stream
 let stream = context.packet.getJavaStream("bitmap");
 if (stream === null) {
 return;
 }

 // The text to use as watermark
 const now = new Date();
 const watermark = "Retrieved by " + context.connectionContext.userName + 
 " on " + now.getFullYear() + "/" + (now.getMonth()+1) + "/" + now.getDate();

 // Read the bitmap
 const ImageIO = Java.type("javax.imageio.ImageIO");
 let img = ImageIO.read(stream);

 // Create the Graphics to draw the text
 let g = img.createGraphics();
 const Color = Java.type("java.awt.Color");
 g.setColor(new Color(255, 255, 0, 150));
 const Font = Java.type("java.awt.Font");
 g.setFont(new Font("sans-serif", Font.BOLD, 16));

 // Draw the text at the bottom of the bitmap
 let textRect = textFont.getStringBounds(watermark, g.getFontRenderContext());
 g.drawString(watermark, (img.getWidth() / 2) - (textRect.getWidth() / 2),
 img.getHeight() - (textRect.getHeight() / 2));

 // Write the bitmap to the column value
 const ByteArrayOutputStream = Java.type("java.io.ByteArrayOutputStream");
 let outStream = new ByteArrayOutputStream();
 ImageIO.write(img, "png", outStream);
 context.packet.bitmap = outStream.toByteArray();

启用这个过滤器之后,从这个表中检索的位图将包括一个水印,其中包含数据库用户的名称和时间戳。

数据库永远不会受到影响:存储在数据库中的位图完全不变,它们是在发送给客户端时即时修改的。

显然,可以选择性地为位图添加水印,可以根据任何相关因素更改水印的文本,还可以通过字体、颜色、定位、透明度等因素添加水印。有关详细信息,参见这个示例

秘密水印

在某些情况下,可能需要以肉眼不可见的方式标记位图。一种简单的方法是编辑图像的元数据,但如果需要更微妙的东西,可以使用隐写术在位图中分发秘密消息,使其难以被检测到。

可以修改以上的示例以使用Adumbra库:

复制

// Get the value of the bitmap column as a byte stream
let inStream = context.packet.getJavaStream("bitmap");
if (inStream === null) {
 return;
}
// The hidden message
const now = new Date();
const message = "Retrieved by " + context.connectionContext.userName + 
 " on " + now.getFullYear() + "/" + (now.getMonth()+1) + "/" + now.getDate();
const messageBytes = context.utils.getUTF8BytesForString(message);
const keyBytes = context.utils.getUTF8BytesForString("This is my secret key");
// Hide the message in the bitmap
const Encoder = Java.type("com.galliumdata.adumbra.Encoder");
const ByteArrayOutputStream = Java.type("java.io.ByteArrayOutputStream");
let outStream = new ByteArrayOutputStream();
let encoder = new Encoder(1);
encoder.encode(inStream, outStream, "png", messageBytes, keyBytes);
context.packet.bitmap = outStream.toByteArray();

有了这一点,提供给客户端修改后的位图将包含一个难以检测的秘密水印,且在没有密钥的情况下几乎无法提取。

水印技术还有哪些用途?

这种水印技术也可以应用于位图以外的文档:

  • 像PDF和MS Word这样的文档可以被赋予一些额外的元数据,或者它们可以被赋予一个可见或不可见的水印。可以参考PDF文档的这个示例
  • 所有的文本文档可以巧妙地使用水印技术进行标记,例如改变间距、拼写、布局、字体和颜色、零宽度字符等。
  • 所有能够在不失去任何重要意义的情况下进行微小更改的数字文档,例如位图、音频文件和样本集,都能够以类似的方式进行修改。
  • 事实上,整个数据集可以通过巧妙地修改数据的一些非关键方面来添加水印,从而有可能在以后识别这些数据集并确切地知道它们的来源。这超出了本文的范围,但是有许多方法可以使数据追溯到其起源。
结论

当需要从数据库中检索位图或文档时,并且每次检索都需要一个定制的水印,这里展示的技术是一种可靠的方法,它避免了给数据库带来任何额外的负担,并且不需要对客户端或服务器进行任何更改。

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值