前言
在之前的文章【你的登录接口真的安全吗?】中,我们在用户登录安全方面做了很多设计,就是保护用户的账号安全,但是!!我相信做过用户体系的开发或产品都知道,用户的密码泄漏是一个不可避免的事件,总会有用户因为各种奇奇怪怪的原因而导致账号被盗,进而导致用户信息泄漏、虚拟数据丢失、经济损失等各种后果。那针对这种场景,我们可以通过什么手段来尽量预防呢?
几种实现方式来判断用户登录环境
一般这种情况,业界最简单的处理方式就是识别用户登录环境是是否正常:比如是否是常登录IP、或者是常登录设备等,如果不是,那么则进行限制、二次验证、用户告警等操作。
异地登录
首先是用户异地登录,一般场景下,用户的使用环境大部分时间都是不怎么变化的,比如公司、家里、宿舍或学校等。那么我们可以基于用户的使用IP,来做风险管理。
伪代码实现
def login(username, password, ip):
# 登录失败,简化其它流程
if not do_login(username, password):
return Result(100, '登录失败')
# 检查用户登录环境异常
if !check_login_env(username, ip):
# 发送短信或邮件给用户,告知用户账号在非常用地登录
send_notice(username, ip)
# 前端收到这个状态码后跳转到二次验证页面
return Result(101, '非常登录地登录')
# 登录成功,异步记录当前ip
async_log_ip(username, ip)
return Result(0, '登录成功')
流程很简单,用户登录成功后,进行一次环境校验,判断用户当前登录ip是否为常登录地,如果不是,那么先给用户发送邮件或短信通知,然后返回对应状态码给前端,跳转到二次校验的页面。
二次校验可以通过APP扫码、手机验证码等方式登录。
*上面的代码中还缺少很重要的一步操作,怎么判断用户的IP是否是常登录IP?我们可以基于IP来实现,但是我们现在家用网络的IP基本上都不是固定IP,所以实际场景下可能更多的是使用地区来判断,比如城市。
伪代码实现
def check_login_env(username, ip):
cur_city = get_city_from_ip(ip)
# 此城市是否在近半年的常登录城市中
city = get_last_half_year_cities(username)
return cur_city == city
def log_env(username, ip):
city = get_city_from_ip(ip)
# 记录当前登录城市
insert_login_ip(username, city, ip, datetime.now())
# 统计常登录城市
# 查询的近半年登录次数最多的城市
city = select_max_login_city_last_half_year()
# 设置常登录城市
set_last_half_year_cities(username, city)
上面只是简单的实现,整个判断过程比较粗糙,准确性也不够高。实际产生中,我们可以根据ip位置,结合算法来计算常登录地;或者结合下面的其它方式共同判断。
非常用设备登录
除了通过ip来判断用户使用环境外,我们一般还会结合用户设备来判断,特别是移动端应用,用户设备大部分时候是固定不变的。
设备信息一般可以使用设备指纹的方式,通过采集设备的各种信息,生成一个唯一标识,用于标识此设备。如果设备指纹不存在,那么证明用户在新设备上登录,则进行二次验证。
伪代码实现
def login(username, password, ip, device_info):
# 登录失败,简化其它流程
if not do_login(username, password):
return Result(100, '登录失败')
# 检查用户登录环境异常
if !check_login_env(username, ip):
# 发送短信或邮件给用户,告知用户账号在非常用地登录
send_notice(username, ip)
# 前端收到这个状态码后跳转到二次验证页面
return Result(101, '非常登录地登录')
if !check_device_env(username, device_info):
send_notice(username, device_info)
# 前端收到这个状态码后跳转到二次验证页面
return Result(102, '正在使用新设备登录')
# 登录成功,异步记录当前ip
async_log_ip(username, ip)
# 记录设备信息
async_log_device(username, device_info)
return Result(0, '登录成功')
用户设备信息采集需要征得用户同意,那万一无法采集信息怎么办? 我们也可以想办法在用户第一次登录时,在用户设备中生成记录一个唯一ID并存储在设备中,用于标记这个设备。
异常IP登录
这个和异地登录不同的是,我们可以维护一个IP黑名单,只要是用户登录的IP在黑名单内,则一定要求用户做二次验证。
黑名单的来源主要是通过购买、自行采集的方式获取到的黑产IP
用户风控
上面的各种方式,都不是孤立的,更多的是结合起来,包括其它更多的判断逻辑,来最终决定用户的登录环境是否存在风险,而这部分功能,我们一般会把它抽离出来,单独做为一个风控服务实现。
我们输入用户登录相关的数据,比如用户ID、登录IP、设备信息等,风控服务结合历史数据、用户行为数据等,通过大数据分析以及我们配置的风控规则,最终输出给我们一个风险级别,然后再根据风险级别决定是否需要做后续的措施。
总结
今天主要讲了几种预防用户账号被盗的手段以及简单的实现,相信大家在使用各种产品的时候也有碰到过对应的功能,我们在做用户体系设计的时候,前期可能用户量比较少,但是也可以尽量的考虑安全相关的设计,体量小有小的做法,大有大的做法,但是做了总比没做好。希望读完这篇文章大家有所收获~