阿里根据截图查到泄露者,用的什么黑科技?(数字盲水印)

https://stgod.com/1482

本文分为五个部分,第一部分综述;第二部分频域数字盲水印制作原理介绍;第三部分盲水印攻击性实验;第四部分总结;第五部分附录(源代码)。

一、综述

本文提供的一种实现“阿里通过肉眼无法识别的标识码追踪员工”的技术手段。通过看其他答主的分析,阿里可能还没用到频域加水印的技术。

在原答案中,存在措辞欠妥之处,对此表示由衷的歉意。

相对于空域方法,频域加盲水印的方法隐匿性更强,抵抗攻击能力更强。这类算法解水印困难,你不知道水印加在那个频段,而且受到攻击往往会破坏图像原本内容。本文简要科普通过频域手段添加数字盲水印。对于web,可以添加一个背景图片,来追踪截图者。

所谓盲水印,是指人感知不到的水印,包括看不到或听不见(没错,数字盲水印也能够用于音频)。其主要应用于音像作品、数字图书等,目的是,在不破坏原始作品的情况下,实现版权的防护与追踪。

添加数字盲水印的方法简单可分为空域方法和频域方法,这两种方法添加了冗余信息,但在编码和压缩情况不变的情况下,不会使原始图像大小产生变化(原来是10MB添加盲水印之后还是10MB)。

空域是指空间域,我们日常所见的图像就是空域。空域添加数字水印的方法是在空间域直接对图像操作(之所以说的这么绕,是因为不仅仅原图是空域,原图的差分等等也是空域),比如将水印直接叠加在图像上。

我们常说一个音有多高,这个音高是指频率;同样,图像灰度变化强烈的情况,也可以视为图像的频率。频域添加数字水印的方法,是指通过某种变换手段(傅里叶变换,离散余弦变换,小波变换等)将图像变换到频域(小波域),在频域对图像添加水印,再通过逆变换,将图像转换为空间域。相对于空域手段,频域手段隐匿性更强,抗攻击性更高。

所谓对水印的攻击,是指破坏水印,包括涂抹,剪切,放缩,旋转,压缩,加噪,滤波等。数字盲水印不仅仅要敏捷性高(不被人抓到),也要防御性强(抗打)。就像Dota的敏捷英雄往往是脆皮,数字盲水印的隐匿性和鲁棒性是互斥的。(鲁棒性是抗攻击性的学术名字)

二、频域制作数字盲水印的方法

信号是有频率的,一个信号可以看做是无数个不同阶的正弦信号的的叠加。

上式为傅里叶变换公式,?(t) 是指时域信号(对于信号我们说时域,因为是与时间有关的,而图像我们往往说空域,与空间有关),ω 是指频率。想要对傅里叶变换有深入了解的同学,建议看一下《信号与系统》或者《数字信号处理》的教材,里面系统介绍了傅里叶变换、快速傅里叶变换、拉普拉斯变换、z变换等。

简而言之,我们有方法将时域信号转换成为频域,同样,我们也能将二维信号(图像)转换为频域。在上文中提到,图像的频率是指图像灰度变换的强烈情况。关于此方面更系统的知识,参见冈萨雷斯的《图像处理》。

下面以傅里叶变换为例,介绍通过频域给图像添加数字盲水印的方法。注意,因为图像是离散信号,我们实际用的是离散傅里叶变换,在本文采用的都是二维快速傅里叶变换,快速傅里叶变换与离散时间傅里叶变换等价,通过蝶型归并的手段,速度更快。下文中傅里叶变换均为二维快速傅里叶变换。

上图为叠加数字盲水印的基本流程。编码的目的有二,一是对水印加密,二控制水印能量的分布。以下是叠加数字盲水印的实验。这是原图像,尺寸300*240 (不要问我为什么不用Lena,那是我前女友),

之后进行傅里叶变换,下图变换后的频域图像,

这是我想加的水印,尺寸200*100,

这是我编码后的水印,编码方式采用随机序列编码,通过编码,水印分布到随机分布到各个频率,并且对水印进行了加密,

将上图与原图的频谱叠加,可见图像的频谱已经发生了巨大的变化,

之后,将叠加水印的频谱进行傅里叶逆变换,得到叠加数字水印后的图像,

