当前位置: 首页 > news >正文

保护自己的MIDlet程序之三:SNProtector

作者:黑洞 文章来源:http://www.j2medev.com/Article/ShowArticle.asp?ArticleID=886

有了前面的基础,现在就开始实现SNProtector。
这回我们对SNProtector又有哪些要求和目标呢?
1。和前面的OnceProtector和TimeProtector一样要使用简单;
2。用户可以在程序里输入用户名和序列号并验证;
3。允许用户试用;
4。允许验证后继续运行程序。

好了,有了目标之后我们如何管理注册码呢?
放在资源里?放在程序里?这两种方法都不方便批量的分发。
哪里呢?我选择jad里面:)

分发的程序的jad里面有两个用户定义字段:
User: cakec
SN: 8180076728b161326ae2cc61b783b451
他们有什么用?看下去就明白了。

大家是不是又想到一个问题,如何可以像前面的两个Protector一样使用简便
只需要判断一下check,又能在用户输入注册码后再继续运行呢?
因为check判断和其它的startApp的初始工作在一个函数里面,难道有什么办法
让函数停止执行?然而如果主进程停止了执行,我又怎么显示输入注册码的界面,
响应用户的输入呢?思考10秒钟然后看我的方案:)

看看你跟我想的是不是一样:利用midlet的生命周期。
大家知道midlet每次pause之后再次切换的时候系统会调用startApp函数,
此时让check通过不就可以了。

ok,下面来看实现:
首先是注册码输入界面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来获取注册信息,所以构造函数是这样:

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

由于我们已经设置了基类Protector为CommandListener,所以需要改造一下基类:
修改Protector的commandAction并增加doCommand函数

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_)
{
。。。
}
}

当用户选择注册的时候,要做的工作就是把用户的输入保存起来。
如果用户选择了试用,就需要一个标志,说明用户要试用。
做完这些工作我们还需要提醒用户暂停程序,然后再恢复程序
以便达到我们重新调用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();
}
}

现在已经把用户输入的注册码保存了起来,在决定命运的check函数里就需要
把保存的信息读出来然后对比判断是否有效,这个就是check函数:

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系统的核心checkCode和generate函数。
generate根据用户名和输入的注册码生成注册序列号
然后checkCode比较生成的注册序列号和验证码得出结论。
大家通过开头的注册码是不是已经知道了,我在这个例子中
简单的使用了md5加密来实现这个过程,下面就是实现:

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;

最后你除了要把开头的两条内容加入jad文件还需要告诉用户一个密码:123456
这个就是cakec的注册密码。

这个SNProtector距离实际应用还有相当距离,因为加密方法太简单,随便生成密码
代入公式把生成的md5码放到SN里面即可,只能象征性的意思一下。如何有更好的加密算法?
这个话题就太大了:)

有意见或建议请联系vmlinuxx@gmail.com,共同学习,共同提高:)

相关文章:

  • 深入学习之前端递归应用
  • 深入学习之浅拷贝
  • 保护自己的MIDlet程序
  • 深入学习之非关系数据库
  • 深入学习之http
  • 实战程序管理器和多语言程序
  • 深入学习之闭包和bind 原型重写
  • 浏览器的渲染过程
  • J2ME-定时器(TimerTask)使用及初探
  • 深入学习之改变this的方法
  • 使用J2MEUnit测试J2ME程序
  • 深入学习之图片预加载 和 闭包新认知
  • NetBeans 4.0创建J2ME手机RSS阅读器
  • J2ME游戏 之 NORMAL-FRAME
  • 深入学习之git操作
  • 【Leetcode】101. 对称二叉树
  • 【从零开始安装kubernetes-1.7.3】2.flannel、docker以及Harbor的配置以及作用
  • 30天自制操作系统-2
  • CentOS6 编译安装 redis-3.2.3
  • java 多线程基础, 我觉得还是有必要看看的
  • Mybatis初体验
  • Ruby 2.x 源代码分析:扩展 概述
  • 跨域
  • 如何打造100亿SDK累计覆盖量的大数据系统
  • 如何用vue打造一个移动端音乐播放器
  • 为视图添加丝滑的水波纹
  • 因为阿里,他们成了“杭漂”
  • 《码出高效》学习笔记与书中错误记录
  • 测评:对于写作的人来说,Markdown是你最好的朋友 ...
  • ​ 全球云科技基础设施:亚马逊云科技的海外服务器网络如何演进
  • #快捷键# 大学四年我常用的软件快捷键大全,教你成为电脑高手!!
  • $var=htmlencode(“‘);alert(‘2“); 的个人理解
  • (带教程)商业版SEO关键词按天计费系统:关键词排名优化、代理服务、手机自适应及搭建教程
  • (附源码)ssm学生管理系统 毕业设计 141543
  • (强烈推荐)移动端音视频从零到上手(上)
  • (转)fock函数详解
  • ./configure、make、make install 命令
  • .NET Core 版本不支持的问题
  • .net oracle 连接超时_Mysql连接数据库异常汇总【必收藏】
  • .Net转前端开发-启航篇,如何定制博客园主题
  • @kafkalistener消费不到消息_消息队列对战之RabbitMq 大战 kafka
  • @RequestMapping处理请求异常
  • []串口通信 零星笔记
  • [1181]linux两台服务器之间传输文件和文件夹
  • [20140403]查询是否产生日志
  • [CTSC2014]企鹅QQ
  • [emacs] CUA的矩形块操作很给力啊
  • [IE9] IE9 Beta崩溃问题解决方案
  • [java基础揉碎]方法的重写/覆盖
  • [JAVA设计模式]第二部分:创建模式
  • [JMS 3] ActiveMQ实现简单的helloworld
  • [js] 正则表达式
  • [Kubernetes]4. 借助腾讯云TKE快速创建Pod、Deployment、Service部署k8s项目
  • [Linux基础开发工具---vim]关于vim的介绍、vim如何配置及vim的基本操作方法
  • [Matlab有限元分析] 2.杆单元有限元分析