溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Android本地驗(yàn)證碼的簡(jiǎn)易實(shí)現(xiàn)方法(防止暴力登錄)

發(fā)布時(shí)間:2020-09-23 18:27:43 來(lái)源:腳本之家 閱讀:193 作者:SEU_Calvin 欄目:移動(dòng)開(kāi)發(fā)

0.  前言 

驗(yàn)證碼無(wú)處不在,有人問(wèn)我,你知道達(dá)芬奇密碼下面是什么嗎,對(duì),答案就是達(dá)芬奇驗(yàn)證碼。

驗(yàn)證碼一個(gè)最主要的作用就是防止惡意暴力破解登錄,防止不間斷的登錄嘗試,有人說(shuō)其實(shí)可以在服務(wù)器端對(duì)該終端進(jìn)行登錄間隔檢測(cè),如果間隔太短可以展示拒絕的姿態(tài)。但是還是本地驗(yàn)證碼作用更加實(shí)在,可以減輕服務(wù)器端的壓力。這篇將使用自定義View來(lái)實(shí)現(xiàn)一個(gè)如下效果的簡(jiǎn)易本地驗(yàn)證碼。算是對(duì)自定義View知識(shí)的復(fù)習(xí)吧。

Android本地驗(yàn)證碼的簡(jiǎn)易實(shí)現(xiàn)方法(防止暴力登錄)

1.  布局結(jié)構(gòu) 

<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="確認(rèn)" 
  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中使用了自定義屬性,面試的時(shí)候偶爾也會(huì)被問(wèn)到,其實(shí)并不難。這里使用文字內(nèi)容、顏色和字號(hào)三個(gè)自定義屬性。命名空間別忘了加。

自定義屬性聲明只需要在values目錄下聲明一個(gè)xml文件即可。文件名字不重要,重要的是這個(gè)name屬性,因?yàn)槲覀儠?huì)在自定義控件類中通過(guò)R.styleable.MyView來(lái)找到這個(gè)自定義屬性聲明信息。

<?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類

看一下這個(gè)類的構(gòu)造函數(shù):

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: 
     //二參為默認(rèn)顏色 
     mTextColor = a.getColor(attr, Color.BLACK); 
     break; 
    case R.styleable.MyView_textsize: 
     // 默認(rèn)字體大小為16sp,TypeValue把sp轉(zhuǎn)化為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) { 
    //生成一個(gè)隨機(jī)的四位數(shù)字,并發(fā)送一個(gè)自定義廣播 
    mText = randomText(); 
    postInvalidate(); 
   } 
  }); 
 } 

核心代碼就是解析自定義屬性,并初始化一個(gè)畫(huà)筆,并把解析出來(lái)的字體大小設(shè)置給畫(huà)筆,設(shè)計(jì)點(diǎn)擊時(shí)間,使其被點(diǎn)擊后重新隨機(jī)產(chǎn)生四位數(shù)字驗(yàn)證碼,并使用postInvalidate()刷新界面。最后使用mBound記錄這個(gè)四位數(shù)文本的寬高。

2.  自定義View類中的其他細(xì)節(jié)

@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); 
  } 
 } 

其實(shí)主要還是measure和draw的過(guò)程了。

在onMeasure()方法中最重要的邏輯應(yīng)該就是處理MeasureSpec.AT_MOST的這種情況了,這時(shí)候前面的mBound.width()就起作用了。還有就是不管何種測(cè)量模式,都手動(dòng)處理了padding的情況。

onDraw()方法中首先繪制了一個(gè)黃色矩形作為自定義View的背景,接著根據(jù)自定義屬性中的文字內(nèi)容和顏色繪制四位數(shù)字,最后繪制四條噪聲直線,顏色隨機(jī),并且起始位置和結(jié)束位置也是隨機(jī)產(chǎn)生的。

3.  實(shí)時(shí)改變維護(hù)的正確驗(yàn)證碼

為了驗(yàn)證用戶輸入的驗(yàn)證碼的正確性,需要在MainActivity中維護(hù)一個(gè)變量,在用戶點(diǎn)擊自定義View刷新驗(yàn)證碼時(shí),能夠?qū)崟r(shí)改變這個(gè)變量的值。這里使用自定義廣播實(shí)現(xiàn),在生成一個(gè)隨機(jī)的四位數(shù)字,發(fā)送一個(gè)自定義廣播。

Intent intent = new Intent(); 
intent.setAction("com.seu_calvin.update"); 
intent.putExtra("data", sb.toString()); 
getContext().sendBroadcast(intent); 

接著在MainActivity注冊(cè)一個(gè)廣播接收者即可取得此時(shí)的驗(yàn)證碼信息,在用戶點(diǎn)擊確定按鈕后在拿到EditText中的值與其進(jìn)行對(duì)比即可。這個(gè)邏輯還是比較簡(jiǎn)單的。

以上所述是小編給大家介紹的Android本地驗(yàn)證碼的簡(jiǎn)易實(shí)現(xiàn)方法(防止暴力登錄),希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)億速云網(wǎng)站的支持!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI