1. 需求

想要实现一个用户白名单功能,以减少异地验证的频率, 提升用户登陆体验。

2. 实现原理

由于之前没有接触过类似的功能,本次实现方法为:在用户表中新增用户IP白名单字段,用于存储用户登陆后的IP的前三位;在登陆时判断是否在一个城市中。这个办法相对而言比较笨,有些城市拥有的IP地址跨度较大。之后有空再写方法来分辨确切的省市自治区吧。也欢迎大佬们指导,让我学习下其他的验证方式。

3. 导入数据

之前的版本中,使用了较大的表来记录用户对接口的调用记录,其中包括了用户ID和用户IP信息。在这个表中,一个用户对应多行记录,一个IP也可以对应多条记录(也可能对应多个账户)。我下意识就想写一个java项目或者python脚本完成这个工作。但是java工具需要建立Java项目确定依赖情况;python原生链接数据库进行处理较慢(数据量大)。我和小林进行讨论后,觉得还是写一个存储过程解决比较简单靠谱。

就在准备动手的时候,我和明哥抱怨了一句:这么复杂的功能,一个SQL怎么可能完成?。明哥了解我的需求后,表示一个SQL足够完成数据整理导入用户表,并向我推荐了一个函数:group_concat

group_concat,与concat类似,用于字符串的拼接。但与concat应用场景不同,group_concat主要适用于在group by语句中拼接分类后的结果字段。基本语法为:

group_concat( [distinct] 待连接字段 [order by 排序字段 asc/desc ] [separator '分隔符'] )

将其置入查询语句的select之后,就可以轻易的完成批量获取用户分组后的IP信息了。

select SELECT create_user_id, group_concat( DISTINCT concat( '#', SUBSTRING_INDEX   ( ip_address, '.', 3 ) ) SEPARATOR '' ) FROM sys_log GROUP BY create_user_id;

为了符合设计(设计的IP白名单格式为#xxx.xxx.xxx):使用SUBSTRING_INDEX函数获取了第三个’.’之前的字符串;使用concat将’#’拼接到切割后的IP字段之前;使用group_concat函数中的SEPARATOR关键字将默认的逗号(’,’)分隔符替换为空。执行之后,就只有用户ID和指定格式的用户IP白名单了。

对于修改用户表,可以直接将上述的sql放置在update语句中,增加一些判断,则一个SQL就完成了IP地址的转储:

update sys_user a
set a.address_ip = (SELECT group_concat(distinct concat('#', SUBSTRING_INDEX(ip_address, '.', 3)) separator '')
                    FROM sys_log b
                    where b.create_user_id = a.id
                    group by create_user_id);

END~

欢迎联系我一起学习讨论~

01-19 10:23
查看更多