如何为数据库中的位图添加动态水印
译者 | 李睿
审校 | 重楼
概要
许多数据库存储了以blob或文件形式保存的数据位图,其中包括照片、库中文档扫描、图添态水医学图像等。加动当这些位图被各种数据库客户端和应用程序检索时,数据为了日后的库中识别和追踪,有时需要在检索时为它们添加唯一的图添态水水印。在某些情况下,加动人们甚至希望这些水印是数据不可见的。
这种动态的库中位图操作可以很容易地通过可编程的数据库代理完成,无需对持久化存储的图添态水位图进行任何修改。
这种方法有以下好处:
水印可以为每次检索进行定制,加动并可以包含有关日期、数据时间、库中用户身份、图添态水IP地址等信息。图像处理由代理完成,这样不会给数据库带来额外的负载。不需要更改数据库或数据库客户端。最终结果给定一个存储在数据库中的位图,例如下图:

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

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

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

然后,代理可以在检索位图时根据需要处理这些位图。
例如,它只能为某些位图添加水印,也可以根据具体情况使用不同样式的水印。存储在数据库中的位图完全不受影响:它们在转发给客户端时被动态修改。
优点客户和数据库对此一无所知——这对他们来说是完全透明的。每当图像被检索时,都可以为其添加独特的水印(例如,日期/时间、用户名、客户端的IP地址等)。数据库服务器上不会增加额外的负载。缺点由于添加了代理,系统变得更加复杂。延迟会增加(通常是适度的),主要取决于图像的服务器托管大小,但应该与替代方案进行比较。实例使用代理,可以创建一个简单的过滤器,为某些位图添加水印。
如果假设数据库包含一个名为images的表,其中包含一个名为bitmap的列,类型为blob或varbinary(取决于数据库),可以在代理中使用以下参数创建一个结果集过滤器:
复制Query pattern: regex:select.*from.*images.*1.以下一些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();1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.32.33.启用这个过滤器之后,从这个表中检索的位图将包括一个水印,其中包含数据库用户的名称和时间戳。
数据库永远不会受到影响:存储在数据库中的位图完全不变,它们是在发送给客户端时即时修改的。
显然,可以选择性地为位图添加水印,可以根据任何相关因素更改水印的文本,还可以通过字体、颜色、定位、透明度等因素添加水印。有关详细信息,参见这个示例。
秘密水印在某些情况下,可能需要以肉眼不可见的服务器租用方式标记位图。一种简单的方法是编辑图像的元数据,但如果需要更微妙的东西,可以使用隐写术在位图中分发秘密消息,使其难以被检测到。
可以修改以上的示例以使用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();1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.有了这一点,提供给客户端修改后的位图将包含一个难以检测的秘密水印,且在没有密钥的情况下几乎无法提取。
水印技术还有哪些用途?这种水印技术也可以应用于位图以外的文档:
像PDF和MS Word这样的文档可以被赋予一些额外的元数据,或者它们可以被赋予一个可见或不可见的水印。可以参考PDF文档的这个示例。所有的文本文档可以巧妙地使用水印技术进行标记,例如改变间距、拼写、布局、字体和颜色、零宽度字符等。所有能够在不失去任何重要意义的情况下进行微小更改的数字文档,例如位图、音频文件和样本集,都能够以类似的方式进行修改。事实上,整个数据集可以通过巧妙地修改数据的一些非关键方面来添加水印,从而有可能在以后识别这些数据集并确切地知道它们的来源。这超出了本文的范围,但是有许多方法可以使数据追溯到其起源。结论当需要从数据库中检索位图或文档时,并且每次检索都需要一个定制的水印,这里展示的技术是一种可靠的方法,它避免了给数据库带来任何额外的负担,并且不需要对客户端或服务器进行任何更改。
原文标题:Dynamic Watermarking of Bitmaps in Databases,作者:Max Tardiveau
本文地址:http://www.bzuk.cn/news/347e9399559.html
版权声明
本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。