肉眼几乎看不出叠加水印后的图像与原图的差异,这样,数字盲水印已经叠加到图像中去。实际上,我们是把水印以噪声的形式添加到原图像中。下图是在空域上的加水印图与原图的残差(调整了对比度,不然残差调小看不见),

可以看出,实际上上述方法是通过频域添加冗余信息(像噪声一样)。这些噪声遍布全图,在空域上并不容易破坏。

最终,均方误差(MSE)为0.0244

信噪比(PSNR)为64.2dB那么,为什么频谱发生了巨大的变化,而在空域却变化如此小呢?这是因为我们避开了图像的主要频率。下图是原图频谱竖过来的样子,其能量主要集中在低频。

水印提取是水印叠加的逆过程,

经提取后,我们得到如下水印,问:为什么水印要对称呢?嘿嘿,大家想想看。

三、攻击性实验

本部分进行攻击性实验,来验证通过频域手段叠加数字盲水印的鲁棒性。

1.进行涂抹攻击,这是攻击后的图片:

再进行水印提取:

2.进行剪切攻击,就是网上经常用的截图截取一部分的情况:

进行循环补全:

提取水印:

3.伸缩攻击(这个实验明码做的,水印能量较高,隐匿性不强):

提取水印(水印加的不好,混频挺严重的):

4.旋转攻击(明码):

提取水印:

5.JPEG压缩后(这个实验我好像是拿明码做的,能量主要加在了高频):

提取结果:

6.PS 4像素马赛克/均值滤波等,攻击后图像(这是我女朋友吗?丑死了):

提取水印后图像:

7.截屏,

截屏后我手动抠出要测试的图像区域,并且抽样或者插值到原图尺寸:

测试结果:

8. 亮度调节(明码):

水印提取:

9.色相调节(明码):

水印提取:

10.饱和度调节(明码):

水印:

11.对比度(明码):

水印:

12.评论区用waifu2x去噪后图片:

解水印:

13.美图秀秀,我对我女票一键美颜,美白,磨皮,加腮红,加唇彩(有一种很羞耻的感觉,捂脸):

提取水印:

14.对于背景纯色的图其实也是无所谓的

能量系数为10时加水印图片:觉得太显噪就把能量系数调低,不过水印的隐秘性和鲁棒性是互斥的

最终提取出的水印:

15.我用将RGB>600的像素设置成为(0,255,0)来模拟PS魔术手,

提取水印为:

16.屏摄,好吧,这个实验我做哭了

屏摄图:

实验结果:

我把水印能量系数调整到2000都没有用。

屏摄之后与原图信噪比为4dB左右,我用多抽样滤波的方式试过,滤不掉屏摄引入的噪声。屏摄不仅引入了椒盐噪声,乘性噪声,还有有规律的雪花纹理(摩尔纹)。

四、总结

基于频域的盲水印方法隐藏性强,鲁棒性高,能够抵御大部分攻击。但是,对于盲水印算法,健壮性和隐匿性是互斥的。

本文方法针对屏摄不行,我多次实验没有成功,哪位大神可以做一下或者讨论讨论。还有二值化不行,这是我想当然的,觉得肯定不行所以没做实验。其他的我试了试,用给出的方法调整一下能量系数都可以。我想大家最关心的是什么最安全,不会被追踪。

不涉及图像的都安全,比如拿笔记下来。涉及图像的屏摄最安全,截屏十分不安全。

=====彩蛋(加密过的测试图)====

我在上图明码写入了信息。为了抵抗jpg压缩,我水印能量较高,并且因为没有编码,能量分布不均。图中规律性纹路,就是你懂的。嘿嘿,你懂的,解开看看吧。

