.. _oldsamples: Old server-side code samples ============================ Server .. code-block:: java @RestController public class ProcController implements ExternalAuthenticateHandler, MutualAuthenticateHandler { /* This is the private key for SCWS environment creation * (should correspond to the public key for which the webappcert has been generated) * Note: the webappcert is in the javascript code */ private static final String privateKeyPEM = "-----BEGIN RSA PRIVATE KEY-----\r\n" + "MIIBOgIBAAJBAMPMNNpbZZddeT/GTjU0PWuuN9VEGpxXJTAkmZY02o8238fQ2ynt\r\n" + "N40FVl08YksWBO/74XEjU30mAjuaz/FB2kkCAwEAAQJBALoMlsROSLCWD5q8EqCX\r\n" + "rS1e9IrgFfEtFZczkAWc33lo3FnFeFTXSMVCloNCBWU35od4zTOhdRPAWpQ1Mzxi\r\n" + "aCkCIQD9qjKjNvbDXjUcCNqdiJxPDlPGpa78yzyCCUA/+TNwVwIhAMWZoqZO3eWq\r\n" + "SCBTLelVQsg6CwJh9W7vlezvWxUni+ZfAiAopBAg3jmC66EOsMx12OFSOTVq6jiy\r\n" + "/8zd+KV2mnKHWQIgVpZiLZo1piQeAvwwDCUuZGr61Ap08C3QdsjUEssHhOUCIBee\r\n" + "72JZuJeABcv7lHhAWzsiCddVAkdnZKUo6ubaxw3u\r\n" + "-----END RSA PRIVATE KEY-----"; /** * Entry point for generating the signature, for the initial environment creation. * (called by the client between SCWS.findService and SCWS.createEnvironment). * @param rnd the challenge to sign (coming from the client-side SCWS). * @return the cryptogram that will authorize environment creation. */ @GetMapping("/sign_env_challenge") public String signEnvChallenge(String rnd) { try { PrivateKey privateKey; try (PEMParser pemParser = new PEMParser(new StringReader(privateKeyPEM))) { JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC"); Object object = pemParser.readObject(); KeyPair kp = converter.getKeyPair((PEMKeyPair)object); privateKey = kp.getPrivate(); } Signature signer = Signature.getInstance("NONEwithRSA","BC"); signer.initSign(privateKey); signer.update(Hex.decode(rnd)); byte[] signature = signer.sign(); return Hex.toHexString(signature); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e.getMessage(), e); } } /** * Create a {@link SCSSSession} object. * @return the handle of created {@link SCSSSession} object. * @throws SCMException * @throws IOException */ @GetMapping("/init_session") public String startTest() throws SCMException, IOException { final SCSSSession s = new SCSSSession(); return s.getHandle(); } /** * Process session and allow communication between ServerSide SmartCard and ClientSide SmartCard middlewares. * @param id the handle of the {@link SCSSSession} object to communicate with. * @param body the body of HTTP request * @return the result of processed session. * @throws SCMException * @throws IOException */ @PostMapping("/process_session/{id}") public String processSession(@PathVariable String id, @RequestBody String body) throws SCMException, IOException { return SCSSSession.process(id, body); } /** * Execute session. Once {@link SCSSSession} object is created and session is managed with {@link SCSSSession#process}, call this to use methods and attributes from * {@link Token} object. * @param id the handle of {@link SCSSSession} object. * @return some result * @throws SCMException * @throws IOException */ @GetMapping("/exec_session/{id}") public String execSession(@PathVariable String id) throws SCMException, IOException { SCSSSession s = SCSSSession.getSession(id); try { s.init(); /* -------------------------------------------------------------------- */ // here lies the server-side application logic. // Operations are made by calling Token methods on the `s` object. /* -------------------------------------------------------------------- */ } catch (Exception e){ return "Operation failed"; } finally { s.close(); } return "Operation OK"; } } Client .. code-block:: javascript window.webappcert = "4SyF8E6?J4{SVYI)psu*Xb0t#E=1oJdCH}B[Y8){oDbd%GP-L&ZI*KtJl@P?<:t$Tvv[NPS9>6Mqkpnmg^O1Zkn[Zo#czsNjEe:ASWVef!l-I$=e02=*YAmCkmvm1iifG])b[EFTe2>-:Hmk.KPTX9S0CQPVV41h3>S0>QyDEq/Bb?u#Zc^i7v]JDE@jgy@*bbc=59z!woxg6nRpqTxix&o8>5J8D6lzoLkuw=Q8MreUlGfHfBt(&q8!8Eh>BBL.6A)S.&IBkyKcR%$V@Zb$.!0aJjM1A/Rx=u*@Q7W6$kk[zM"; window.connections = []; window.connecting = false; /* boilerplate function for performing a ajax request */ function req(method, url, contents) { return new Promise(function(resolve, reject) { var req = new XMLHttpRequest(); req.onreadystatechange = function () { if (this.readyState === 4) { if (this.status === 200) resolve(req.responseText); else reject(new Error("App server request failed")); } }; req.open(method, url, true); req.send(contents); }); } function reqGet(url) { return req("GET", url); } function reqPost(url, contents) { return req("POST", url, contents); } /* connects to the SCWS, then tries to find smart cards in readers and connect to them */ function init() { /* connecting to SCWS */ console.log("Connecting to SCWS..."); SCWS.findService(window.webappcert).then(function(challenge) { console.log("Connection to SCWS succeeded"); return reqGet("sign_env_challenge?rnd=" + challenge) .then(function(signature) { return SCWS.createEnvironment(signature); }); }).then(function() { console.log("SCWS environment created successfully"); /* check all readers already connected */ var readers = SCWS.readers; if (readers.length == 0) { console.log("No readers found"); } else { for (var i = 0; i < readers.length; i++) checkReader(readers[i]); } document.getElementById("initbtn").style.display = "none"; updateStatus(); /* register event callbacks for checking readers changes */ SCWS.onreaderadded = function(reader) { console.log("Reader inserted: '" + reader.name + "'"); checkReader(reader); } SCWS.onreaderremoved = function(reader) { console.log("Reader removed: '" + reader.name + "'"); checkReader(reader); } SCWS.onreaderstatechanged = function(reader) { console.log("Reader state changed: '" + reader.name + "'"); checkReader(reader); } }).catch(function(err) { console.log("ERROR: " + err.message); }); } function updateStatus() { // update GUI elements to show connection state } /** * Called when a reader needs to be scanned for objects. */ function checkReader(reader) { /* trying to find reader from existing connections */ for (var connidx = 0; connidx < window.connections.length; connidx++) { if (window.connections[connidx].reader == reader) break; } if (connidx == window.connections.length) { if (reader.status == "ok" && reader.cardPresent) { /* reader not found in existing connections, and reader contains card: connecting */ console.log("Connecting to reader '" + reader.name + "'..."); var connection = { reader: reader }; window.connections.push(connection); window.connecting = true; updateStatus(); reader.connect().then(function(token) { connection.token = token; connection.items = []; console.log("Getting objects from reader '" + reader.name + "'..."); return token.getObjects(); }).then(function(items) { connection.items = items; window.connecting = false; updateStatus(); }).catch(function(err) { console.log("ERROR: " + err.message); window.connecting = false; updateStatus(); }); } } else { var conn = connections[connidx]; if (reader.status != "ok" || !reader.cardPresent) { /* reader found in existing connections, but contains no card: removing */ if (conn.token) { console.log("Disconnecting from reader '" + reader.name + "'."); conn.token.disconnect(); } window.connections.splice(connidx, 1); updateStatus(); } } } function showError(err) { document.getElementById("errmsg").textContent = err.message || err; } /* Function that actually opens the server session */ function test() { /* first, create the SCSSSession instance on the server */ reqGet("init_session").then(function(sessHandle) { /* process the session (session handle is used in the URL) */ window.connections[0].token.processServerSession("process_session/" + sessHandle).then(function() { console.log("OK"); /* at that point, the session is fully completed */ }, function() { console.log("error"); }); /* concurrently with the processServerSession call, the REST entry point that actually performs the operation is called, also giving the session handle */ reqGet("exec_session/" + sessHandle).then(function(result) { console.log(result); /* although the REST operation is completed, the session may not be yet finished at that point */ }); }); }