黑灰产在互联网领域盛行,从反面推动了业务安全反欺诈领域的快速发展。互联网SAAS服务产品响应市场不断创新,也决定了业务风险的多样性。笔者所在财税领域常见的非财税业务互联网风控场景包括登陆注册、短信接口、营销活动、渠道引流推广、交易和支付等。本文以这些风控场景为基础,搭建一套基于规则引擎的业务风控反欺诈平台。本篇文章会讲到如下内容:

1. 剖析羊毛党等黑产的运作体系、攻击手段等;

2. 分享如何搭建一套基于 Groovy 规则引擎的业务风控平台,平台由事件中心、指标中心、规则决策中心、处罚中心等模块组成。

# 搭建一套基于 Groovy 规则引擎的业务风控平台

## 引语

​ 国内互联网安全产业大致分为两大块:**基础安全和业务安全**。2014年之前,国内的安全行业大部分是聚焦在网络安全、系统安全、Web安全等领域,大家耳熟能详的安全词汇包括SQL注入、XSS、缓冲区溢出、暗链、挂马等都属于基于安全这个领域。2014年之后,互联网产品业务的爆发式增长,安全行业的侧重点也开始发生变化,黑产团队从"攻击渗透获利"转向利用"业务风控缺失进行获利",黑产行业的规模越来越庞大、分工越来越明确。

## 洞悉黑产

### 黑灰产事件

2017年我国网络安全产业规模为450多亿元,而黑灰产已达近千亿元规模互联网。近年来黑灰产业发生大量了案例事件,给个人企业造成了巨大的经济损失。

#### 腾讯视频VIP

2018 年 1 月初,腾讯视频也曾就 0.2 元 VIP 会员支付异常问题发出了声明。腾讯视频突然出现重大BUG,原9折优惠的18元一个月视频会员,一下子0.2元就能买了。

#### 拼多多领取无门槛券

拼多多从2019年1月20号凌晨开始,拼多多出现巨大漏洞,用户可以领取100元无门槛券。有大批用户开启“薅羊毛”的节奏,利用无门槛券来充值话费、Q币。

> 1月20日晨,有黑灰产团伙通过一个过期的优惠券漏洞盗取数千万元平台优惠券,进行不正当牟利。针对此行为,平台已第一时间修复漏洞,并正对涉事订单进行溯源追踪。同时我们已向公安机关报案,并将积极配合相关部门对涉事黑灰产团伙予以打击。

#### 京东由于优惠券设置错误

2020年1月7日,京东由于优惠券设置错误,导致大量产品以0元或者超低价成交,并且发货。网传小家电被薅24万件,损失金额高达7000多万。

> 敬的京东用户大家好,因为1月7日优惠券设置错误原因,导致大量产品以0元或者超低价的情况下成交,并且发货。

目前对此京东已经做出处理方案。

1,针对未发货的订单,京东已经做拦截处理,并且后续不会发货。

2,针对已经发货的产品,京东已经做出拦截处理,商品将会召回。

3,针对部分已签收的订单,如果您满意手中的产品,可以按照原价的8折购买,如果不满意请直接取消,取消后配送员将在24小时内上门取回商品,感谢您的配合。

因为这次错误给您带来的抱歉,京东深感歉意,所有被召回或者拦截的订单,处理成功后系统会自动为您发放一个20元的无门槛优惠券,作为赔偿。

#### 公安部“净网2020”集群战役

央视新闻2020年10月18日报道,在公安部“净网2020”集群战役中,徐州警方就捣毁了一个为网络诈骗、赌博等犯罪提供即时通信工具“养号”、交易的特大黑产平台。抓获犯罪嫌疑人84名,串并各类网络诈骗案件1300多起,涉案金额5000多万元。警方侦查后发现,小果平台绑定的QQ号有2亿多个,而且还发现,在全国1300多起网络诈骗案件中,犯罪分子使用的QQ号都是来自这个平台。那么,小果平台为什么会有这么多QQ号?这些QQ号码都是怎么获取的呢?号商手里有大量的QQ号码,他为了对这些QQ号码控制和使用,他需要绑定大量的手机卡,小果平台上的卡商拥有大量的手机卡,号商把这些QQ号码批量绑定到小果平台上卡商的手机卡上,卡商通过购买猫池、卡池和物联网卡,租用场地建立猫池窝点,通过小果平台的客户端软件接入小果平台,远程对手机卡进行批量的操作。