五、附录/源码分享

  1. %% 傅里叶变换加水印源代码
  2. %% 运行环境 Matlab2010a
  3. clc;clear;close all;
  4. alpha = 1;
  5. %% read data
  6. im = double(imread(‘gl1.jpg‘))/255;
  7. mark = double(imread(‘watermark.jpg‘))/255;
  8. figure, imshow(im),title(‘original image‘);
  9. figure, imshow(mark),title(‘watermark‘);
  10. %% encode mark
  11. imsize = size(im);
  12. %random
  13. TH=zeros(imsize(1)*0.5,imsize(2),imsize(3));
  14. TH1 = TH;
  15. TH1(1:size(mark,1),1:size(mark,2),:) = mark;
  16. M=randperm(0.5*imsize(1));
  17. N=randperm(imsize(2));
  18. save(‘encode.mat‘,‘M‘,‘N‘);
  19. for i=1:imsize(1)*0.5
  20. for j=1:imsize(2)
  21. TH(i,j,:)=TH1(M(i),N(j),:);
  22. end
  23. end
  24. % symmetric
  25. mark_ = zeros(imsize(1),imsize(2),imsize(3));
  26. mark_(1:imsize(1)*0.5,1:imsize(2),:)=TH;
  27. for i=1:imsize(1)*0.5
  28. for j=1:imsize(2)
  29. mark_(imsize(1)+1-i,imsize(2)+1-j,:)=TH(i,j,:);
  30. end
  31. end
  32. figure,imshow(mark_),title(‘encoded watermark‘);
  33. %imwrite(mark_,‘encoded watermark.jpg‘);
  34. %% add watermark
  35. FA=fft2(im);
  36. figure,imshow(FA);title(‘spectrum of original image‘);
  37. FB=FA+alpha*double(mark_);
  38. figure,imshow(FB); title(‘spectrum of watermarked image‘);
  39. FAO=ifft2(FB);
  40. figure,imshow(FAO); title(‘watermarked image‘);
  41. %imwrite(uint8(FAO),‘watermarked image.jpg‘);
  42. RI = FAO-double(im);
  43. figure,imshow(uint8(RI)); title(‘residual‘);
  44. %imwrite(uint8(RI),‘residual.jpg‘);
  45. xl = 1:imsize(2);
  46. yl = 1:imsize(1);
  47. [xx,yy] = meshgrid(xl,yl);
  48. figure, plot3(xx,yy,FA(:,:,1).^2+FA(:,:,2).^2+FA(:,:,3).^2),title(‘spectrum of original image‘);
  49. figure, plot3(xx,yy,FB(:,:,1).^2+FB(:,:,2).^2+FB(:,:,3).^2),title(‘spectrum of watermarked image‘);
  50. figure, plot3(xx,yy,FB(:,:,1).^2+FB(:,:,2).^2+FB(:,:,3).^2-FA(:,:,1).^2+FA(:,:,2).^2+FA(:,:,3).^2),title(‘spectrum of watermark‘);
  51. %% extract watermark
  52. FA2=fft2(FAO);
  53. G=(FA2-FA)/alpha;
  54. GG=G;
  55. for i=1:imsize(1)*0.5
  56. for j=1:imsize(2)
  57. GG(M(i),N(j),:)=G(i,j,:);
  58. end
  59. end
  60. for i=1:imsize(1)*0.5
  61. for j=1:imsize(2)
  62. GG(imsize(1)+1-i,imsize(2)+1-j,:)=GG(i,j,:);
  63. end
  64. end
  65. figure,imshow(GG);title(‘extracted watermark‘);
  66. %imwrite(uint8(GG),‘extracted watermark.jpg‘);
  67. %% MSE and PSNR
  68. C=double(im);
  69. RC=double(FAO);
  70. MSE=0; PSNR=0;
  71. for i=1:imsize(1)
  72. for j=1:imsize(2)
  73. MSE=MSE+(C(i,j)-RC(i,j)).^2;
  74. end
  75. end
  76. MSE=MSE/360.^2;
  77. PSNR=20*log10(255/sqrt(MSE));
  78. MSE
  79. PSNR
  80. %% attack test
  81. %% attack by smearing
  82. %A = double(imread(‘gl1.jpg‘));
  83. %B = double(imread(‘attacked image.jpg‘));
  84. attack = 1-double(imread(‘attack.jpg‘))/255;
  85. figure,imshow(attack);
  86. FAO_ = FAO;
  87. for i=1:imsize(1)
  88. for j=1:imsize(2)
  89. if attack(i,j,1)+attack(i,j,2)+attack(i,j,3)>0.5
  90. FAO_(i,j,:) = attack(i,j,:);
  91. end
  92. end
  93. end
  94. figure,imshow(FAO_);
  95. %extract watermark
  96. FA2=fft2(FAO_);
  97. G=(FA2-FA)*2;
  98. GG=G;
  99. for i=1:imsize(1)*0.5
  100. for j=1:imsize(2)
  101. GG(M(i),N(j),:)=G(i,j,:);
  102. end
  103. end
  104. for i=1:imsize(1)*0.5
  105. for j=1:imsize(2)
  106. GG(imsize(1)+1-i,imsize(2)+1-j,:)=GG(i,j,:);
  107. end
  108. end
  109. figure,imshow(GG);title(‘extracted watermark‘);
  110. %% attack by cutting
  111. s2 = 0.8;
  112. FAO_ = FAO;
  113. FAO_(:,s2*imsize(2)+1:imsize(2),:) = FAO_(:,1:int32((1-s2)*imsize(2)),:);
  114. figure,imshow(FAO_);
  115. %extract watermark
  116. FA2=fft2(FAO_);
  117. G=(FA2-FA)*2;
  118. GG=G;
  119. for i=1:imsize(1)*0.5
  120. for j=1:imsize(2)
  121. GG(M(i),N(j),:)=G(i,j,:);
  122. end
  123. end
  124. for i=1:imsize(1)*0.5
  125. for j=1:imsize(2)
  126. GG(imsize(1)+1-i,imsize(2)+1-j,:)=GG(i,j,:);
  127. end
  128. end
  129. figure,imshow(GG);title(‘extracted watermark‘);
  130. %%小波变换加水印,解水印大家按照加的思路逆过来就好
  131. clc;clear;close all;
  132. %% read data
  133. im = double(imread(‘gl1.jpg‘))/255;
  134. mark = double(imread(‘watermark.jpg‘))/255;
  135. figure, imshow(im),title(‘original image‘);
  136. figure, imshow(mark),title(‘watermark‘);
  137. %% RGB division
  138. im=double(im);
  139. mark=double(mark);
  140. imr=im(:,:,1);
  141. markr=mark(:,:,1);
  142. img=im(:,:,2);
  143. markg=mark(:,:,2);
  144. imb=im(:,:,3);
  145. markb=mark(:,:,3);
  146. %% parameter
  147. r=0.04;
  148. g = 0.04;
  149. b = 0.04;
  150. %% wavelet tranform and add watermark
  151. % for red
  152. [Cwr,Swr]=wavedec2(markr,1,‘haar‘);
  153. [Cr,Sr]=wavedec2(imr,2,‘haar‘);
  154. % add watermark
  155. Cr(1:size(Cwr,2)/16)=...
  156. Cr(1:size(Cwr,2)/16)+r*Cwr(1:size(Cwr,2)/16);
  157. k=0;
  158. while k<=size(Cr,2)/size(Cwr,2)-1
  159. Cr(1+size(Cr,2)/4+k*size(Cwr,2)/4:size(Cr,2)/4+...
  160. (k+1)*size(Cwr,2)/4)=Cr(1+size(Cr,2)/4+...
  161. k*size(Cwr,2)/4:size(Cr,2)/4+(k+1)*size(Cwr,2)/4)+...
  162. r*Cwr(1+size(Cwr,2)/4:size(Cwr,2)/2);
  163. Cr(1+size(Cr,2)/2+k*size(Cwr,2)/4:size(Cr,2)/2+...
  164. (k+1)*size(Cwr,2)/4)=Cr(1+size(Cr,2)/2+...
  165. k*size(Cwr,2)/4:size(Cr,2)/2+(k+1)*size(Cwr,2)/4)+...
  166. r*Cwr(1+size(Cwr,2)/2:3*size(Cwr,2)/4);
  167. Cr(1+3*size(Cwr,2)/4+k*size(Cwr,2)/4:3*size(Cwr,2)/4+...
  168. (k+1)*size(Cwr,2)/4)=Cr(1+3*size(Cr,2)/4+...
  169. k*size(Cwr,2)/4:3*size(Cr,2)/4+(k+1)*size(Cwr,2)/4)+...
  170. r*Cwr(1+3*size(Cwr,2)/4:size(Cwr,2));
  171. k=k+1;
  172. end;
  173. Cr(1:size(Cwr,2)/4)=Cr(1:size(Cwr,2)/4)+r*Cwr(1:size(Cwr,2)/4);
  174. % for green
  175. [Cwg,Swg]=WAVEDEC2(markg,1,‘haar‘);
  176. [Cg,Sg]=WAVEDEC2(img,2,‘haar‘);
  177. Cg(1:size(Cwg,2)/16)=...
  178. Cg(1:size(Cwg,2)/16)+g*Cwg(1:size(Cwg,2)/16);
  179. k=0;
  180. while k<=size(Cg,2)/size(Cwg,2)-1
  181. Cg(1+size(Cg,2)/4+k*size(Cwg,2)/4:size(Cg,2)/4+...
  182. (k+1)*size(Cwg,2)/4)=Cg(1+size(Cg,2)/4+...
  183. k*size(Cwg,2)/4:size(Cg,2)/4+(k+1)*size(Cwg,2)/4)+...
  184. g*Cwg(1+size(Cwg,2)/4:size(Cwg,2)/2);
  185. Cg(1+size(Cg,2)/2+k*size(Cwg,2)/4:size(Cg,2)/2+...
  186. (k+1)*size(Cwg,2)/4)=Cg(1+size(Cg,2)/2+...
  187. k*size(Cwg,2)/4:size(Cg,2)/2+(k+1)*size(Cwg,2)/4)+...
  188. g*Cwg(1+size(Cwg,2)/2:3*size(Cwg,2)/4);
  189. Cg(1+3*size(Cg,2)/4+k*size(Cwg,2)/4:3*size(Cg,2)/4+...
  190. (k+1)*size(Cwg,2)/4)=Cg(1+3*size(Cg,2)/4+...
  191. k*size(Cwg,2)/4:3*size(Cg,2)/4+(k+1)*size(Cwg,2)/4)+...
  192. g*Cwg(1+3*size(Cwg,2)/4:size(Cwg,2));
  193. k=k+1;
  194. end;
  195. Cg(1:size(Cwg,2)/4)=Cg(1:size(Cwg,2)/4)+g*Cwg(1:size(Cwg,2)/4);
  196. % for blue
  197. [Cwb,Swb]=WAVEDEC2(markb,1,‘haar‘);
  198. [Cb,Sb]=WAVEDEC2(imb,2,‘haar‘);
  199. Cb(1:size(Cwb,2)/16)+b*Cwb(1:size(Cwb,2)/16);
  200. k=0;
  201. while k<=size(Cb,2)/size(Cwb,2)-1
  202. Cb(1+size(Cb,2)/4+k*size(Cwb,2)/4:size(Cb,2)/4+...
  203. (k+1)*size(Cwb,2)/4)=Cb(1+size(Cb,2)/4+...
  204. k*size(Cwb,2)/4:size(Cb,2)/4+(k+1)*size(Cwb,2)/4)+...
  205. g*Cwb(1+size(Cwb,2)/4:size(Cwb,2)/2);
  206. Cb(1+size(Cb,2)/2+k*size(Cwb,2)/4:size(Cb,2)/2+...
  207. (k+1)*size(Cwb,2)/4)=Cb(1+size(Cb,2)/2+...
  208. k*size(Cwb,2)/4:size(Cb,2)/2+(k+1)*size(Cwb,2)/4)+...
  209. b*Cwb(1+size(Cwb,2)/2:3*size(Cwb,2)/4);
  210. Cb(1+3*size(Cb,2)/4+k*size(Cwb,2)/4:3*size(Cb,2)/4+...
  211. (k+1)*size(Cwb,2)/4)=Cb(1+3*size(Cb,2)/4+...
  212. k*size(Cwb,2)/4:3*size(Cb,2)/4+(k+1)*size(Cwb,2)/4)+...
  213. b*Cwb(1+3*size(Cwb,2)/4:size(Cwb,2));
  214. k=k+1;
  215. end;
  216. Cb(1:size(Cwb,2)/4)=Cb(1:size(Cwb,2)/4)+b*Cwb(1:size(Cwb,2)/4);
  217. %% image reconstruction
  218. imr=WAVEREC2(Cr,Sr,‘haar‘);
  219. img=WAVEREC2(Cg,Sg,‘haar‘);
  220. imb=WAVEREC2(Cb,Sb,‘haar‘);
  221. imsize=size(imr);
  222. FAO=zeros(imsize(1),imsize(2),3);
  223. for i=1:imsize(1);
  224. for j=1:imsize(2);
  225. FAO(i,j,1)=imr(i,j);
  226. FAO(i,j,2)=img(i,j);
  227. FAO(i,j,3)=imb(i,j);
  228. end
  229. end
  230. figure, imshow(FAO); title(‘watermarked image‘);
  • 其实如果防御做得好,想绕过还真的没那么容易。按照DLP,也就是数据防泄密的思路:

