有了前面的基礎(chǔ),現(xiàn)在就開始實現(xiàn)SNPRotector。
這回我們對SNProtector又有哪些要求和目標(biāo)呢?
1。和前面的OnceProtector和TimeProtector一樣要使用簡單;
2。用戶可以在程序里輸入用戶名和序列號并驗證;
3。允許用戶試用;
4。允許驗證后繼續(xù)運行程序。
好了,有了目標(biāo)之后我們?nèi)绾喂芾碜源a呢?
放在資源里?放在程序里?這兩種方法都不方便批量的分發(fā)。
哪里呢?我選擇jad里面:)
分發(fā)的程序的jad里面有兩個用戶定義字段:
User: cakec
SN: 8180076728b161326ae2cc61b783b451
他們有什么用?看下去就明白了。
大家是不是又想到一個問題,如何可以像前面的兩個Protector一樣使用簡便
只需要判斷一下check,又能在用戶輸入注冊碼后再繼續(xù)運行呢?
因為check判斷和其它的startApp的初始工作在一個函數(shù)里面,難道有什么辦法
讓函數(shù)停止執(zhí)行?然而如果主進程停止了執(zhí)行,我又怎么顯示輸入注冊碼的界面,
響應(yīng)用戶的輸入呢?思考10秒鐘然后看我的方案:)
看看你跟我想的是不是一樣:利用midlet的生命周期。
大家知道m(xù)idlet每次pause之后再次切換的時候系統(tǒng)會調(diào)用startApp函數(shù),
此時讓check通過不就可以了。
ok,下面來看實現(xiàn):
首先是注冊碼輸入界面SNInputUI:
package vmlinux.app;
import javax.microedition.lcdui.*;
public class SNInputUI extends Form {
TextField tfUser_;
TextField tfSN_;
public SNInputUI()
{
super(StringManager.get("SNInputUI.Title"));
tfUser_=new TextField(StringManager.get("SNInputUI.User"),"",20,TextField.ANY);
tfSN_=new TextField(StringManager.get("SNInputUI.SN"),"",60,TextField.ANY);
this.append(tfUser_);
this.append(tfSN_);
}
public String getUser()
{
return tfUser_.getString();
}
public String getSN()
{
return tfSN_.getString();
}
}
這個沒有難度,不說了。
然后是SNProtector:
我們需要使用新的UI來獲取注冊信息,所以構(gòu)造函數(shù)是這樣:
public SNProtector(MIDlet app)
{
super(app);
ui_=new SNInputUI();
cmdDone_=new Command(StringManager.get("SNProtector.Done"),Command.SCREEN,1);
cmdTry_=new Command(StringManager.get("SNProtector.Try"),Command.SCREEN,2);
ui_.addCommand(cmdDone_);
ui_.addCommand(cmdTry_);
}
由于我們已經(jīng)設(shè)置了基類Protector為CommandListener,所以需要改造一下基類:
修改Protector的commandAction并增加doCommand函數(shù)
public void commandAction(Command c, Displayable d) {
if(c==cmdOK_)
app_.notifyDestroyed();
else
doCommand(c);
}
protected void doCommand(Command c)
{
}
然后在SNProtector重寫doCommand:
protected void doCommand(Command c)
{
if(c==cmdDone_)
{
。。。
}
else if(c==cmdTry_)
{
。。。
}
}
當(dāng)用戶選擇注冊的時候,要做的工作就是把用戶的輸入保存起來。
如果用戶選擇了試用,就需要一個標(biāo)志,說明用戶要試用。
做完這些工作我們還需要提醒用戶暫停程序,然后再恢復(fù)程序
以便達到我們重新調(diào)用startApp的目的。
所以完整的doCommand就是這樣:
protected void doCommand(Command c)
{
if(c==cmdDone_)
{
SNInputUI input=((SNInputUI)ui_);
if(input.getUser().equals(app_.getAppProperty("User")))
{
try
{
RecordStore.deleteRecordStore(SNRMS);
}
catch(Exception ex)
{
//ignore
}
try
{
RecordStore rs=RecordStore.openRecordStore(SNRMS,true);
byte[] buf=input.getSN().getBytes();
rs.addRecord(buf,0,buf.length);
rs.closeRecordStore();
}
catch(Exception ex)
{
System.out.println(ex);
}
showAlert();
}
}
else if(c==cmdTry_)
{
tryit=true;
showAlert();
}
}
現(xiàn)在已經(jīng)把用戶輸入的注冊碼保存了起來,在決定命運的check函數(shù)里就需要
把保存的信息讀出來然后對比判斷是否有效,這個就是check函數(shù):
public boolean check()
{
if(tryit)
{
tryit=false;
return true;
}
boolean r=true;
try
{
RecordStore rs=RecordStore.openRecordStore(SNRMS,true);
RecordEnumeration e=rs.enumerateRecords(null,null,false);
if(e.hasNextElement())
{
r=checkCode(generate(app_.getAppProperty("User"),new String(e.nextRecord())));
}
else
{
r=false;
}
rs.closeRecordStore();
}
catch(Exception ex)
{
r=false;
}
if(!r)
{
showUI();
}
return r;
}
最后就是sn系統(tǒng)的核心checkCode和generate函數(shù)。
generate根據(jù)用戶名和輸入的注冊碼生成注冊序列號
然后checkCode比較生成的注冊序列號和驗證碼得出結(jié)論。
大家通過開頭的注冊碼是不是已經(jīng)知道了,我在這個例子中
簡單的使用了md5加密來實現(xiàn)這個過程,下面就是實現(xiàn):
boolean checkCode(byte[] x)
{
boolean r=true;
byte[] s=getCode();
if(x!=null && s!=null && x.length==s.length)
{
for(int i=0;i<x.length;++i)
if(x[i]!=s[i])
{
r=false;
break;
}
}
else
r=false;
return r;
}
byte[] getCode()
{
String sn=app_.getAppProperty("SN");
if(sn==null)
return null;
else
{
//deserialize sn from text
return sn.getBytes();
}
}
public byte[] generate(String user,String code)
{
String u=app_.getAppProperty("User");
if(u==null !u.equals(user))
return null;
else
{
//compute inner-code from user and code
Md5 md5=new Md5(user+"/r/n"+code+"/r/nvmlinux snprotector");
try
{
md5.processString();
return md5.getStringDigest().getBytes();
}
catch(Exception ex)
{
System.out.println(ex);
return null;
}
}
}
怎么樣,這就是我的SNProtector的工作過程。
使用方法:在startApp開始加入if(!new SNProtector(this).check())return;
最后你除了要把開頭的兩條內(nèi)容加入jad文件還需要告訴用戶一個密碼:123456
這個就是cakec的注冊密碼。
這個SNProtector距離實際應(yīng)用還有相當(dāng)距離,因為加密方法太簡單,隨便生成密碼
代入公式把生成的md5碼放到SN里面即可,只能象征性的意思一下。如何有更好的加密算法?
這個話題就太大了:)
有意見或建議請聯(lián)系vmlinuxx@Gmail.com,共同學(xué)習(xí),共同提高:)
(出處:http://www.companysz.com)
新聞熱點
疑難解答