### 攻击手段

对于黑产行业而言,想尽可能降低成本,提供攻击效率。工欲善其事,必先利其器。黑灰产对产品业务发起各种攻击需要的各种攻击平台以及自动化攻击工具,包括虚拟号码、猫池、代理IP池、设备伪造工具、打码平台等。

#### 猫池

猫池,是指有通信模块,可收发短信,支持多张手机卡同时使用的设备,一般有8槽、16槽的,高端的甚至达到128槽(即可以同时插8、16或128张手机卡)。猫池是“卡商”必不可少的工具之一,只有通过猫池,才能实现多张手机卡同时作业,大量收发短信验证码的效果。

"猫池”算得上是一个高科技装备,一台机器,不需要屏幕,一次能插入上百张SIM卡,“虚拟”出几百台手机,通过一个软件就能集中控制群发短信、自动上网、还能相互“拨打电话”——当然,是没有实际通话内容的。

#### 虚假号码

​ 虚拟运营商简单来说就是某大型企业(比如题主提到的蜗牛移动)得到相关部门批准后,举例比如1709(1709号段属联通网)那么与联通进行合作由联通提供信号与网络蜗牛移动负责运营与客服系统。

​ 发送到用户手机上的验证码信息,包括短信验证码或者语音验证码。短信验证码可以轻松被猫池读取。语音验证码本质上是一次电话呼叫,用户接听后,自动播放一段语音,其中包含朗读的验证码信息。

​ 某些接码平台提供了听码服务,有专门的听码人员,或由开发者提供语音识别的功能,来完成验证码提取。除此之外,通过在猫池上设置呼叫转移,可以把包含验证码信息的短信呼叫,转移到特定的手机号上去,由用户来听取验证码。

使用场景:

+ 首单减免:诱惑如此之大,羊毛党趋之若鹜。

先到接码平台上申请一个手机号,虚假号码一般是独占的,在我申请使用这个号码之后,与我申请的验证码模板相比配的第一条短信,会显示在我的个人界面中

由于该平台下单,是必须通过移动端进行的,而且该平台已经建立了自己的设备指纹。如果用我自己的手机登陆这个账号,设备指纹会显示我已经拥有过一个账号,然后自动将两个账户合并,优惠券不在发放。

所以,一般还会配合模拟器,或改机工具进行。

+ 刷单场景

整个刷单包含了三个环节:批量注册、扫货和下单,都有自动化的工具。其中,虚假号码就是用在批量注册环节。

#### 代理IP池

代理池应该说已经是比较成熟的技术,而且在飞速发展,比如现在主流的“秒拨”技术,给企业在风险IP识别和判定上带来极大的难度。代理池技术目前被广泛用于爬虫、灰黑产、SEO、网络攻击、刷单、薅羊毛等等领域。

## 搭建风控平台

​ 业务风控平台完整的前端业务流程包括:风险评估、风险监控、风险分析、策略产生、处罚处置、申诉核实等。针对我司现有业务单元产品,风控平台基于登陆注册、短信接口、营销活动、渠道引流推广、交易和支付等业务场景构建一套通用的风控系统,用于支持不同渠道、不同业务场景的风险识别和防范。

​ 业务风控平台由**风控网关(事件中心)、指标中台、监控报警、分析平台、决策中台、处罚中台**等组成。风控网关定义了事件元模型,接收用户发送的业务指标数据,风控网关对外可以提供实时同步(dubbo泛化调用)、准实时异步(rocketMQ/kafka)等多种数据接入方式。指标中台用于定义指标模型以及计算指标数据。

### 事件中心

​ 事件接入中心是整个业务风控平台规则引擎的的数据入口,所有的业务方都是通过该模块接入到风控平台并准实时落入**数据中台**。事件接入中心提供同步实时(**DUBBO**)、异步准实时(**MQ**)等多种接入方式。风控事件模型包含事件唯一标示符、触发事件的用户ID、产品业务名称、事件的渠道(移动端、web端等)。风控事件模型能够做到足够灵活、通用的、可配置的,使得业务方能够快速通过业务埋点接入事件中心。

| 字段名 | 字段含义 | 字段类型 |

| ---- | ---- |---- |

| app_code | 事件所属业务线 |varchar(32) |

