一:当一个用户频繁登录失败
用假如用户在短时间内连续登录失败 被认为恶意登录
package com.longinfail
import java.util
import org.apache.flink.api.common.state.{ListState, ListStateDescriptor, ValueState, ValueStateDescriptor}
import org.apache.flink.streaming.api.TimeCharacteristic
import org.apache.flink.streaming.api.functions.KeyedProcessFunction
import org.apache.flink.streaming.api.functions.timestamps.BoundedOutOfOrdernessTimestampExtractor
import org.apache.flink.streaming.api.scala._
import org.apache.flink.streaming.api.windowing.time.Time
import org.apache.flink.util.Collector
import scala.collection.mutable.ListBuffer
//输入数据
case class LogInEvent(userId:Long,ip:String,eventType:String,timestamp:Long)
//输出信息 只要报警信息
case class LoginFailWarning(userId:Long,firstFailTime:Long,lastFailTime:Long,warnigmsg:String)
object LonginFail {
def main(args: Array[String]): Unit = {
val env: StreamExecutionEnvironment = StreamExecutionEnvironment.getExecutionEnvironment
env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime)
val inputstream: DataStream[String] = env.readTextFile(“in/LoginLog.csv”)
val loginStream: DataStream[LogInEvent] = inputstream.map(data => {
val arr: Array[String] = data.split(",")
LogInEvent(arr(0).toLong, arr(1), arr(2), arr(3).toLong)
}).assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractorLogInEvent {
override def extractTimestamp(element: LogInEvent): Long = element.timestamp * 1000L
})
//继续转换 如果2s之内连续登录失败,输出报警信息
loginStream
.keyBy(_.userId)
.process(new LoginFailWarningResult(2)).print() //假如同一用户连续两次登录失败 报警输出
env.execute()
}
}
class LoginFailWarningResult(failTimes: Int) extends KeyedProcessFunction[Long,LogInEvent,LoginFailWarning]{
//保存状态
//定义状态 保存当前所有的登录失败事件 保存定时器的时间戳
lazy val loginFailList: ListState[LogInEvent] = getRuntimeContext.getListState(new ListStateDescriptorLogInEvent)
lazy val timestampState: ValueState[Long] = getRuntimeContext.getState(new ValueStateDescriptorLong)
override def processElement(value: LogInEvent, ctx: KeyedProcessFunction[Long, LogInEvent, LoginFailWarning]#Context, out: Collector[LoginFailWarning]): Unit = {
if(value.eventType ==“fail”){
loginFailList.add(value)
//如果没有定时器 那么注册一个2s的定时器
if(timestampState.value()==0){
val ts: Long = value.timestamp*1000+2000L
ctx.timerService().registerEventTimeTimer(ts)
}
else {
//如果成功 直接清空状态和定时器
ctx.timerService().deleteEventTimeTimer(timestampState.value())
loginFailList.clear()
timestampState.clear()
}
}
}
override def onTimer(timestamp: Long, ctx: KeyedProcessFunction[Long, LogInEvent, LoginFailWarning]#OnTimerContext, out: Collector[LoginFailWarning]): Unit = {
val listBuffer = new ListBufferLogInEvent
val iter: util.Iterator[LogInEvent] = loginFailList.get().iterator()
while(iter.hasNext){
listBuffer+=iter.next()
}
//判断登录失败事件的个数 如果超过上限 就报警
if(listBuffer.length >= failTimes){
out.collect(LonginFail(listBuffer.head.userId,listBuffer.head.timestamp,listBuffer.head.timestamp,
“login fail in 2s for”+listBuffer.length+“times.”
))
}
//清空状态
loginFailList.clear()
timestampState.clear()
}
}