0

I am working on some new functionality for one of our existing Java based web applications. The web app itself is hosted on one of our internal servers and can be accessed via the browser at several computer terminals throughout our facility. The application is for conducting quality checks at various stages of our production process. Currently, users are required to manually login by selecting their userName from a drop down and entering their password before conducting each quality check. In order to speed up the process, I have been asked to implement the reading of a smart card for login.

I have written a utility class using javax.smartcardio and I am able to access the USB card reader terminal plugged into my laptop, read the ATR from the card and use the info to login to the application when I am running the application on my local tomcat7 server. So, on my local machine, everything works great.

Unfortunately, once I deploy the application to our web server, I can no longer detect the card reader terminal as I believe that the Java web application is actually looking for the reader on the machine that it is deployed to.

Is there any way that I can have my java code access a card reader plugged into a remote work station through interaction with the browser?

The web app is written in GWT, and I am using RPC calls to access the back end server side code. Any help is greatly appreciated. The card reader code is quite simple, so I'll post it if that helps:

import java.util.List;

import javax.smartcardio.Card;
import javax.smartcardio.CardTerminal;
import javax.smartcardio.TerminalFactory;

public class SwipeCardUtil 
{

    private static org.apache.log4j.Logger LOGGER  = org.apache.log4j.Logger.getLogger("hwslqc");

    /**
     * @return ATR
     */
    public static String readCardATR()
    {
        String ATR = "";
        try 
        {
            // Show the list of available terminals
            TerminalFactory factory = TerminalFactory.getDefault();

            List<CardTerminal> terminals = factory.terminals().list();
            if (terminals.size() == 0) 
            {
                LOGGER.error("No Swipe Card Terminals Found");
                return null;
            }

            //System.out.println("Terminal: " + terminals.get(0).getName());
            // Get the first terminal in the list
            CardTerminal terminal = terminals.get(0);

            if(terminal.isCardPresent())
            {
                // Establish a connection with the card using
                // "T=0", "T=1", "T=CL" or "*"
                Card theCard = terminal.connect("*");

                // Get ATR
                byte[] baATR = theCard.getATR().getBytes();
                ATR = SwipeCardUtil.byteArrayToHexString(baATR);
                //System.out.println("ATR: " + ATR);
                // Disconnect
                // true: reset the card after disconnecting card.
                theCard.disconnect(true);
             }
            else{
                 return null;
             }

        } 
        catch (Exception ex) {
            LOGGER.error("No Card Reader Connected. Please connect a Card Reader and try again. "+ex.toString());
            ex.printStackTrace();
        }
        return ATR;
    }

    /**
     * @param theBytes
     * @return theByteArray as a hex string
     */
    public static String byteArrayToHexString(byte[] theBytes)          
    {             
        StringBuffer sb = new StringBuffer(theBytes.length * 2);             

        for (int i = 0; i < theBytes.length; i++) 
        {               
            int byteToRead = theBytes[i] & 0xff;               
            if (byteToRead < 16) 
            {                 
                sb.append('0');               
            }               
            sb.append(Integer.toHexString(byteToRead));          
        }             
        return sb.toString().toUpperCase();          
     }
}
steve.westfall
  • 159
  • 1
  • 12
  • Aside from the programming language, this is a possible duplicate of [Write on a NFC tag using simple php form](http://stackoverflow.com/q/22252440/2425802). – Michael Roland Nov 15 '14 at 20:22
  • 1
    While I don't agree that it's a duplicate, I do agree that your answer to that question also answers mine. Its looks like I will need to investigate writing a Java Applet to try and accomplish what I need to do. Thanks for your input Michael. I appreciate it. – steve.westfall Nov 16 '14 at 00:30

1 Answers1

2

Your client is a web browser, and your web app is deployed on a remote server. The only way to get the reader's data from the client is to implement a piece of software running on the client side. There are several ways to do this but many will not run on the client's web browser.

You can try to implement an applet, but chances are high that the applet will not have sufficient rights to access the client's hardware. To elevate the applets privileges it must be signed by a browser trusted CA. That's quite an endeavour.

Another way would be to not use a web browser at all but to implement a rich client software. But that is as much pain as the previous suggestion since the whole productbis based on a thin client/web browser concept.

Maybe you could use a single sign on approach. If the users are on a windows machine and logged on with their account, you could use waffle.

Hannes
  • 2,018
  • 25
  • 32
  • Thanks Hannes, but SSO won't work in this instance as the Windows login for these workstations are set-up by the production line they belong to with several different people needing to login to various screens of the application. It's looking like I will need to try to write a Java Applet and get it signed by a CA. Thanks for your input, I appreciate it. – steve.westfall Nov 16 '14 at 00:34
  • I know this post is 3 years old now but @steve.westfall, what did you end up doing? i have the same issue as you, however Java Applets are not supported anymore. – Benji Weiss Apr 27 '17 at 20:23
  • Hi @Benji Weiss the solution we used was indeed a java applet. Calls to the applet were made using Javascript. We signed it with a self-signed certificate, but also had to use a downgraded version of java to get around the browser security issues. We had to manually accept the security exception at each workstation. The system is a completely internal network firewalled off from any outside internet access. Hope this helps. – steve.westfall Apr 28 '17 at 13:14
  • @steve.westfall ahhh I see. Thanks for the reply. Unfortunately I'm trying to accomplish this by using the Internet and for any user to be able to navigate to my site and utilize smart card features with their own smart card. The more research I do, the closer I get to either a Native application, or a browser plugin – Benji Weiss Apr 28 '17 at 13:16
  • Hi, sorry to bring this up two years later, but since I have done the whole applet thing several years ago, I'm curious as to what the solution to this problem would be nowadays, especially given that applet are no longer supported. Thank you in advance! – Milad Dec 23 '19 at 21:57