| app_name | 事件所属业务名称 |varchar(32) |

| biz_owner | 事件所属业务负责人 |varchar(32) |

| channel | 事件的来源渠道 |varchar(32) |

| event_name | 事件名称 |varchar(32) |

| event_unq_id | 事件唯一标识符 |varchar(32) |

| indicator_sample | 事件指标 |varchar(500) |

​ 业务方需要引入风控团队提供的风控业务埋点**SDK**,**SDK**定义事件模型的标准数据结构以及对外统一暴露采集数据的接口。事件接入中心时序图如下:![1]

### 指标中心

​ 业务风控的实时风险决策中,无论是采用规则还是模型技术路线,都需要对一定时间范围内的数据进行加工,这些变量称为指标。指标中心主要负责维护规则和算法需要的各种特征/指标数据。针对事件数据,可能需要做多种维度的统计和分析得到处理后的数据,称为特征数据 。例如单个用户每小时、每天、每周的登陆次数等。指标中心主要包括指标定义和指标计算两大核心模块。

#### 指标定义

​ 风控反欺诈领域,为了只能够及时阻断发现风险行为,以上指标需要能够随时上线,时间窗口和计算维度组合不确定。指标极端可以抽象总结为以下几个特征:事件、指标名称、计算方式、主维度、从维度、时间窗口(时间片)等字段。其中主维度至少有一个,从维度最多有一个;计算指标的方式包括求总数、求和、求平均值、求最大值、求最小值等方式。

#### 指标计算

​ 指标计算模块主要是进行指标的计算,关于指标计算的建设我们将其分为短期、长期两个阶段:

+ 短期:利用Redis + lua 计数器完成指标计算

+ 指标Key的定义与构成,包括所属事件、事件窗口、主维度、从维度、计算方式等;

+ 如何计算滑动窗口的指标;

+ 如何批量获取指标key(REDIS+LUA)

+ 长期:利用Flink完成指标并行计算

+ Flink是当今流计算领域无可争议的No.1, 可以利用Flink完成指标的并行计算。

+ 业务系统把埋点数据发送到Kafka;

+ Flink订阅Kafka,完成原子粒度的聚合;

+ Flink把汇总的指标结果写入Redis或Hbase,供实时风控系统查询。(指标存储根据场景选择Redis或者HBase即可)

##### 计算引擎

风控采集的事件数据需要实时统计计算才能生成规则决策所需的指标,并行流式计算框架能够解决指标的性能和效率问题。业界主流的流式计算框架主要包括MapReduce、Pig/Hive、Spark、Storm、Flink等。

+ MapReduce

MapReduce是第一代计算引擎,用于批处理,编写程序十分耗时,开发效率低,很少有生产企业用于执行批计算任务。

+ Pig/Hive

Pig/Hive是第二代计算引擎,其存储基于hadoop/hdfs,计算基于MR,Pig/Hive处理任务时将代码解析为一个个任务来执行,降低了编写MR代码的成本

Hive 提供类sql语法的HQL查询语言,程序员熟悉SQL所以相比Pig更喜欢使用Hive

Pig/Hive只支持批处理计算

+ Spark/Storm

Spark/Storm是第三代实时数据处理计算引擎,其存储基于hadoop/hdfs,计算基于MR,Pig/Hive处理任务时将代码解析为一个个任务来执行,降低了编写MR代码的成本

Storm属于真正的流式处理,低延迟(ms级延迟),高吞吐,且每条数据都会触发计算。

Spark属于批处理转化为流处理即将流式数据根据时间切分成小批次进行计算,对比与storm而言延迟会高于0.5s(s级延迟),但是性能上的消耗低于storm。“流式计算是批次计算的特例(流式计算是拆分计算的结果)”

+ Flink

Flink2015年出现在apache,后来又被阿里巴巴技术团队进行优化为Blink,Flink支持流式计算也支持的批次处理。

Flink为流式计算而生属于每一条数据触发计算,在性能的消耗低于storm,吞吐量高于storm,延时低于storm,并且比storm更加易于编写。因为storm如果要实现窗口需要自己编写逻辑,但是flink中有窗口方法。

Flink内部支持多种函数,其中包括窗口函数和各种算子(这一点和spark很像,但是在性能和实时上spark是没有办法比较的)

