热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Java中如何根据照片定位你的位置

前言这篇文章很早之前就想写的,奈何本人比较懒。本周三在朋友圈看到一位名为LexPython大佬发表过关于这方面的文章,也因为最近思想上有了很深的觉悟&
前言

这篇文章很早之前就想写的,奈何本人比较懒 。本周三在朋友圈看到一位名为Lex Python大佬发表过关于这方面的文章,也因为最近思想上有了很深的觉悟,总想记录一些走过的路。与其说些写技术博客,我更倾向于记录知识。

本文没有什么过深的东西,很简单的小知识,适用各行业的同学们。各位看官看看即可,增加一下安全和隐私意识,虽说互联网时代没有隐私可言,但是可以通过一些操作来避免。接下来说一下作死小能手约翰·迈克菲,通过他的故事知道安全和隐私的重要性。

杀毒软件之父“约翰·迈克菲”的传奇人生!

约翰·迈克菲传奇的一生在2021年6月29日落下了帷幕,但是关于他的作死事迹至今还在流传。下面我简略的说一下,详细的情况我们可以找度娘咨询一下。

20世纪60年代末,他在麦卡菲在一家公司中学会了有关早期计算机的基本知识。在38岁之前不务正业,与毒品和酒精为伴。经历过一些打击,迈克菲痛定思痛戒毒,痛改前非,老老实实的当起程序员。

在这个阶段通过他的技术和头脑,发明了全球第一款商用的杀毒软件McAfee,最开始是免费,因为挣不到钱。靠着自己手段和歪招,娶白富美,当上总经理、出任CEO走上人生巅峰。也许生活的太安逸舒适,追求刺激,玩上各种极限危险运动,结果一次意外自己侄子摔死了。

他最有名的一次作死是在2012年——因涉嫌谋杀遭到中美洲小国伯利兹的通缉。 当时迈克菲大爷正在伯利兹一个小镇上当着土皇帝。他买下了一大片土地,在那儿和7个妹子住一起鬼混。不仅如此,他甚至还花钱把当地警察收编成了私人部队。伯利兹政府怀疑他在偷偷制造冰毒,曾派特种部队突袭过他家,但却没找到违禁药物。

就在这节骨眼上,迈克菲大爷的邻居被枪杀了。伯利兹政府说他有重大杀人嫌疑,而迈克菲大爷则说自己遭到了陷害。 当警方上门逮捕他的时候,迈克菲大爷在后院沙滩上挖了个坑把自己埋进去躲过了搜查。随后他带着女朋友坐小船逃到了邻国危地马拉。

就在这么狼狈的时候,迈克菲大爷也没忘记作死。他不仅发博客嘲笑伯利兹政府,还找来了记者和自己一起体验流亡生活。 没想到那记者是个猪队友,他不但把跟迈克菲大爷的合照发到网上,还说“大家快看,迈克菲和我在一起噢!”(一边逃亡一边浪),

网友们一查照片信息,发现里面居然连GPS定位数据都有。数据显示拍照的地点就在危地马拉的一处海边。 警察闻讯赶过去一搜,发现迈克菲大爷果然躲在那里,于是就把他抓了起来。(好家伙,直呼网友内行啊)

表情包.jpg

复盘一下约翰·迈克菲如何被抓的?

约翰·迈克菲的故事告诉我们两件事 ,第一件事不作不会死,远离猪队友。第二件事本文正题消除掉Exif信息。

为什么通过一张照片就可以定位到拍照者的准确位置,其实关键在于照片文件里有一个名叫EXIF信息。他其实专门为数码相机照片设计的。用于记录照片的属性和拍摄数据。下面通过代码(技术手段)展示一下EXIF信息!!!

先说配置部分,用Java控制台工程即可,我用的AS控制台工程,建议用IntelliJ IDEA。我是为了省事有现成的编译器就没有用IntelliJ IDEA。我用的是gradle方式作为远程依赖,maven同理。

