欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android本地验证码的简易实现方法(防止暴力登录)

程序员文章站 2022-10-24 17:34:46
0.  前言  验证码无处不在,有人问我,你知道达芬奇密码下面是什么吗,对,答案就是达芬奇验证码。 验证码一个最主要的作用就是防止恶意暴力破解登录,...

0.  前言 

验证码无处不在,有人问我,你知道达芬奇密码下面是什么吗,对,答案就是达芬奇验证码。

验证码一个最主要的作用就是防止恶意暴力破解登录,防止不间断的登录尝试,有人说其实可以在服务器端对该终端进行登录间隔检测,如果间隔太短可以展示拒绝的姿态。但是还是本地验证码作用更加实在,可以减轻服务器端的压力。这篇将使用自定义view来实现一个如下效果的简易本地验证码。算是对自定义view知识的复习吧。

Android本地验证码的简易实现方法(防止暴力登录)

1.  布局结构 

<relativelayout xmlns:android="http://schemas.android.com/apk/res/android" 
 xmlns:myattribute="http://schemas.android.com/apk/res-auto" 
 android:layout_width="match_parent" 
 android:layout_height="match_parent" > 
 <com.calvin.verification_code.myview 
  android:layout_width="wrap_content" 
  android:layout_height="wrap_content" 
  android:layout_centerinparent="true" 
  android:padding="10dp" 
  myattribute:text="0 0 0 0 " 
  myattribute:textcolor="#000" 
  myattribute:textsize="40sp" 
  android:id="@+id/myview" /> 
 <edittext 
  android:layout_width="wrap_content" 
  android:layout_height="wrap_content" 
  android:inputtype="number" 
  android:hint="刷新后输入" 
  android:layout_below="@+id/myview" 
  android:layout_centerhorizontal="true" 
  android:layout_margintop="20dp" 
  android:id="@+id/edittext" /> 
 <button 
  android:text="确认" 
  android:layout_width="wrap_content" 
  android:layout_height="wrap_content" 
  android:layout_alignbottom="@+id/edittext" 
  android:layout_alignparentend="true" 
  android:layout_marginend="10dp" 
  android:id="@+id/button" /> 
</relativelayout> 

在自定义控件myview中使用了自定义属性,面试的时候偶尔也会被问到,其实并不难。这里使用文字内容、颜色和字号三个自定义属性。命名空间别忘了加。

自定义属性声明只需要在values目录下声明一个xml文件即可。文件名字不重要,重要的是这个name属性,因为我们会在自定义控件类中通过r.styleable.myview来找到这个自定义属性声明信息。

<?xml version="1.0" encoding="utf-8"?> 
<resources> 
 <declare-styleable name="myview"> 
  <attr name="text" format="string"/> 
  <attr name="textcolor" format="color"/> 
  <attr name="textsize" format="dimension"/> 
 </declare-styleable> 
</resources> 

2.  自定义view类

看一下这个类的构造函数:

public myview(context context, attributeset attrs, int defstyle) { 
  super(context, attrs, defstyle); 
  typedarray a = context.obtainstyledattributes(attrs, r.styleable.myview); 
  for (int i = 0; i < a.getindexcount(); i++) { 
   int attr = a.getindex(i); 
   switch (attr) { 
    case r.styleable.myview_text: 
     mtext = a.getstring(attr); 
     break; 
    case r.styleable.myview_textcolor: 
     //二参为默认颜色 
     mtextcolor = a.getcolor(attr, color.black); 
     break; 
    case r.styleable.myview_textsize: 
     // 默认字体大小为16sp,typevalue把sp转化为px 
     mtextsize = a.getdimensionpixelsize(attr, 
       (int) typedvalue.applydimension(typedvalue.complex_unit_sp, 
         16, getresources().getdisplaymetrics())); 
     break; 
   } 
  } 
  a.recycle(); 
  mpaint = new paint(); 
  mpaint.settextsize(mtextsize); 
  mbound = new rect(); 
  //获得绘制文本的宽和高 
  mpaint.gettextbounds(mtext, 0, mtext.length(), mbound); 
  this.setonclicklistener(new onclicklistener() { 
   @override 
   public void onclick(view v) { 
    //生成一个随机的四位数字,并发送一个自定义广播 
    mtext = randomtext(); 
    postinvalidate(); 
   } 
  }); 
 } 

核心代码就是解析自定义属性,并初始化一个画笔,并把解析出来的字体大小设置给画笔,设计点击时间,使其被点击后重新随机产生四位数字验证码,并使用postinvalidate()刷新界面。最后使用mbound记录这个四位数文本的宽高。

2.  自定义view类中的其他细节

@override  
protected void onmeasure(int widthmeasurespec, int heightmeasurespec) { 
  int width = 0; 
  int height = 0; 
  int specmode = measurespec.getmode(widthmeasurespec); 
  int specsize = measurespec.getsize(widthmeasurespec); 
  switch (specmode) { 
   case measurespec.exactly: 
    width = getpaddingleft() + getpaddingright() + specsize; 
    break; 
   case measurespec.at_most: 
    width = getpaddingleft() + getpaddingright() + mbound.width(); 
    break; 
  } 
  //同样逻辑处理高 
  setmeasureddimension(width, height); 
} 
 @override 
 protected void ondraw(canvas canvas) { 
  mpaint.setcolor(color.yellow); 
  canvas.drawrect(0, 0, getmeasuredwidth(), getmeasuredheight(), mpaint); 
  mpaint.setcolor(mtextcolor); 
  canvas.drawtext(mtext, getwidth() / 2 - mbound.width() / 2, getheight() / 2 + mbound.height() / 2, mpaint); 
  random random = new random(); 
  for(int i = 0; i <= 3; i++){ 
   int temp = random.nextint(colors.length); 
   mpaint.setcolor(colors[temp]); 
   mpaint.setstrokewidth(3); 
   canvas.drawline(randomstartwidth(),randomstartheight(),randomendwidth(),randomendheight(),mpaint); 
  } 
 } 

其实主要还是measure和draw的过程了。

在onmeasure()方法中最重要的逻辑应该就是处理measurespec.at_most的这种情况了,这时候前面的mbound.width()就起作用了。还有就是不管何种测量模式,都手动处理了padding的情况。

ondraw()方法中首先绘制了一个黄色矩形作为自定义view的背景,接着根据自定义属性中的文字内容和颜色绘制四位数字,最后绘制四条噪声直线,颜色随机,并且起始位置和结束位置也是随机产生的。

3.  实时改变维护的正确验证码

为了验证用户输入的验证码的正确性,需要在mainactivity中维护一个变量,在用户点击自定义view刷新验证码时,能够实时改变这个变量的值。这里使用自定义广播实现,在生成一个随机的四位数字,发送一个自定义广播。

intent intent = new intent(); 
intent.setaction("com.seu_calvin.update"); 
intent.putextra("data", sb.tostring()); 
getcontext().sendbroadcast(intent); 

接着在mainactivity注册一个广播接收者即可取得此时的验证码信息,在用户点击确定按钮后在拿到edittext中的值与其进行对比即可。这个逻辑还是比较简单的。

以上所述是小编给大家介绍的android本地验证码的简易实现方法(防止暴力登录),希望对大家有所帮助