Flink支持仅一次语义保证数据不丢失

Flink支持通过envent time来控制窗口时间,支持乱序时间和时间处理

对于批次处理flink的批处理可以理解为 “批次处理是流式处理的特例”

### 决策中心

决策中心是风控平台的大脑,规则引擎又是决策引擎最为核心的组件。决策中心系统交互流程如下:

我们先来了解下规则的定义。规则包括三个部分:

+ 事实,即被判断的主体和属性,如上面规则的账号及登陆次数、IP和注册次数等;

+ 条件,判断的逻辑,如某事实的某属性大于某个指标;

+ 指标阈值,判断的依据,比如登陆次数的临界阈值,注册账号数的临界阈值等;

#### 规则引擎技术选型

+ Drools

Drools是一款基于Java的开源规则引擎,实现了将业务决策从应用程序中分离出来。

优点:

1、简化系统架构,优化应用

2、提高系统的可维护性和维护成本

3、方便系统的整合

4、减少编写“硬代码”业务规则的成本和风险

+ Aviator

Aviator是一个高性能、轻量级的java语言实现的表达式求值引擎,主要用于各种表达式的动态求值。Aviator的设计目标是轻量级和高性能 ,相比于Groovy、JRuby的笨重,Aviator非常小,加上依赖包也才450K,不算依赖包的话只有70K;当然,Aviator的语法是受限的,它不是一门完整的语言,而只是语言的一小部分集合。

其次,Aviator的实现思路与其他轻量级的求值器很不相同,其他求值器一般都是通过解释的方式运行,而Aviator则是直接将表达式编译成Java字节码,交给JVM去执行。简单来说,Aviator的定位是介于Groovy这样的重量级脚本语言和IKExpression这样的轻量级表达式引擎之间。

+ EasyRules(注解以及yml方式)

Easy Rules是一个简单而强大的Java规则引擎

+ JEXL

Java Expression Language (JEXL) 是一个表达式语言引擎,可以用来在应用或者框架中使用,可以用来校验数据。

虽然Jexl受JSP标签库(JSTL)的影响产生的,但不是JSTL中表达式语言的实现。

+ Esper

Esper 是一个事件流处理和事件关联的引擎(CEP,complex event processing 复合事件处理)。作为实时事件驱动框架,当事件流中有事件条件发生时,Esper能够触发自定义动作(POJO)。Esper也是为了大量事件关联而设计,当有数百万的事件进来时,不能用经典的数据库架构来存储所有事件。

+ QLExpress

由阿里的电商业务规则、表达式(布尔组合)、特殊数学公式计算(高精度)、语法分析、脚本二次定制等强需求而设计的一门动态脚本引擎解析工具。

github地址:alibaba/QLExpress

##### 选择Groovy搭建规则引擎的原因

+ Groovy脚本引擎的性能以及与Java语言的无缝衔接

基于JVM的动态脚本语言,支持闭包和自己封装的一些简单语法,大大减少代码量

Groovy可以调用强大的Java所有的库

企业界的支持:简单好用省时省力,易于使用维护、稳定,能承受大负荷,被Oracle、ThoughtWorks、SpringSource公司看好

+ 至于为什么不选择Drools而选择了Groovy

学习曲线陡峭,其引入的DRL语言较复杂,独立的系统很难进行二次开发

以内存实现时间窗功能,无法支持较长跨度的时间窗

无法有效支持定时触达(如用户在浏览发生后30分钟触达支付条件判断)

+ 滴滴、网易考拉等互联网大厂选择使用Groovy作为规则引擎的背书

##### Java集成Groovy三种方式

Java应用在运行时集成Groovy的三种方式,分别是Eval、GroovyShell、GroovyClassLoader:

+ Eval: groovy.util.Eval 类在运行时,动态执行 Groovy 最简单的方式

+ GroovyShell:gGroovyShell 是用来执行脚本的一个简单工具。其内部使用机制是使用了 groovy.lang.GroovyClassLoader 在运行时编译并加载 classes.

```

GroovyShell shell = new GroovyShell(binding);

Object res = shell.evaluate(script);

```

+ GroovyClassLoader

#### 基于groovy实现复杂布尔表达式规则引擎

在规则引擎决策中,规则往往涉及到多个复杂布尔表达式条件的逻辑计算。条件(condition)通过或与非逻辑运算符组合成复杂的布尔表达式。这类布尔表达式有两种特点:一是条件及表达式是动态可配置的;二是表达式是条件的组合,所以相对是比较复杂的。这里我们基于groovy动态脚本引擎实现了计算复杂性布尔表达式的规则引擎。

Drools规则引擎中定义的规则包含两个部分:`LHS(Left Hand Side)和RHS(Right Hand Side)`,一条规则可以抽象成if-then语句。

```

when <LHS>

then <RHS>

```

一条规则也可以理解为包含多个条件的复杂布尔表达式, 其中每一个条件执行的结果要么是true,要么是false。

规则中的条件可以简化为三个部分: "左变量"、"操作符"、"右变量"。比如,某个用户的登陆次数大于10次。

用户的登陆次数就是左变量,"大于"就是,登陆次数的阈值10次就是右变量。

```

用户的登陆次数> 10次

```

例如,某个具体的规则:

```java

boolean result = exp1 || exp2 && (exp3 || exp4)

```

其中每一条条件exp1、exp2、exp3、exp4的形式可能如下:

```java

exp1 = var1 > 5

exp2 = var2 < 5

exp3 = var3 != "北京"

exp4 = var4 >= 20

```

为方便规则的计算,我们将规则简化成:

```java

boolean result = 1 || 2 && (3 || 4)

```

从`1 || 2 && (3 || 4)`可以看出,规则就是多个条件语句与或非的组合。

使用groovy使用上诉复杂布尔表达式时,可以提前将数字替换为在数字前增加前缀以便在groovy中执行以及计算:

```java

boolean result = e1 || e2 && (e3 || e4)

```

示例代码:

```java

/**

* 字符串内所有数字前面增加前缀

*

* @param str String

* 原字符串

* @param prefix String

* 数字前面需要增加的前缀

* @return String

*/

public static String addPrefixBeforeNumber(String str, String prefix) {

StringBuilder result = new StringBuilder();

boolean isChar = false;

StringBuilder sb = new StringBuilder();

for (int i = 0; i < str.length(); i++) {

char c = str.charAt(i);

if (c >= '0' && c <= '9') {

sb.append(str.charAt(i));

if (i == str.length() - 1) {

sb.setLength(0);

}

isChar = false;

} else {

if (sb.length() > 0 && isChar == false) {

result.append(prefix).append(sb.toString());

sb.setLength(0);

}

result.append(c);

isChar = true;

}

}

return result.toString();

}

```

规则的运算操作支持数值运算和字符串运算两大类:

+ 数值运算操作符

序号 | 符号 | 说明

- | :-: | -: |

1 | == | 等于 |

2 | > | 大于 |

3 | < | 小于 |

4 | >= | 大于等于 |

5 | <= | 小于等于 |

6 | != | 不等于 |

+ 字符串运算操作符

序号 | 符号 | 说明

- | :-: | -: |

1 | CONTAINS | 包含 |

2 | NOT_CONTAINS | 不包含 |

3 | EQUAL_IGNORE_CASE | 不区分大小写的字符串等于 |

4 | STRING_EQUAL | 字符串相等 |

5 | NOTSTRING_EQUAL | 字符串不等 |

6 | NOT_EQUAL_IGNORE_CASE | 不区分大小写的字符串不等 |

7 | MATCHES | 正则匹配 |

8 | NOT_MATCHES | 正则不匹配 |

### 处罚中心

todo

## 参考

+ 图解网络黑色产业链 该如何防范?

图解网络黑色产业链该如何防范?-中共中央网络安全和信息化委员会办公室

+ 深网丨猫池、撞库、伪基站,拼多多薅羊毛事件背后的千亿黑产网络

深网丨猫池、撞库、伪基站,拼多多薅羊毛事件背后的千亿黑产网络_科技_腾讯网

+ 养号平台养2亿个QQ号供骗子选用!已被江苏警方捣毁!

养号平台养2亿个QQ号供骗子选用!已被江苏警方捣毁!_深圳新闻网