我熟悉gradle依赖方式,看文档好像metadata-extractor-2.16.0只支持maven,于是把开源项目clone 下来编译成jar放在lib下作为依赖。xmpcore:6.0.6和metadata是配套的需要远程依赖,http请求api方面用的成熟的第三方框架okhttp3。依赖如下图所示:

image.png

package com.example.exif;import com.drew.imaging.ImageMetadataReader;
import com.drew.metadata.Directory;
import com.drew.metadata.Metadata;
import com.drew.metadata.Tag;
import java.io.File;
import java.io.IOException;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;public class ReadExifPhoto {public static void main(String[] args) {File file = new File("/Users/sky/Downloads/IMG_20210706_172959.jpg");try {Metadata metadata = ImageMetadataReader.readMetadata(file);for (Directory directory : metadata.getDirectories()) {for (Tag tag : directory.getTags()) {System.out.print(tag.getTagName() + " --> ");System.out.println(tag.getDescription());}if (directory.hasErrors()) {for (String error : directory.getErrors()) {System.err.println("ERROR: " + error);}}}} catch (Exception e) {e.printStackTrace();}}

控制台输出信息如下内容,我对关键的信息加上注释。详细的每一条属性需要找一下度娘了,我也记不住属性很多!!!

> Task :lib:ReadExifPhoto.main()
Compression Type --> Baseline
Data Precision --> 8 bits
Image Height --> 3472 pixels //图片高度 单位(px)
Image Width --> 4624 pixels //图片宽度 单位(px)
Number of Components --> 3
Component 1 --> Y component: Quantization table 0, Sampling factors 2 horiz/2 vert
Component 2 --> Cb component: Quantization table 1, Sampling factors 1 horiz/1 vert
Component 3 --> Cr component: Quantization table 1, Sampling factors 1 horiz/1 vert
Version --> 1.1
Resolution Units --> none
X Resolution --> 1 dot
Y Resolution --> 1 dot
Thumbnail Width Pixels --> 0
Thumbnail Height Pixels --> 0
Image Width --> 4624 pixels
Model --> Redmi Note 8 Pro //拍摄手机型号
Image Height --> 3472 pixels
Orientation --> Right side, top (Rotate 90 CW)
Date/Time --> 2021:07:06 17:30:00 //拍摄照片时间
Make --> Xiaomi //拍摄手机厂商 ,小米手机
F-Number --> f/1.9
Focal Length --> 5.4 mm
Exposure Time --> 9999/500000 sec
Flash --> Flash did not fire
Unknown tag (0x9999) --> {"mirror":false,"sensor_type":"rear","Hdr":"auto","OpMode":36869}
ISO Speed Ratings --> 396
Unknown tag (0x8895) --> 0
Exif Image Height --> 3472 pixels
Exif Image Width --> 4624 pixels
Aperture Value --> f/1.9
Shutter Speed Value --> 49.5 sec
Sub-Sec Time --> 549
GPS Latitude Ref --> N //北纬
GPS Latitude --> 39° 58' 31.89" //纬度
GPS Longitude Ref --> E //东经
GPS Longitude --> 116° 20' 42.77" //经度
GPS Time-Stamp --> 09:29:59.000 UTC
GPS Date Stamp --> 2021:07:06
XMP Value Count --> 1
Number of Tables --> 4 Huffman tables
Detected File Type Name --> JPEG //图片类型
Detected File Type Long Name --> Joint Photographic Experts Group
Detected MIME Type --> image/jpeg
Expected File Name Extension --> jpg
File Name --> IMG_20210706_172959.jpg //拍摄图片文件名
File Size --> 6556702 bytes //图片文件大小 转换一下大约6.6mb
File Modified Date --> 星期二 七月 06 17:30:46 +08:00 2021

从上面可以获取到关键一点GPS定位信息,从控制台得知E116° 20’ 42.77,N 39° 58’ 31.89, 这个信息是不能直接被使用,需要进行一次转换才能找到真正位置信息。

在数学中,表示角度的度、分、秒分别使用°、′、″符号进行表示。1°=60′,1′=60″ ,1°=3600″。下面的转换工具代码如下:

/*** 经纬度坐标格式转换* @param Gps*/private static double conversionUtil(String Gps) {String du = Gps.split("°")[0].replace(" ", "");String fen = Gps.split("°")[1].split("'")[0].replace(" ", "");String miao = Gps.split("°")[1].split("'")[1].replace(" ", "").replace("\"", "");return Double.parseDouble(du)+Double.parseDouble(fen)/60 + Double.parseDouble(miao)/3600;}System.out.println("得到的纬度数据为:====="+conversionUtil("39° 58' 31.89"));System.out.println("得到的经度数据为:====="+conversionUtil("116° 20' 42.77"));Console log 输出:得到的纬度数据为:=====39.975525000000005
得到的经度数据为:=====116.34521388888888

得到了真实的gps定位地址,接下来应该去百度地图或者高德地图找到详细的地理信息。这里我才用的是高德开放平台逆地理web api方式 ,详细调用高德api 需要看下文档,文档内容如下:地理/逆地理编码-API文档-开发指南-Web服务 API | 高德地图API


//演示代码如下,高德key是我自己申请的 ,大家拿去用真实有效。
//也可以用自己申请后的参数。请求上限每天600次,谨慎使用private static void sendGetRequest(){String url = "http://restapi.amap.com/v3/geocode/regeo?key=adbda67c40bbe332e1d18b5ddb03d721&location=116.345214,39.975525&radius=500&extensions=base&batch=false&roadlevel=1";OkHttpClient okHttpClient = new OkHttpClient();final Request request = new Request.Builder().url(url).get()//默认就是GET请求,可以不写.build();Call call = okHttpClient.newCall(request);call.enqueue(new Callback() {@Overridepublic void onFailure(Call call, IOException exception) {System.err.println(exception);}@Overridepublic void onResponse(Call call, Response response) throws IOException {System.out.println( "onResponse: " + response.body().string());}});}

image.png

formatted_address字段就是根据gps得到有效地址信息了。因为计算方式略有不同,我的真实的地址和高德给的略有差异。所以你还是找不到我(手动滑稽)!!!! 代码内容到此结束


{"status": "1","regeocode": {"addressComponent": {"city": [],"province": "北京市","adcode": "110108","district": "海淀区","towncode": "110108008000","streetNumber": {"number": "22号","location": "116.344753,39.975785","direction": "西北","distance": "48.7649","street": "知春路"},"country": "中国","township": "北太平庄街道","businessAreas": [{"location": "116.339877,39.965569","name": "大钟寺村","id": "110108"}],"building": {"name": [],"type": []},"neighborhood": {"name": [],"type": []},"citycode": "010"},"formatted_address": "北京市海淀区北太平庄街道知春路22号知春路22号院"},"info": "OK","infocode": "10000"
}

你的位置是怎么泄露的呢?

满足以下三个条件就会泄露位置:

  • 打开手机GPS定位

  • 拍照设置成保存地理位置

  • 拍照后发送原图。因此如果我们对症下药注意这几个方面,照片的信息安全会大大提高。


如何防范这个问题呢

只要对图片经过压缩,用PS修改等操作后,该图片的EXIF信息可能就不存在了。朋友圈我们经常用,一般情况下腾讯会对微信朋友圈、公众号的推文里的图片进行压缩,保护个人隐私。建议朋友圈不要发原图!!! 小姐姐们一点也不担心因为你们都是美美的,完全不用担心图片exif信息泄露。

  • 安卓系统:以小米手机为例,进入相机设置–关闭保存地理位置信息(开口一句国粹,好像我的保存地理位置信息一直都没关过,我好方 (~ ̄(OO) ̄)ブ)

相机设置.png

  • 苹果IOS系统:隐私权–定位服务–相机(永不)

ios相机设置.png

提醒
  • 不认识的人坚决不提供任何缘由的高清原图,防止获取你的位置信息

  • 发布教程、攻略、贴吧的图片应稍加处理再发布

  • 不对我国军事等敏感信息等以任何形势提供拍摄(例如铁路线上运送军事武器等)


结尾

有一次妹子问我,你怎么知道我在那个位置 ,现在你应该知道了吧 ,希望你看不到!!!


推荐阅读
  • java多线程获取线程返回结果
    我们在使用java多线程编写相关业务代码时,往往有这样一种情况,某个线程依赖于其他线程执行结果。也就是说,我们需要在一个线程中获取另一个线程的信息。可以分为两种情况,一种是轮询,一 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文介绍了如何在给定的有序字符序列中插入新字符,并保持序列的有序性。通过示例代码演示了插入过程,以及插入后的字符序列。 ... [详细]
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • Android源码深入理解JNI技术的概述和应用
    本文介绍了Android源码中的JNI技术,包括概述和应用。JNI是Java Native Interface的缩写,是一种技术,可以实现Java程序调用Native语言写的函数,以及Native程序调用Java层的函数。在Android平台上,JNI充当了连接Java世界和Native世界的桥梁。本文通过分析Android源码中的相关文件和位置,深入探讨了JNI技术在Android开发中的重要性和应用场景。 ... [详细]
  • Java自带的观察者模式及实现方法详解
    本文介绍了Java自带的观察者模式,包括Observer和Observable对象的定义和使用方法。通过添加观察者和设置内部标志位,当被观察者中的事件发生变化时,通知观察者对象并执行相应的操作。实现观察者模式非常简单,只需继承Observable类和实现Observer接口即可。详情请参考Java官方api文档。 ... [详细]
  • 本文介绍了MVP架构模式及其在国庆技术博客中的应用。MVP架构模式是一种演变自MVC架构的新模式,其中View和Model之间的通信通过Presenter进行。相比MVC架构,MVP架构将交互逻辑放在Presenter内部,而View直接从Model中读取数据而不是通过Controller。本文还探讨了MVP架构在国庆技术博客中的具体应用。 ... [详细]
  • 使用eclipse创建一个Java项目的步骤
    本文介绍了使用eclipse创建一个Java项目的步骤,包括启动eclipse、选择New Project命令、在对话框中输入项目名称等。同时还介绍了Java Settings对话框中的一些选项,以及如何修改Java程序的输出目录。 ... [详细]
  • 感谢大家对IT十八掌大数据的支持,今天的作业如下:1.实践PreparedStament的CRUD操作。2.对比Statement和PreparedStatement的大批量操作耗时?(1 ... [详细]
  • 开发笔记:Spark Java API 之 CountVectorizer
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了SparkJavaAPI之CountVectorizer相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 本文介绍了iOS数据库Sqlite的SQL语句分类和常见约束关键字。SQL语句分为DDL、DML和DQL三种类型,其中DDL语句用于定义、删除和修改数据表,关键字包括create、drop和alter。常见约束关键字包括if not exists、if exists、primary key、autoincrement、not null和default。此外,还介绍了常见的数据库数据类型,包括integer、text和real。 ... [详细]
  • 本文介绍了GregorianCalendar类的基本信息,包括它是Calendar的子类,提供了世界上大多数国家使用的标准日历系统。默认情况下,它对应格里高利日历创立时的日期,但可以通过调用setGregorianChange()方法来更改起始日期。同时,文中还提到了GregorianCalendar类为每个日历字段使用的默认值。 ... [详细]
  • C#数字图像处理的3种方法
    来源:http:zxlovenet.cnblogs.com本文主要通过彩色图象灰度化来介绍C#处理数字图像的3种方法,Bitmap类、BitmapData类和Graphics类是C ... [详细]
author-avatar
蔡士奇佳霖哲维
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有