import org.apache.flink.cep.scala.{CEP, PatternStream}
import org.apache.flink.cep.scala.pattern.Pattern
import org.apache.flink.streaming.api.scala._
import org.apache.flink.streaming.api.TimeCharacteristic
import org.apache.flink.streaming.api.functions.timestamps.BoundedOutOfOrdernessTimestampExtractor
import org.apache.flink.streaming.api.scala.StreamExecutionEnvironment
import org.apache.flink.streaming.api.windowing.time.Time
import scala.collection.Map
/**
* 恶意登录监控
1.基本需求
用户在短时间内频繁登录失败,有程序恶意攻击的可能
同一用户(可以是不同IP)在2秒内连续两次登录失败,需要报警
2.解决思路
将用户的登录失败行为存入ListState,设定定时器2秒后触发,查看ListState中有几次失败登录
更加精确的检测,可以使用CEP库实现事件流的模式匹配
* @return ${return}
* @author fujiwen
*/
object LoginFailWithCEP {
def main(args: Array[String]): Unit = {
val env: StreamExecutionEnvironment =
StreamExecutionEnvironment.getExecutionEnvironment
env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime)
env.setParallelism(1)
val dataStream: DataStream[LoginEvent] = env.fromCollection(List(
LoginEvent(1, "192.168.0.1", "fail", 1558430842),
LoginEvent(1, "192.168.0.2", "fail", 1558430843),
LoginEvent(1, "192.168.0.3", "fail", 1558430844),
LoginEvent(1, "192.168.0.1", "fail", 1558430845),
LoginEvent(1, "192.168.0.2", "fail", 1558430846),
LoginEvent(1, "192.168.0.3", "fail", 1558430847),
LoginEvent(1, "192.168.0.1", "fail", 1558430848),
LoginEvent(1, "192.168.0.2", "fail", 1558430849),
LoginEvent(1, "192.168.0.3", "fail", 1558430888),
LoginEvent(2, "192.168.10.10", "success", 1558430845)
)).assignTimestampsAndWatermarks(
new BoundedOutOfOrdernessTimestampExtractor[LoginEvent](Time.milliseconds(1000)) {
override def extractTimestamp(t: LoginEvent): Long = t.eventTime * 1000
})
//本次采用CEP实现
//定义匹配模式,匹配2秒内连续失败的
val loginFailPattern: Pattern[LoginEvent, LoginEvent] = Pattern
.begin[LoginEvent]("begin")
.where(_.eventType.equals("fail"))
.next("next")
.where(_.eventType.equals("fail"))
.within(Time.seconds(2))
//定义匹配的数据流
val patternStream: PatternStream[LoginEvent] = CEP
.pattern(dataStream.keyBy(_.userId), loginFailPattern)
//注意事项导入正确的Map包
patternStream.select((pattern: Map[String, Iterable[LoginEvent]]) => {
val first: LoginEvent = pattern.getOrElse("begin", null).iterator.next()
val second: LoginEvent = pattern.getOrElse("next", null).iterator.next()
(second.userId, second.ip, second.eventType)
}).print()
env.execute("Login Fail Test")
}
}
//case class LoginEvent(userId: Long, ip: String, eventType: String, eventTime: Long)
恶意登录监控的CEP实现
最新推荐文章于 2022-06-29 17:02:53 发布