1.重要的图片或者文档内加水印,文件里面再加上全息数字水印(这个大家都说得很全面了)

然而这就足够了吗?或者说只有这些防护?乃义务!

2.所有终端监控敏感操作:另存、截屏、剪贴板、对敏感文档的操作等等,上述行为一律上传到审计服务器上备份待查。

3.禁止未授权(未安装终端防护程序)的终端接入内网和业务系统

4.有敏感操作或者跨终端登录的时候通过摄像头拍摄人脸(知道为什么扎克伯格要贴摄像头了吧)

5.定期对硬盘进行文件扫描,关键字、相似度、OCR等方法识别出可能是敏感或者涉密的文件,并提取特征,进行标定。

6.同样采用散列值、关键字、相似度匹配等方法检查所有网络出口:邮件、聊天、网站、网盘等,对传输内容全部解码进行审计并且记录。

7.检查或者关闭所有物理出口,USB、Wi-Fi、蓝牙、音频口(防止通过耳机口盗窃数据)。

8.所有文件落地加密(文件加密或者全盘加密),偷硬盘也没用。

9.所有电子设备进出办公区域全部审核检查。

10.核心机密文档不落地,存放于核心服务器,采用远程终端或者虚拟窗口方式查阅/编辑。

别笑,富士康和华为基本上就是这么干的。

