Android开发——本地验证码的简易实现(防止暴力登录)

但使书种多,会有岁稔时。这篇文章主要讲述Android开发——本地验证码的简易实现(防止暴力登录)相关的知识,希望能为你提供帮助。
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); } }


【Android开发——本地验证码的简易实现(防止暴力登录)】其实主要还是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中的值与其进行对比即可。这个逻辑还是比较简单的。
笔者水平有限, 如果有问题或者错误请多留言交流。转载请注明出处: http://blog.csdn.net/seu_calvin/article/details/70156547。

    推荐阅读