| |
JavaCard主应用程序开发教程 |
|
时间: 2003-12-09 来自:yesky |
 |
|
OpenCard框架介绍
智能卡供应商一般不仅提供开发工具箱,而且提供支持读取端应用程序和JavaCard小应用程序的应用程序编程接口。许多供应商支持OpenCard框架( OCF),这是一套基于Java的应用程序编程接口,把一些来自不同的供应商的与读卡器交互的细节隐藏起来。
OpenCard联盟是一群推动OpenCard框架定义与采用的公司,目前OpenCard框架是1.2版本。OCF的目标是提供给主机端应用程序的开发者跨不同的卡片读取器供应商工作的应用编程接口。
OCF为你定义许多标准卡服务。其中两个是FileAccessCardService和SignatureCardService。一个特殊的类型是ApplicationManagerCardService,提供了在卡上安装、注册和删除小应用程序的生命周期管理方法。
当编写一个主机端基于OCF的应用程序时,你基本上要把它分离成两个部分:
1、和终端或者读取器交互的主应用程序对象(初始化OCF,等待卡片插入并且终止OCF),并且能够显露高级的卡片访问方法,例如getBalance ()。
2、一个实现实际的低级通道管理和APDU输入/输出的小应用程序代理。当把APDU细节从应用程序中隐藏起来的时候,这个代理(Proxy)设计模式允许你显露一个面向对象接口。
 Figure 2. OCF应用程序的结构
总之,一个典型的OCF应用程序具有一个或多个main对象,都是在主机上创建,可能再它们的自己执行的线程上。这些main应用程序对象显露了高级的特定应用程序调用,这些最终都被委托给小应用程序代理。它们使用SmartCard对象,这是应用程序到OCF的入口点,启动应用程序来初始化并且关闭OCF,并且等待卡片被插入。main对象可以实现一个CTListener,你不久将看到,这个监听者提供了诸如卡片插入和拔出等事件的异步标志信息。
你可以使用一个同步或者异步模型编写你的应用程序。
在同步模型中,你的主应用程序初始化OCF,然后等待卡片被插入。然后它执行你的main应用程序逻辑,并且在完成的时候关闭OCF:
... try { // Initialize OCF SmartCard.start(); // Wait for a smart card CardRequest cr = new CardRequest(CardRequest.NEWCARD, null, OCFCardAccessor.class); SmartCard myCard = SmartCard.waitForCard(cr);
// Main client work is done here... ...
} catch (Exception e){ // Handle exception } finally { try { // Shut down OCF SmartCard.shutdown(); } catch (Exception e) { e.printStackTrace(); } } ... | 列表⒈一个同步OCF应用程序的典型结构
如果你喜欢使用异步的途径,你的类必须实现CTListener接口,并且,在初始化阶段,注册它自己用于诸如插入和拔出等卡片终端事件的通知。下面的应用程序骨架以初始化OCF和注册监听者开始,然后定义了用于有效事件的回调方法。
public class MyHostSideApp implements CTListener ... public MyHostSideApp() { try { // Initialize the framework SmartCard.start (); // Register this as a Card Terminal Event Listener CardTerminalRegistry.getRegistry().addCTListener(this); } catch (Exception e) { // handle error... } }
public void cardInserted(CardTerminalEvent ctEvent) { ... }
public void cardRemoved(CardTerminalEvent ctEvent) { ... } ... } | 列表2、一个异步OCF应用程序的典型结构
当一张卡片被插入时,运行时间调用cardInserted ()方法,并且当卡片被拔出时,运行时间调用cardRemoved()方法。在下面的代码中,插入卡片初始化小应用程序代理的创建,并且拔出卡片触发小应用程序代理的清除。代码列表还说明了信用卡余额请求代理。
import opencard.core.event.CTListener; import opencard.core.event.CardTerminalEvent; import opencard.core.service.SmartCard; import opencard.core.service.CardService; ...
public class MyHostSideApp implements CTListener { public void MyHostSideApp() { try { // Initialize the framework SmartCard.start (); // Register this as a Card Terminal Event Listener CardTerminalRegistry.getRegistry().addCTListener(this); } catch (Exception e) { // Handle error. ... } }
/** * Card insertion event. Get new card and card service * @param ctEvent The card insertion event. */
public void cardInserted(CardTerminalEvent ctEvent) { try { // Get a SmartCard object card = SmartCard.getSmartCard(ctEvent); // Get the card proxy instance. myCardProxy = (MyCardProxy) card.getCardService(MyCardProxy.class, true); } catch (Exception e) { e.printStackTrace(); } }
/** * Card removal event. Invalidate card and card service. * @param ctEvent The card removal event. */ public synchronized void cardRemoved(CardTerminalEvent ctEvent) { card = null; myCardProxy = null; // Initialize the framework SmartCard.shutdown(); }
/** * Get balance from the smart card. */ public int getBalance() { try { // Get mutex to prevent other Card Services from modifying // data. Delegate the call to the applet proxy. card.beginMutex(); return Integer.parseInt(myCardProxy.getBalance()); } catch (Throwable e) { return 0; } finally { // End mutual exclusion card.endMutex(); } } ... } | 列表⒊一个增强的基于监听者的OCF应用程序
接下来是小应用程序代理的选节。OCF应用程序委托服务调用到小应用程序代理,实现复杂的APDU管理模块:
public class MyCardProxy extends AppletProxy { // My APDU definitions. final static byte MyAPPLET_CLA = (byte)0x80; final static byte VERIFY_INS = (byte)0x20; final static byte GET_BALANCE_INS = (byte) 0x30; final static short GET_BALANCE_RESPONSE_SZ = 2; protected final static int OK = 0x9000; final static short SW_PINVERIFY_FAILED = (short)0x6900;
/** * Reusable command APDU for getting an information * entry field. */
private CommandAPDU getBalanceAPDU = new CommandAPDU(14);
...
/** Application identifier of the BusinessCard applet */
private static final ApplicationID MY_CARD_AID = new ApplicationID(new byte[] { (byte)0xD4, (byte)0x55, (byte)0x00, (byte)0x00, (byte)0x22, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0xFF}); /** * Create a MyCardProxy instance. * * @param scheduler The Scheduler from which channels * have to be obtained. * @param card The SmartCard object to which this * service belongs. * @param blocking Currently not used. * * @throws opencard.core.service.CardServiceException * Thrown when instantiation fails. */
protected void initialize(CardServiceScheduler scheduler, SmartCard card, boolean blocking) throws CardServiceException { super.initialize(MY_CARD_AID, scheduler, card, blocking); try { // Allocate the card channel. This gives us // exclusive access to the card until we release the // channel. allocateCardChannel();
// Get the Card State. ...
} finally { releaseCardChannel(); } }
/** * Gets the balance. * @return The balance. */
public String getBalance() throws CardServiceInvalidCredentialException, CardServiceOperationFailedException, CardServiceInvalidParameterException, CardServiceUnexpectedResponseException, CardServiceException, CardTerminalException { try { allocateCardChannel();
// Set up the command APDU and send it to the card. getBalanceAPDU.setLength(0); getBalanceAPDU.append(MyAPPLET_CLA); // Class getBalanceAPDU.append(GET_BALANCE_INS); // Instr'n getBalanceAPDU.append((byte) 0x00); // P1 getBalanceAPDU.append((byte) 0x00); // P2 getBalanceAPDU.append((byte) 0x00); // Lc getBalanceAPDU.append((byte) 0x00); // Le
// Send command APDU and check the response. ResponseAPDU response = sendCommandAPDU(getCardChannel(), MY_CARD_AID, getBalanceAPDU); switch (response.sw() & 0xFFFF) { case OK : return new String(response.data()); default : throw new CardServiceUnexpectedResponseException("RC=" + response.sw()); } } finally { releaseCardChannel(); } }
... } | 列表4、一个小应用程序代理示例
你可以在OpenCard Framework 1.2 Programmer ' s Guide(http://www.opencard.org/docs/pguide/PGuide.html)中获得更多的关于OCF使用的消息。还引用了OpenCard Framework引用实现(http://www.opencard.org/index-download.shtml)中的示例文件。
本文中未涉及,但是值得一提的是称为Global Platform(http://www.globalplatform.org)的主机端应用程序编程接口。Global Platform Card Committee提供了一组补充Java Card应用程序编程接口的卡片应用程序编程接口,提供了卡片管理特性。这些规范都在2.1.1版本中。
|
|
|
|
|
|
|
|