转载请注明出处:https://stgod.com/1482

时间: 2024-10-25 21:50:29

阿里根据截图查到泄露者,用的什么黑科技?(数字盲水印)的相关文章

阿里云发布黑科技:面对海量的文本翻译任务,阿里翻译团队是如何解决的

摘要: 对国际化企业来说语言问题是亟待突破的重要关口.面对海量的文本翻译任务,昂贵低效的人工翻译显然不能满足需求,利用计算机自动进行文本翻译的机器翻译才是解决这个问题的关键.阿里翻译团队在机器翻译领域做了大量技术储备,并针对我们所处的电子商务领域进行算法优化,进而打造阿里巴巴自己的机器翻译平台. 对国际化企业来说语言问题是亟待突破的重要关口.面对海量的文本翻译任务,昂贵低效的人工翻译显然不能满足需求,利用计算机自动进行文本翻译的机器翻译才是解决这个问题的关键.阿里翻译团队在机器翻译领域做了大量技

黑科技揭秘:如何通过阿里云超算,使得汽车仿真效率提升25%

摘要: 在汽车行业,过去有一句俗话,一辆车从设计到下线,"至少要11辆真实碰撞试验",今天,在现代化的汽车制造业,通过长期发展的设计和仿真软件,几乎所有的环节,都可以做到设计与仿真一体化的高性能计算实现,这一进步的背后需要依赖更强的并行计算集群和灵活的数据流动,以及实现复杂算法的工业仿真软件. 在汽车行业,过去有一句俗话,一辆车从设计到下线,"至少要11辆真实碰撞试验",今天,在现代化的汽车制造业,通过长期发展的设计和仿真软件,几乎所有的环节,都可以做到设计与仿真一

一次查内存泄露

最近项目在进行对外测试,在服务器上线几个小时后,内存飙到了5.8G(预期2G),JVM一直在GC. 由于现场太大(dump有6G左右)和网络条件不理想,我们边下载dump边开着自己的测试服务器来模拟少量玩家游戏并且通过图形化工具来监视内存中的重量级对象,如玩家.场景等.最后在发现玩家缓存过期清空后,玩家的实例对象一直都没有被GC掉,然后通过工具找出了两个主要的内存泄漏点: 对象池中的对象回收后还一直持有玩家对象的强引用. 一些定时器的生命周期超出了持有者的生命周期,一直持有者玩家对象的强引用并且

从量子加密到机器学习,盘点2015阿里云开放的黑科技

http://www.csdn.net/article/2015-12-18/2826512 摘要:因为云计算应用的不断深入.以及对大数据处理需求的不断扩大,用户要求功能丰富.性能强大.高可用性的产品,云计算厂商们也推陈出新,不断地推出新产品,本文就盘点了业内翘楚阿里云在2015年那些有价值的新产品. 作为云计算产业热土的中国.2015年产业规模依然保持快速增长.且国内的公有云服务领域有几十家企业在角逐.经过几年的发展,眼下市场逐渐明朗.有些公有云企业已经遥遥率先,而有些企业非常可惜,已经開始掉

