随着網際網路的高速發展,一個應用為了保護使用者的隐私,通常會通過設定使用者名+密碼的驗證方式保證使用者隐私的相對安全,我知道一般網站的登入驗證,通常會設定一個二維碼,通過驗證二維碼,防止惡意軟體通過機械程式,對使用者密碼進行破解,那麼Android裝置如何實作這個功能呢?相信很多開發者對此不屑一顧,因為這樣增加了使用者使用的複雜性,很多軟體是不會這樣設計的,現在我們暫且不談它是不是有用,今天我們重點探讨一下,如何在Android的裝置上實作這個功能。本篇為大家介紹的内容包括:1、使用者連續多次輸錯密碼,增加驗證碼驗證;2、Android如何通過http請求達到與伺服器之間的通訊。好了下面開始我們今天内容的介紹,首先我們先一起來學習一下如何實作使用者連續多次輸錯密碼,增加驗證碼功能。
既然用的到二維碼,那麼Android如何生成二維碼呢?為大家提供一個生成二維碼的類:
//生成二維碼的類
public class BPUtil {
/**
* 用于生成二維碼的字元
*/
private static final char[] CHARS = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'a','b','c','d','e','f','g','h','i','j','k','m','l','n','o','p','q','r','s','t','u','v','w','x','y','z',
'A','B','C','D','E','F','G','H','I','J','K','M','L','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'
};
private static BPUtil bpUtil;
public static BPUtil getInstance() {
if(bpUtil == null)
bpUtil = new BPUtil();
return bpUtil;
}
// width="60" height="30"
// base_padding_left="5"
// range_padding_left="10"
// base_padding_top="15"
// range_padding_top="10"
// codeLength="4"
// line_number="3"
// font_size="20"
//default settings
private static final int DEFAULT_CODE_LENGTH = 4;
private static final int DEFAULT_FONT_SIZE = 20;
private static final int DEFAULT_LINE_NUMBER = 3;
private static final int BASE_PADDING_LEFT = 5, RANGE_PADDING_LEFT = 10, BASE_PADDING_TOP = 15, RANGE_PADDING_TOP = 10;
private static final int DEFAULT_WIDTH = 60, DEFAULT_HEIGHT = 30;
//settings decided by the layout xml
//canvas width and height
private int width = DEFAULT_WIDTH, height = DEFAULT_HEIGHT;
//random word space and pading_top
private int base_padding_left = BASE_PADDING_LEFT, range_padding_left = RANGE_PADDING_LEFT,
base_padding_top = BASE_PADDING_TOP, range_padding_top = RANGE_PADDING_TOP;
//number of chars, lines; font size
private int codeLength = DEFAULT_CODE_LENGTH, line_number = DEFAULT_LINE_NUMBER, font_size = DEFAULT_FONT_SIZE;
//variables
private String code;
private int padding_left, padding_top;
private Random random = new Random();
public Bitmap createBitmap() {
padding_left = 0;
Bitmap bp = Bitmap.createBitmap(width, height, Config.ARGB_8888);
Canvas c = new Canvas(bp);
code = createCode();
c.drawColor(Color.WHITE);
Paint paint = new Paint();
paint.setTextSize(font_size);
for (int i = 0; i < code.length(); i++) {
randomTextStyle(paint);
randomPadding();
c.drawText(code.charAt(i) + "", padding_left, padding_top, paint);
}
for (int i = 0; i < line_number; i++) {
drawLine(c, paint);
}
c.save( Canvas.ALL_SAVE_FLAG );//儲存
c.restore();//
return bp;
}
public String getCode() {
return bpUtil.createCode();
}
private String createCode() {
StringBuilder buffer = new StringBuilder();
for (int i = 0; i < codeLength; i++) {
buffer.append(CHARS[random.nextInt(CHARS.length)]);
}
return buffer.toString();
}
private void drawLine(Canvas canvas, Paint paint) {
int color = randomColor();
int startX = random.nextInt(width);
int startY = random.nextInt(height);
int stopX = random.nextInt(width);
int stopY = random.nextInt(height);
paint.setStrokeWidth(1);
paint.setColor(color);
canvas.drawLine(startX, startY, stopX, stopY, paint);
}
private int randomColor() {
return randomColor(1);
}
private int randomColor(int rate) {
int red = random.nextInt(256) / rate;
int green = random.nextInt(256) / rate;
int blue = random.nextInt(256) / rate;
return Color.rgb(red, green, blue);
}
private void randomTextStyle(Paint paint) {
int color = randomColor();
paint.setColor(color);
paint.setFakeBoldText(random.nextBoolean()); //true為粗體,false為非粗體
float skewX = random.nextInt(11) / 10;
skewX = random.nextBoolean() ? skewX : -skewX;
paint.setTextSkewX(skewX); //float類型參數,負數表示右斜,整數左斜
// paint.setUnderlineText(true); //true為下劃線,false為非下劃
// paint.setStrikeThruText(true); //true為删除線,false為非删除
}
private void randomPadding() {
padding_left += base_padding_left + random.nextInt(range_padding_left);
padding_top = base_padding_top + random.nextInt(range_padding_top);
}
}
有了二維碼,下面我們開始設計我們的功能,這裡先簡單說一下,我們最終要實作的功能:1、使用者正常輸入使用者名+密碼登入;2、當使用者連續3次輸錯密碼,要求使用者之後必須增加驗證碼輸入驗證。下面我們開始功能設計實作,首先是我們的布局檔案:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="${relativePackage}.${activityClass}"
android:orientation="vertical"
>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="@string/yanzheng" />
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<TextView
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/name" />
<EditText
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_weight="6"
android:layout_height="wrap_content"
android:hint="@string/name_new"
android:singleLine="true"
/>
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<TextView
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/password" />
<EditText
android:id="@+id/pass"
android:layout_weight="6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="@string/pass_new"
android:singleLine="true"
/>
</LinearLayout>
<LinearLayout
android:id="@+id/layout_yanzhengma"
android:visibility="gone"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/yanzhengma" />
<TextView
android:id="@+id/rander"
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<EditText
android:id="@+id/rander_input"
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
/>
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<Button
android:id="@+id/get"
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/get" />
<Button
android:id="@+id/post"
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/post" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>
重點的内容來了,我們主Activity代碼,大家先看一下吧:
public class MainActivity extends Activity {
private TextView mytext = null;
private EditText myname = null;//使用者名
private EditText mypass = null;//密碼
private EditText myrander = null;//驗證碼
private Button mygetbutton = null;//Get方式發送Http請求
private Button mypostbutton = null;//Post方式發送Http請求
private LinearLayout myline = null;//控制二維碼的顯示
private static int n = 0;//使用者輸錯密碼次數統計
static String name = null;//使用者輸入的使用者名
static String password = null;//使用者輸入的密碼
private String edit;//使用者輸入使用者輸入的驗證碼
private String code;//驗證碼
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mytext = (TextView)findViewById(R.id.rander);
myname = (EditText)findViewById(R.id.name);
mypass = (EditText)findViewById(R.id.pass);
myrander = (EditText)findViewById(R.id.rander_input);
mygetbutton = (Button)findViewById(R.id.get);
mypostbutton = (Button)findViewById(R.id.post);
myline = (LinearLayout)findViewById(R.id.layout_yanzhengma);
mygetbutton.setOnClickListener(new mygetbutton());
mypostbutton.setOnClickListener(new mypostbutton());
}
class mygetbutton implements OnClickListener{
public void onClick(View v) {
name = myname.getText().toString();
password = mypass.getText().toString();
if(n>=3){//連續三次輸錯密碼
edit = myrander.getText().toString();
boolean boo = captcha (code , edit);
if(boo){
new Thread(new Runnable() {
public void run() {
final boolean flag = SendServer.getsave(name, password);
runOnUiThread(new Runnable() {
public void run() {
if(flag){
Toast.makeText(MainActivity.this, "登入成功", Toast.LENGTH_SHORT).show();
n=0;
}else{
Toast.makeText(MainActivity.this, "登入失敗", Toast.LENGTH_SHORT).show();
n++;
if(n>=3){
myline.setVisibility(View.VISIBLE);
}
}
}
});
}
}).start();
}else{
code = BPUtil.getInstance().getCode().toLowerCase();//生成新的二維碼
mytext.setText(code);//展示在使用者面前
}
}else{
new Thread(new Runnable() {
public void run() {
final boolean flag = SendServer.getsave(name, password);
runOnUiThread(new Runnable() {
public void run() {
if(flag){
Toast.makeText(MainActivity.this, "登入成功", Toast.LENGTH_SHORT).show();
n=0;
}else{
Toast.makeText(MainActivity.this, "登入失敗", Toast.LENGTH_SHORT).show();
n++;
if(n>=3){
myline.setVisibility(1);
code = BPUtil.getInstance().getCode().toLowerCase();
mytext.setText(code);
}
}
}
});
}
}).start();
}
}
}
class mypostbutton implements OnClickListener{
public void onClick(View v) {
name = myname.getText().toString();
password = mypass.getText().toString();
new Thread(new Runnable() {
public void run() {
final boolean flag = SendServer.postsave(name, password);
runOnUiThread(new Runnable() {
@Override
public void run() {
if(flag){
Toast.makeText(MainActivity.this, "登入成功", Toast.LENGTH_SHORT).show();
n=0;
}else{
Toast.makeText(MainActivity.this, "登入失敗", Toast.LENGTH_SHORT).show();
n++;
if(n>=3){
myline.setVisibility(1);
}
}
}
});
}
}).start();
}
}
@SuppressLint("ShowToast")
private boolean captcha (String code , String edit) {
boolean flag = false;
if (code.equals(edit)) {
flag = true;
}else {
flag = false;
Toast.makeText(MainActivity.this, " 驗證碼錯誤", 0).show();
// imageview.setImageBitmap(bitmap);
}
return flag;
}
protected void onRestart() {
super.onRestart();
n=0;
}
protected void onDestroy() {
super.onDestroy();
n=0;
}
}
在這裡簡單介紹一下代碼,因為本篇接下來要為大家分享關于Android發送GET、POST請求的知識,這裡我寫了兩個按鈕,一個用來通過使用GET方式驗證,一個通過使用POST方式驗證,功能上是一緻的。最後請大家注意一下:紅色字型部分,紅色字型部分就是我們通過調用上部二維碼生成類,生成二維碼,然後展示在使用者界面。還有就是:onRestart、onDestroy都是Activity的生命周期函數,這裡将n歸零,友善我們的再次登入體驗。好了到這裡我們的第一部分就完成了,下面我們開始進入我們本篇的下半部分。
關于Android伺服器請求,一般有兩種方式:GET、POST兩種方式,接下來我們就開始一起學習吧。
public class SendServer {
//GET方式請求
public static boolean getsave(String name, String password) {
boolean flag = false;
HttpURLConnection conn = null;
try {
//防止中文亂碼
String username = URLEncoder.encode(name, "UTF-8");
String userpassword = URLEncoder.encode(password, "UTF-8");
URL url = new URL("http://10.20.90.3:8080/Register/ManageServlet?"+"name="+username+"&password="+userpassword);
conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
conn.setReadTimeout(5000);
int responseCode = conn.getResponseCode();
if(responseCode == 200){
InputStream is = conn.getInputStream();
String stu = getStringFromInputStream(is);
if(stu.equals("登入成功")){
flag = true;
}
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally{
if(conn != null){
conn.disconnect(); //關閉連接配接
}
}
return flag;
}
//POST請求
public static boolean postsave(String name, String password) {
boolean flag = false;
HttpURLConnection conn = null;
try {
URL url = new URL("http://10.20.90.3:8080/Register/ManageServlet?");
conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setConnectTimeout(5000);
conn.setReadTimeout(5000);
//post請求參數
String data = "name="+name+"&password="+password;
OutputStream out = conn.getOutputStream();
out.write(data.getBytes());
out.flush();
out.close();
// conn.setRequestProperty("Content-Length", 500);// 内容長度設定為500;請求頭消息格式設定
int respon = conn.getResponseCode();
if(respon == 200){
InputStream is = conn.getInputStream();
String stu = getStringFromInputStream(is);
if(stu.equals("登入成功")){
flag = true;
}
}
} catch (Exception e) {
e.printStackTrace();
}finally{
if(conn != null){
conn.disconnect();
}
}
return flag;
}
//解析服務傳回的請求
private static String getStringFromInputStream(InputStream is) throws Exception{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024*8];
int len = -1;
while((len = is.read(buffer)) != -1){
baos.write(buffer, 0, len);
}
is.close();
String html = new String(baos.toByteArray(), "GBK");//接收伺服器端的資料時,防止出現中文亂碼。
//String html = baos.toString();
baos.close();
return html;
}
}
好了結束了,内容簡單,大家自行了解吧。新手學習,高手交流。