搭建一套基于 Groovy 规则引擎的业务风控平台相关推荐

  1. 使用 Drools 规则引擎实现业务逻辑,可调试drl文件

    http://www.srcsky.com/tech/arts/389.html 代码下载http://download.csdn.net/detail/zhy011525/2462313 使用 Dr ...

  2. 基于 SOA 的组件化业务基础平台

    基于 SOA 的组件化业务基础平台 原文:基于 SOA 的组件化业务基础平台 前言 业务基础平台是业务逻辑应用和基础架构平台之间的一个中间层,解决 "应用软件的业务描述和操作系统平台.软件基 ...

  3. 基于 Apache Flink 和规则引擎的实时风控解决方案 ​

    对一个互联网产品来说,典型的风控场景包括: 注册风控.登陆风控.交易风控.活动风控等,而风控的最佳效果是防患于未然,所以事前事中和事后三种实现方案中,又以事前预警和事中控制最好. 这要求风控系统一定要 ...

  4. Java内嵌Groovy脚本引擎进行业务规则剥离(一)

    2019独角兽企业重金招聘Python工程师标准>>> 一些常见商业应用程序或企业应用,大多都会遇上业务规则在一定的条件下,允许进行一些灵活的配置,以满足业务变化的需要. 解决的方式 ...

  5. groovy 规则引擎 java_Java内嵌Groovy脚本引擎进行业务规则剥离(一)

    一些常见商业应用程序或企业应用,大多都会遇上业务规则在一定的条件下,允许进行一些灵活的配置,以满足业务变化的需要. 解决的方式大致有以下几个方面: 最为传统的方式是java程序直接写死提供几个可调节的 ...

  6. 使用 Drools 规则引擎实现业务逻辑

    要求施加在当今软件产品上的大多数复杂性是行为和功能方面的,从而导致组件实现具有复杂的业务逻辑.实现 J2EE 或 J2SE 应用程序中业务逻辑最常见的方法是编写 Java 代码来实现需求文档的规则和逻 ...

  7. 规则引擎在数据治理平台的实践

    一.背景 在数据治理时,经常会遇到个性化统计分析的场景:基于数据的某些属性进行组合筛选,只有符合条件的数据才进行统计分析. 传统的实现方式是:业务人员提供筛选条件,数据开发人员在ETL任务直接开发.这 ...

  8. 以Drools5.5为例说明“规则引擎在业务系统中应用”---起始篇

    一.规则引擎 见 百度百科 二.Drools5.5配置 1.安装配置Drools5.5 1.下载http://www.drools.org/download/download.html 2.安装ecl ...

  9. 基于SOA的组件化业务基础平台[转]

    转自https://www.ibm.com/developerworks/cn/webservices/1111_xiaojg_soa/index.html 业务基础平台是业务逻辑和基础架构平台之间的 ...

最新文章

  1. box-cox数据规整转换
  2. pc端WINCE的安装包
  3. 小米小爱蓝牙音箱_小米小爱蓝牙音箱——值否?
  4. python中if的效率_Python 代码性能优化技巧
  5. 为什么云服务器没西南的_去年“双11“我买的那台云服务器
  6. C++中面向对象的理解
  7. OpenSplice DDS 分布式DDS网络架构(DDS 6.9.0+VS 2013+Qt 5.8.0 )
  8. 解决Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-compile
  9. 管理感悟:当好主管的关键
  10. java语句快捷键_Java中快捷键
  11. 点云配准(四) 四元数与旋转变换
  12. Python学习手册之数据类型
  13. Thinkpad e450c 如何关闭触控板
  14. 未来智安XDR及核心组件产品上榜《嘶吼2022网络安全产业图谱》
  15. 如何给PDF中的内容添加下划线
  16. PyQt5 | PyQt5环境配置及组件介绍
  17. 实训期间的开发过程及心得体会
  18. 今日新网络舆情信息监测收集技术解决办法
  19. HTML+CSS写个人简历
  20. 真容慧表NxCells 构建模板 管理数据表详解

热门文章

  1. c语言用sort函数选择排序,简单选择排序(Simple Selection Sort)的C语言实现
  2. 一个问题来对比文心一言和chatgpt
  3. [当人工智能遇上安全] 5.基于机器学习算法的主机恶意代码识别研究
  4. 电机噪音测试:手持式噪音计术语1
  5. 服务器运维的工作内容及职责
  6. powerdesinger 批量修改表前缀
  7. Uni-App开发框架介绍
  8. 移民找老张解析:美国绿卡与美国公民身份的区别
  9. 【3d游戏模型】女骑士制作指南:硬表面和纹理
  10. Android开发--CardView使用