前端和算法实现:给网站上加上自己的水印(以后用上)

watermark插件的github地址:https://github.com/saucxs/watermark 一.简单 阿里巴巴内网的不可见水印用的是什么算法? 下面的只是简单的加一个很浅的水印,实现起来很容易. 浏览器终端下粘贴下面的代码, 这样就可以加水印了.我选择了百度的首页,好像百度对这个有防护. 它的作用是在当前页面上增加了一个透明度只有0.005的很多的水印.水印内容"测试水印,1021002301,测试水印,DAHJDBJJdjsfsc" 使用QQ截图,这样一点也看不

前端和算法实现:给网站上加上自己的水印(简单+复杂)

一.简单 阿里巴巴内网的不可见水印用的是什么算法? 据说月饼事件截图的那位员工也被开除了? 下面的只是简单的加一个很浅的水印,实现起来很容易. 浏览器终端下粘贴下面的代码, 这样就可以加水印了.我选择了百度的首页,好像百度对这个有防护. 它的作用是在当前页面上增加了一个透明度只有0.005的很多的水印.水印内容“测试水印,1021002301,测试水印,DAHJDBJJdjsfsc” 使用QQ截图,这样一点也看不出来,有水印. 现在把图片放到PS里面,建一个图层在上面.全部填充为黑色,混合模式选

一个五年 Android 开发者百度、阿里、聚美、映客的面试心经

花絮 也许会有人感叹某些人的运气比较好,但是他们不曾知道对方吃过多少苦,受过多少委屈.某些时候就是需要我们用心去发现突破点,然后顺势而上,抓住机遇,那么你将会走向另外一条大道,成就另外一个全新的自我. 先简单说说我最近的面试经历吧.面试的公司很多,其中有让我心血沸腾的经历,也有让我感到失望到无助的经历,我将这些体会都记录下来,细想之后很值得,面了这么多公司,要是最后什么也没有留下来,那就太浪费了.至少对于我来说有些东西在整理总结之后才能得到一个肯定的答案.希望这些能对即将换工作或者打算看看机会的

使用gc、objgraph干掉python内存泄露与循环引用!

Python使用引用计数和垃圾回收来做内存管理,前面也写过一遍文章<Python内存优化>,介绍了在python中,如何profile内存使用情况,并做出相应的优化.本文介绍两个更致命的问题:内存泄露与循环引用.内存泄露是让所有程序员都闻风丧胆的问题,轻则导致程序运行速度减慢,重则导致程序崩溃:而循环引用是使用了引用计数的数据结构.编程语言都需要解决的问题.本文揭晓这两个问题在python语言中是如何存在的,然后试图利用gc模块和objgraph来解决这两个问题. 注意:本文的目标是Cpyth

12306泄露信息查询工具 12306回应信息泄露

12306用户数据泄露今年日登上各大媒体头版头条,从曝光的截图来看,泄露结果超过13万条,包括邮箱.手机号.身份证号等敏感信息一一在列. 更让人恐怖的是,已经有网友反映,称自己在12306上买好的火车票不见了,显然是被人利用泄露信息给恶意退掉了! 此外,泄露资料的用户还很可能遭遇各种骚扰.诈骗,比如说各种垃圾短信和广告,比如说以退票为借口的行骗,而且因为很多人还都在网站上填写了亲人.好友信息共同买票,甚至可能牵连亲友. 当下之急,就是立即修改12306密码,而且尽量不要和其它网站上的密码重复.