概述
在对安全性要求比较高的系统中,我们可能希望,指定该系统登录时只允许某些特定标识的浏览器进行登录。这时我们就需要做到1、得到浏览器较为唯一的设备标识;2、在设备变更时,自动触发鉴权机制,通过手机或邮件的形式向用户发送确认消息让用户确定是本人操作。本文介绍了这样的过程。
1、浏览器标识 user-agent
user-agent 是用来标识用户身份所用,访问你的站点的可能会是正常用户、爬虫、机器人等;
爬虫机器人的user-agent大部分长这样:
Go-http-client/1.1
python-requests/2.23.0
YisouSpider
Intellij IDEA Github Plugin
Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)
我们可以利用这个来对爬虫做限制(当然如果你需要seo,那么对搜索引擎的爬虫则不需要做限制)
对于正常用户的user-agent长这样:
Mozilla/5.0 (Windows NT 6.4; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2225.0 Safari/537.36
其可分为:
Mozilla/5.0 (平台) 引擎版本 浏览器版本号
(1)Mozilla/5.0
这部分是对浏览器老大哥的尊重;早期网站对Mozilla比较友好,对Mozilla(前网景)返回的网页更图文并茂一些。
https://blog.csdn.net/wq18512847606/article/details/80300701
(2)平台
也就是该浏览器是运行在哪个平台上的,如windows、linux、安卓、苹果等。
Windows NT 5.0 // 如 Windows 2000
Windows NT 5.1 // 如 Windows XP
Windows NT 6.0 // 如 Windows Vista
Windows NT 6.1 // 如 Windows 7
Windows NT 6.2 // 如 Windows 8
Windows NT 6.3 // 如 Windows 8.1
Windows NT 10.0 // 如 Windows 10
Win64; x64 // Win64 on x64
WOW64 // Win32 on x64
X11; Linux i686; // Linux 桌面,i686 版本
X11; Linux x86_64; // Linux 桌面,x86_64 版本
X11; Linux i686 on x86_64 // Linux 桌面,运行在 x86_64 的 i686 版本
Macintosh; Intel Mac OS X 10_9_0 // Intel x86 或者 x86_64
Macintosh; PPC Mac OS X 10_9_0 // PowerPC
Macintosh; Intel Mac OS X 10.12; // 不用下划线,用点
移动设备
function isMobileDevice(ua) {
if (/(iphone|ios|android|mini|mobile|mobi|Nokia|Symbian|iPod|iPad|Windowss+Phone|MQQBrowser|wp7|wp8|UCBrowser7|UCWEB|360s+Aphones+Browser)/i.test(ua)) {
return true;
}
return false;
}
(3)引擎版本
AppleWebKit/537.36 (KHTML, like Gecko)...Safari/537.36,历史上,苹果依靠了WebKit内核开发出Safari浏览器,WebKit包含了WebCore引擎,而WebCore又从KHTML衍生而来。由于历史原因,KHTML引擎需要声明自己是“类似Gecko”的,因此引擎部分这么写。再后来,Google开发Chrome也是用了WebKit内核,于是也跟着这么写。借用Littern的一句话:“Chrome 希望能得到为Safari编写的网页,于是决定装成Safari,Safari使用了WebKit渲染引擎,而WebKit呢又伪装自己是KHTML,KHTML呢又是伪装成Gecko的。同时所有的浏览器又都宣称自己是Mozilla。”。不过,后来Chrome 28某个版本改用了blink内核,但还是保留了这些字符串。而且,最近的几十个版本中,这部分已经固定,没再变过
作者:狗子渣渣
链接:https://www.jianshu.com/p/c5cf6a1967d1
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
(4)浏览器版本
例如
Chrome/98.0.4758.102 Safari/537.36
Chrome/102.0.5005.124 Safari/537.36 Edg/102.0.1245.44
Chrome/90.0.4430.210 Mobile Safari/537.36
包含了浏览器的类型和浏览器版本,其中98 537 102 等为大版本号,较少改动,而后面的小版本则会经常变更。
需要注意每个浏览器不仅会发送自己的版本,也会发送其它浏览器的版本,例如上例第一行是谷歌浏览器的;第二行是edge浏览器的。
浏览器标识
经过上面对user-agent组成的分析。可以发现我们可以利用的就是取出掉浏览器小版本号的字符串来作为较不易变的浏览器设备标识,当然也会有变更的可能,如果发生了这样的变更,那么可以认为设备改变,需要发送认证信息。
Mozilla/5.0 (Windows NT 6.4; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2225.0 Safari/537.36
=>
Mozilla/5.0 (Windows NT 6.4; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41 Safari/537
go提取浏览器设备标识
代码的思路主要是利用正则匹配出版本号,然后保留大版本号,将小版本号去掉。
// Chrome/41.0.2225.0 => Chrome/41 + 0.2225.0
var reg = regexp.MustCompile(`(\S+/\d+)\.([\d.]+)`)
func GetDeviceInfoForUa(userAgent string) string {
di := userAgent
submatch := reg.FindAllStringSubmatch(userAgent, -1)
for _, mat := range submatch {
if len(mat) > 2 {
di = strings.ReplaceAll(di, mat[0], mat[1])
}
}
return di
}
func Example_getDeviceInfoForUa() {
userAgents := []string{
`Mozilla/5.0 (Windows NT 6.4; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2225.0 Safari/537.36`,
`Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3100.0 Safari/537.36`,
}
for _, agent := range userAgents {
fmt.Println(GetDeviceInfoForUa(agent))
}
//Output:
//Mozilla/5 (Windows NT 6.4; WOW64) AppleWebKit/537 (KHTML, like Gecko) Chrome/41 Safari/537
//Mozilla/5 (Windows NT 10.0; Win64; x64) AppleWebKit/537 (KHTML, like Gecko) Chrome/60 Safari/537
}
校验设备标识的流程
- 登录,在完成一系列账户密码校验码的校验之后
- 服务端校验user-agent是否是该用户关联的设备标识
- 如果发现该设备标识用户没有关联,则向密保手机/邮箱发送随机生成验证码,记录令牌信息、设备信息,同时 redirect 用户到设备验证页面
- 用户填写验证码,确认添加该设备
- 服务端核验验证码正确,将设备标识加入用户关联中
- 获取当前设备标识,站点信息,用户ID等写入令牌,生成token,然后回到登录页面,自动登录
- 用户访问敏感资源,携带自身的token
- 校验token时判断当前用户的设备标识、站点信息,是否和令牌记录的一致,如果一致方可放行
设备是否会被伪造呢?当然会,但这样可以提高伪造登录的难度,相比只要携带token就可以访问站点,这种方式无疑安全了多。
这里的设备标识是否只能为user-agent呢,当然不是,还可以是c端设备标识。
如果对安全性的要求更高,还可以向设备标识中增加或者IP,IP段前缀。校验令牌时同时校验IP。
具体代码比较多,不再叙述了。
版权声明
本文章由作者“衡于墨”创作,转载请注明出处,未经允许禁止用于商业用途
评论区#
还没有评论哦,期待您的评论!
引用发言