Java中如何根据照片定位你的位置
作者:互联网
前言
这篇文章很早之前就想写的,奈何本人比较懒 。本周三在朋友圈看到一位名为Lex Python大佬发表过关于这方面的文章,也因为最近思想上有了很深的觉悟,总想记录一些走过的路。与其说些写技术博客,我更倾向于记录知识。
本文没有什么过深的东西,很简单的小知识,适用各行业的同学们。各位看官看看即可,增加一下安全和隐私意识,虽说互联网时代没有隐私可言,但是可以通过一些操作来避免。接下来说一下作死小能手约翰·迈克菲,通过他的故事知道安全和隐私的重要性。
杀毒软件之父“约翰·迈克菲”的传奇人生!
约翰·迈克菲传奇的一生在2021年6月29日落下了帷幕,但是关于他的作死事迹至今还在流传。下面我简略的说一下,详细的情况我们可以找度娘咨询一下。
20世纪60年代末,他在麦卡菲在一家公司中学会了有关早期计算机的基本知识。在38岁之前不务正业,与毒品和酒精为伴。经历过一些打击,迈克菲痛定思痛戒毒,痛改前非,老老实实的当起程序员。
在这个阶段通过他的技术和头脑,发明了全球第一款商用的杀毒软件McAfee,最开始是免费,因为挣不到钱。靠着自己手段和歪招,娶白富美,当上总经理、出任CEO走上人生巅峰。也许生活的太安逸舒适,追求刺激,玩上各种极限危险运动,结果一次意外自己侄子摔死了。
他最有名的一次作死是在2012年——因涉嫌谋杀遭到中美洲小国伯利兹的通缉。 当时迈克菲大爷正在伯利兹一个小镇上当着土皇帝。他买下了一大片土地,在那儿和7个妹子住一起鬼混。不仅如此,他甚至还花钱把当地警察收编成了私人部队。伯利兹政府怀疑他在偷偷制造冰毒,曾派特种部队突袭过他家,但却没找到违禁药物。
就在这节骨眼上,迈克菲大爷的邻居被枪杀了。伯利兹政府说他有重大杀人嫌疑,而迈克菲大爷则说自己遭到了陷害。 当警方上门逮捕他的时候,迈克菲大爷在后院沙滩上挖了个坑把自己埋进去躲过了搜查。随后他带着女朋友坐小船逃到了邻国危地马拉。
就在这么狼狈的时候,迈克菲大爷也没忘记作死。他不仅发博客嘲笑伯利兹政府,还找来了记者和自己一起体验流亡生活。 没想到那记者是个猪队友,他不但把跟迈克菲大爷的合照发到网上,还说“大家快看,迈克菲和我在一起噢!”(一边逃亡一边浪),
网友们一查照片信息,发现里面居然连GPS定位数据都有。数据显示拍照的地点就在危地马拉的一处海边。 警察闻讯赶过去一搜,发现迈克菲大爷果然躲在那里,于是就把他抓了起来。(好家伙,直呼网友内行啊)
复盘一下约翰·迈克菲如何被抓的?
约翰·迈克菲的故事告诉我们两件事 ,第一件事不作不会死,远离猪队友。第二件事本文正题消除掉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。依赖如下图所示:
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() {
@Override
public void onFailure(Call call, IOException exception) {
System.err.println(exception);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
System.out.println( "onResponse: " + response.body().string());
}
});
}
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) ̄)ブ)
- 苹果IOS系统:隐私权–定位服务–相机(永不)
提醒
-
不认识的人坚决不提供任何缘由的高清原图,防止获取你的位置信息
-
发布教程、攻略、贴吧的图片应稍加处理再发布
-
不对我国军事等敏感信息等以任何形势提供拍摄(例如铁路线上运送军事武器等)
结尾
有一次妹子问我,你怎么知道我在那个位置 ,现在你应该知道了吧 ,希望你看不到!!!
标签:定位,Java,--,信息,照片,迈克,File,import,GPS 来源: https://blog.csdn.net/baidu_31156101/article/details/118724762