blob: 711349a12bb20e81d488756b2fd862262d4c657f [file] [log] [blame]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Apache TomEE</title>
<meta name="description"
content="Apache TomEE is a lightweight, yet powerful, JavaEE Application server with feature rich tooling." />
<meta name="keywords" content="tomee,asf,apache,javaee,jee,shade,embedded,test,junit,applicationcomposer,maven,arquillian" />
<meta name="author" content="Luka Cvetinovic for Codrops" />
<link rel="icon" href="../../favicon.ico">
<link rel="icon" type="image/png" href="../../favicon.png">
<meta name="msapplication-TileColor" content="#80287a">
<meta name="theme-color" content="#80287a">
<link rel="stylesheet" type="text/css" href="../../css/normalize.css">
<link rel="stylesheet" type="text/css" href="../../css/bootstrap.css">
<link rel="stylesheet" type="text/css" href="../../css/owl.css">
<link rel="stylesheet" type="text/css" href="../../css/animate.css">
<link rel="stylesheet" type="text/css" href="../../fonts/font-awesome-4.1.0/css/font-awesome.min.css">
<link rel="stylesheet" type="text/css" href="../../fonts/eleganticons/et-icons.css">
<link rel="stylesheet" type="text/css" href="../../css/jqtree.css">
<link rel="stylesheet" type="text/css" href="../../css/idea.css">
<link rel="stylesheet" type="text/css" href="../../css/cardio.css">
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-2717626-1']);
_gaq.push(['_setDomainName', 'apache.org']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
</head>
<body>
<div class="preloader">
<img src="../../img/loader.gif" alt="Preloader image">
</div>
<nav class="navbar">
<div class="container">
<div class="row"> <div class="col-md-12">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/">
<span>
<img src="../../img/logo-active.png">
</span>
Apache TomEE
</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav navbar-right main-nav">
<li><a href="../../docs.html">Documentation</a></li>
<li><a href="../../community/index.html">Community</a></li>
<li><a href="../../security/security.html">Security</a></li>
<li><a href="../../download-ng.html">Downloads</a></li>
</ul>
</div>
<!-- /.navbar-collapse -->
</div></div>
</div>
<!-- /.container-fluid -->
</nav>
<div id="main-block" class="container main-block">
<div class="row title">
<div class="col-md-12">
<div class='page-header'>
<h1>Webservice Ws Security</h1>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<p><em>Help us document this example! Click the blue pencil icon in the upper right to edit this page.</em></p>
<h2>CalculatorImpl</h2>
<pre><code>package org.superbiz.calculator;
import javax.annotation.security.DeclareRoles;
import javax.annotation.security.RolesAllowed;
import javax.ejb.Stateless;
import javax.jws.WebService;
/**
* This is an EJB 3 style pojo stateless session bean
* Every stateless session bean implementation must be annotated
* using the annotation @Stateless
* This EJB has a single interface: CalculatorWs a webservice interface.
*/
//START SNIPPET: code
@DeclareRoles(value = {&quot;Administrator&quot;})
@Stateless
@WebService(
portName = &quot;CalculatorPort&quot;,
serviceName = &quot;CalculatorWsService&quot;,
targetNamespace = &quot;http://superbiz.org/wsdl&quot;,
endpointInterface = &quot;org.superbiz.calculator.CalculatorWs&quot;)
public class CalculatorImpl implements CalculatorWs, CalculatorRemote {
@RolesAllowed(value = {&quot;Administrator&quot;})
public int sum(int add1, int add2) {
return add1 + add2;
}
public int multiply(int mul1, int mul2) {
return mul1 * mul2;
}
}
</code></pre>
<h2>CalculatorRemote</h2>
<pre><code>package org.superbiz.calculator;
import javax.ejb.Remote;
@Remote
public interface CalculatorRemote {
public int sum(int add1, int add2);
public int multiply(int mul1, int mul2);
}
</code></pre>
<h2>CalculatorWs</h2>
<pre><code>package org.superbiz.calculator;
import javax.jws.WebService;
//END SNIPPET: code
/**
* This is an EJB 3 webservice interface
* A webservice interface must be annotated with the @Local
* annotation.
*/
//START SNIPPET: code
@WebService(targetNamespace = &quot;http://superbiz.org/wsdl&quot;)
public interface CalculatorWs {
public int sum(int add1, int add2);
public int multiply(int mul1, int mul2);
}
</code></pre>
<h2>ejb-jar.xml</h2>
<pre><code>&lt;ejb-jar xmlns=&quot;http://java.sun.com/xml/ns/javaee&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
xsi:schemaLocation=&quot;http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd&quot;
version=&quot;3.0&quot; id=&quot;simple&quot; metadata-complete=&quot;false&quot;&gt;
&lt;enterprise-beans&gt;
&lt;session&gt;
&lt;ejb-name&gt;CalculatorImplTimestamp1way&lt;/ejb-name&gt;
&lt;service-endpoint&gt;org.superbiz.calculator.CalculatorWs&lt;/service-endpoint&gt;
&lt;ejb-class&gt;org.superbiz.calculator.CalculatorImpl&lt;/ejb-class&gt;
&lt;session-type&gt;Stateless&lt;/session-type&gt;
&lt;transaction-type&gt;Container&lt;/transaction-type&gt;
&lt;/session&gt;
&lt;session&gt;
&lt;ejb-name&gt;CalculatorImplTimestamp2ways&lt;/ejb-name&gt;
&lt;service-endpoint&gt;org.superbiz.calculator.CalculatorWs&lt;/service-endpoint&gt;
&lt;ejb-class&gt;org.superbiz.calculator.CalculatorImpl&lt;/ejb-class&gt;
&lt;session-type&gt;Stateless&lt;/session-type&gt;
&lt;transaction-type&gt;Container&lt;/transaction-type&gt;
&lt;/session&gt;
&lt;session&gt;
&lt;ejb-name&gt;CalculatorImplUsernameTokenPlainPassword&lt;/ejb-name&gt;
&lt;service-endpoint&gt;org.superbiz.calculator.CalculatorWs&lt;/service-endpoint&gt;
&lt;ejb-class&gt;org.superbiz.calculator.CalculatorImpl&lt;/ejb-class&gt;
&lt;session-type&gt;Stateless&lt;/session-type&gt;
&lt;transaction-type&gt;Container&lt;/transaction-type&gt;
&lt;/session&gt;
&lt;session&gt;
&lt;ejb-name&gt;CalculatorImplUsernameTokenHashedPassword&lt;/ejb-name&gt;
&lt;service-endpoint&gt;org.superbiz.calculator.CalculatorWs&lt;/service-endpoint&gt;
&lt;ejb-class&gt;org.superbiz.calculator.CalculatorImpl&lt;/ejb-class&gt;
&lt;session-type&gt;Stateless&lt;/session-type&gt;
&lt;transaction-type&gt;Container&lt;/transaction-type&gt;
&lt;/session&gt;
&lt;session&gt;
&lt;ejb-name&gt;CalculatorImplUsernameTokenPlainPasswordEncrypt&lt;/ejb-name&gt;
&lt;service-endpoint&gt;org.superbiz.calculator.CalculatorWs&lt;/service-endpoint&gt;
&lt;ejb-class&gt;org.superbiz.calculator.CalculatorImpl&lt;/ejb-class&gt;
&lt;session-type&gt;Stateless&lt;/session-type&gt;
&lt;transaction-type&gt;Container&lt;/transaction-type&gt;
&lt;/session&gt;
&lt;session&gt;
&lt;ejb-name&gt;CalculatorImplSign&lt;/ejb-name&gt;
&lt;service-endpoint&gt;org.superbiz.calculator.CalculatorWs&lt;/service-endpoint&gt;
&lt;ejb-class&gt;org.superbiz.calculator.CalculatorImpl&lt;/ejb-class&gt;
&lt;session-type&gt;Stateless&lt;/session-type&gt;
&lt;transaction-type&gt;Container&lt;/transaction-type&gt;
&lt;/session&gt;
&lt;session&gt;
&lt;ejb-name&gt;CalculatorImplEncrypt2ways&lt;/ejb-name&gt;
&lt;service-endpoint&gt;org.superbiz.calculator.CalculatorWs&lt;/service-endpoint&gt;
&lt;ejb-class&gt;org.superbiz.calculator.CalculatorImpl&lt;/ejb-class&gt;
&lt;session-type&gt;Stateless&lt;/session-type&gt;
&lt;transaction-type&gt;Container&lt;/transaction-type&gt;
&lt;/session&gt;
&lt;session&gt;
&lt;ejb-name&gt;CalculatorImplSign2ways&lt;/ejb-name&gt;
&lt;service-endpoint&gt;org.superbiz.calculator.CalculatorWs&lt;/service-endpoint&gt;
&lt;ejb-class&gt;org.superbiz.calculator.CalculatorImpl&lt;/ejb-class&gt;
&lt;session-type&gt;Stateless&lt;/session-type&gt;
&lt;transaction-type&gt;Container&lt;/transaction-type&gt;
&lt;/session&gt;
&lt;session&gt;
&lt;ejb-name&gt;CalculatorImplEncryptAndSign2ways&lt;/ejb-name&gt;
&lt;service-endpoint&gt;org.superbiz.calculator.CalculatorWs&lt;/service-endpoint&gt;
&lt;ejb-class&gt;org.superbiz.calculator.CalculatorImpl&lt;/ejb-class&gt;
&lt;session-type&gt;Stateless&lt;/session-type&gt;
&lt;transaction-type&gt;Container&lt;/transaction-type&gt;
&lt;/session&gt;
&lt;/enterprise-beans&gt;
&lt;/ejb-jar&gt;
</code></pre>
<h2>openejb-jar.xml</h2>
<pre><code>&lt;openejb-jar xmlns=&quot;http://www.openejb.org/openejb-jar/1.1&quot;&gt;
&lt;ejb-deployment ejb-name=&quot;CalculatorImpl&quot;&gt;
&lt;properties&gt;
# webservice.security.realm
# webservice.security.securityRealm
# webservice.security.transportGarantee = NONE
webservice.security.authMethod = WS-SECURITY
wss4j.in.action = UsernameToken
wss4j.in.passwordType = PasswordText
wss4j.in.passwordCallbackClass = org.superbiz.calculator.CustomPasswordHandler
# automatically added
wss4j.in.validator.{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}UsernameToken = org.apache.openejb.server.cxf.OpenEJBLoginValidator
&lt;/properties&gt;
&lt;/ejb-deployment&gt;
&lt;ejb-deployment ejb-name=&quot;CalculatorImplTimestamp1way&quot;&gt;
&lt;properties&gt;
webservice.security.authMethod = WS-SECURITY
wss4j.in.action = Timestamp
&lt;/properties&gt;
&lt;/ejb-deployment&gt;
&lt;ejb-deployment ejb-name=&quot;CalculatorImplTimestamp2ways&quot;&gt;
&lt;properties&gt;
webservice.security.authMethod = WS-SECURITY
wss4j.in.action = Timestamp
wss4j.out.action = Timestamp
&lt;/properties&gt;
&lt;/ejb-deployment&gt;
&lt;ejb-deployment ejb-name=&quot;CalculatorImplUsernameTokenPlainPassword&quot;&gt;
&lt;properties&gt;
webservice.security.authMethod = WS-SECURITY
wss4j.in.action = UsernameToken
wss4j.in.passwordType = PasswordText
wss4j.in.passwordCallbackClass=org.superbiz.calculator.CustomPasswordHandler
&lt;/properties&gt;
&lt;/ejb-deployment&gt;
&lt;ejb-deployment ejb-name=&quot;CalculatorImplUsernameTokenHashedPassword&quot;&gt;
&lt;properties&gt;
webservice.security.authMethod = WS-SECURITY
wss4j.in.action = UsernameToken
wss4j.in.passwordType = PasswordDigest
wss4j.in.passwordCallbackClass=org.superbiz.calculator.CustomPasswordHandler
&lt;/properties&gt;
&lt;/ejb-deployment&gt;
&lt;ejb-deployment ejb-name=&quot;CalculatorImplUsernameTokenPlainPasswordEncrypt&quot;&gt;
&lt;properties&gt;
webservice.security.authMethod = WS-SECURITY
wss4j.in.action = UsernameToken Encrypt
wss4j.in.passwordType = PasswordText
wss4j.in.passwordCallbackClass=org.superbiz.calculator.CustomPasswordHandler
wss4j.in.decryptionPropFile = META-INF/CalculatorImplUsernameTokenPlainPasswordEncrypt-server.properties
&lt;/properties&gt;
&lt;/ejb-deployment&gt;
&lt;ejb-deployment ejb-name=&quot;CalculatorImplSign&quot;&gt;
&lt;properties&gt;
webservice.security.authMethod = WS-SECURITY
wss4j.in.action = Signature
wss4j.in.passwordCallbackClass=org.superbiz.calculator.CustomPasswordHandler
wss4j.in.signaturePropFile = META-INF/CalculatorImplSign-server.properties
&lt;/properties&gt;
&lt;/ejb-deployment&gt;
&lt;/openejb-jar&gt;
</code></pre>
<h2>webservices.xml</h2>
<pre><code>&lt;webservices xmlns=&quot;http://java.sun.com/xml/ns/j2ee&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
xsi:schemaLocation=&quot;http://java.sun.com/xml/ns/j2ee
http://www.ibm.com/webservices/xsd/j2ee_web_services_1_1.xsd&quot;
xmlns:ger=&quot;http://ciaows.org/wsdl&quot; version=&quot;1.1&quot;&gt;
&lt;webservice-description&gt;
&lt;webservice-description-name&gt;CalculatorWsService&lt;/webservice-description-name&gt;
&lt;port-component&gt;
&lt;port-component-name&gt;CalculatorImplTimestamp1way&lt;/port-component-name&gt;
&lt;wsdl-port&gt;CalculatorImplTimestamp1way&lt;/wsdl-port&gt;
&lt;service-endpoint-interface&gt;org.superbiz.calculator.CalculatorWs&lt;/service-endpoint-interface&gt;
&lt;service-impl-bean&gt;
&lt;ejb-link&gt;CalculatorImplTimestamp1way&lt;/ejb-link&gt;
&lt;/service-impl-bean&gt;
&lt;/port-component&gt;
&lt;port-component&gt;
&lt;port-component-name&gt;CalculatorImplTimestamp2ways&lt;/port-component-name&gt;
&lt;wsdl-port&gt;CalculatorImplTimestamp2ways&lt;/wsdl-port&gt;
&lt;service-endpoint-interface&gt;org.superbiz.calculator.CalculatorWs&lt;/service-endpoint-interface&gt;
&lt;service-impl-bean&gt;
&lt;ejb-link&gt;CalculatorImplTimestamp2ways&lt;/ejb-link&gt;
&lt;/service-impl-bean&gt;
&lt;/port-component&gt;
&lt;port-component&gt;
&lt;port-component-name&gt;CalculatorImplUsernameTokenPlainPassword&lt;/port-component-name&gt;
&lt;wsdl-port&gt;CalculatorImplUsernameTokenPlainPassword&lt;/wsdl-port&gt;
&lt;service-endpoint-interface&gt;org.superbiz.calculator.CalculatorWs&lt;/service-endpoint-interface&gt;
&lt;service-impl-bean&gt;
&lt;ejb-link&gt;CalculatorImplUsernameTokenPlainPassword&lt;/ejb-link&gt;
&lt;/service-impl-bean&gt;
&lt;/port-component&gt;
&lt;port-component&gt;
&lt;port-component-name&gt;CalculatorImplUsernameTokenHashedPassword&lt;/port-component-name&gt;
&lt;wsdl-port&gt;CalculatorImplUsernameTokenHashedPassword&lt;/wsdl-port&gt;
&lt;service-endpoint-interface&gt;org.superbiz.calculator.CalculatorWs&lt;/service-endpoint-interface&gt;
&lt;service-impl-bean&gt;
&lt;ejb-link&gt;CalculatorImplUsernameTokenHashedPassword&lt;/ejb-link&gt;
&lt;/service-impl-bean&gt;
&lt;/port-component&gt;
&lt;port-component&gt;
&lt;port-component-name&gt;CalculatorImplUsernameTokenPlainPasswordEncrypt&lt;/port-component-name&gt;
&lt;wsdl-port&gt;CalculatorImplUsernameTokenPlainPasswordEncrypt&lt;/wsdl-port&gt;
&lt;service-endpoint-interface&gt;org.superbiz.calculator.CalculatorWs&lt;/service-endpoint-interface&gt;
&lt;service-impl-bean&gt;
&lt;ejb-link&gt;CalculatorImplUsernameTokenPlainPasswordEncrypt&lt;/ejb-link&gt;
&lt;/service-impl-bean&gt;
&lt;/port-component&gt;
&lt;/webservice-description&gt;
&lt;/webservices&gt;
</code></pre>
<h2>CalculatorTest</h2>
<pre><code>package org.superbiz.calculator;
import junit.framework.TestCase;
import org.apache.cxf.binding.soap.saaj.SAAJInInterceptor;
import org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.endpoint.Endpoint;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor;
import org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor;
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.WSPasswordCallback;
import org.apache.ws.security.handler.WSHandlerConstants;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import javax.xml.ws.soap.SOAPBinding;
import java.io.IOException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
public class CalculatorTest extends TestCase {
//START SNIPPET: setup
protected void setUp() throws Exception {
Properties properties = new Properties();
properties.setProperty(Context.INITIAL_CONTEXT_FACTORY, &quot;org.apache.openejb.core.LocalInitialContextFactory&quot;);
properties.setProperty(&quot;openejb.embedded.remotable&quot;, &quot;true&quot;);
new InitialContext(properties);
}
//END SNIPPET: setup
//START SNIPPET: webservice
public void testCalculatorViaWsInterface() throws Exception {
Service calcService = Service.create(new URL(&quot;http://127.0.0.1:4204/CalculatorImpl?wsdl&quot;),
new QName(&quot;http://superbiz.org/wsdl&quot;, &quot;CalculatorWsService&quot;));
assertNotNull(calcService);
CalculatorWs calc = calcService.getPort(CalculatorWs.class);
Client client = ClientProxy.getClient(calc);
Endpoint endpoint = client.getEndpoint();
endpoint.getOutInterceptors().add(new SAAJOutInterceptor());
Map&lt;String, Object&gt; outProps = new HashMap&lt;String, Object&gt;();
outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
outProps.put(WSHandlerConstants.USER, &quot;jane&quot;);
outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
outProps.put(WSHandlerConstants.PW_CALLBACK_REF, new CallbackHandler() {
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
pc.setPassword(&quot;waterfall&quot;);
}
});
WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps);
endpoint.getOutInterceptors().add(wssOut);
assertEquals(10, calc.sum(4, 6));
}
public void testCalculatorViaWsInterfaceWithTimestamp1way() throws Exception {
Service calcService = Service.create(new URL(&quot;http://127.0.0.1:4204/CalculatorImplTimestamp1way?wsdl&quot;),
new QName(&quot;http://superbiz.org/wsdl&quot;, &quot;CalculatorWsService&quot;));
assertNotNull(calcService);
// for debugging (ie. TCPMon)
calcService.addPort(new QName(&quot;http://superbiz.org/wsdl&quot;,
&quot;CalculatorWsService2&quot;), SOAPBinding.SOAP12HTTP_BINDING,
&quot;http://127.0.0.1:8204/CalculatorImplTimestamp1way&quot;);
// CalculatorWs calc = calcService.getPort(
// new QName(&quot;http://superbiz.org/wsdl&quot;, &quot;CalculatorWsService2&quot;),
// CalculatorWs.class);
CalculatorWs calc = calcService.getPort(CalculatorWs.class);
Client client = ClientProxy.getClient(calc);
Endpoint endpoint = client.getEndpoint();
endpoint.getOutInterceptors().add(new SAAJOutInterceptor());
Map&lt;String, Object&gt; outProps = new HashMap&lt;String, Object&gt;();
outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.TIMESTAMP);
WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps);
endpoint.getOutInterceptors().add(wssOut);
assertEquals(12, calc.multiply(3, 4));
}
public void testCalculatorViaWsInterfaceWithTimestamp2ways() throws Exception {
Service calcService = Service.create(new URL(&quot;http://127.0.0.1:4204/CalculatorImplTimestamp2ways?wsdl&quot;),
new QName(&quot;http://superbiz.org/wsdl&quot;, &quot;CalculatorWsService&quot;));
assertNotNull(calcService);
// for debugging (ie. TCPMon)
calcService.addPort(new QName(&quot;http://superbiz.org/wsdl&quot;,
&quot;CalculatorWsService2&quot;), SOAPBinding.SOAP12HTTP_BINDING,
&quot;http://127.0.0.1:8204/CalculatorImplTimestamp2ways&quot;);
// CalculatorWs calc = calcService.getPort(
// new QName(&quot;http://superbiz.org/wsdl&quot;, &quot;CalculatorWsService2&quot;),
// CalculatorWs.class);
CalculatorWs calc = calcService.getPort(CalculatorWs.class);
Client client = ClientProxy.getClient(calc);
Endpoint endpoint = client.getEndpoint();
endpoint.getOutInterceptors().add(new SAAJOutInterceptor());
endpoint.getInInterceptors().add(new SAAJInInterceptor());
Map&lt;String, Object&gt; outProps = new HashMap&lt;String, Object&gt;();
outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.TIMESTAMP);
WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps);
endpoint.getOutInterceptors().add(wssOut);
Map&lt;String, Object&gt; inProps = new HashMap&lt;String, Object&gt;();
inProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.TIMESTAMP);
WSS4JInInterceptor wssIn = new WSS4JInInterceptor(inProps);
endpoint.getInInterceptors().add(wssIn);
assertEquals(12, calc.multiply(3, 4));
}
public void testCalculatorViaWsInterfaceWithUsernameTokenPlainPassword() throws Exception {
Service calcService = Service.create(new URL(&quot;http://127.0.0.1:4204/CalculatorImplUsernameTokenPlainPassword?wsdl&quot;),
new QName(&quot;http://superbiz.org/wsdl&quot;, &quot;CalculatorWsService&quot;));
assertNotNull(calcService);
// for debugging (ie. TCPMon)
calcService.addPort(new QName(&quot;http://superbiz.org/wsdl&quot;,
&quot;CalculatorWsService2&quot;), SOAPBinding.SOAP12HTTP_BINDING,
&quot;http://127.0.0.1:8204/CalculatorImplUsernameTokenPlainPassword&quot;);
// CalculatorWs calc = calcService.getPort(
// new QName(&quot;http://superbiz.org/wsdl&quot;, &quot;CalculatorWsService2&quot;),
// CalculatorWs.class);
CalculatorWs calc = calcService.getPort(CalculatorWs.class);
Client client = ClientProxy.getClient(calc);
Endpoint endpoint = client.getEndpoint();
endpoint.getOutInterceptors().add(new SAAJOutInterceptor());
Map&lt;String, Object&gt; outProps = new HashMap&lt;String, Object&gt;();
outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
outProps.put(WSHandlerConstants.USER, &quot;jane&quot;);
outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
outProps.put(WSHandlerConstants.PW_CALLBACK_REF, new CallbackHandler() {
@Override
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
pc.setPassword(&quot;waterfall&quot;);
}
});
WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps);
endpoint.getOutInterceptors().add(wssOut);
assertEquals(10, calc.sum(4, 6));
}
public void testCalculatorViaWsInterfaceWithUsernameTokenHashedPassword() throws Exception {
Service calcService = Service.create(new URL(&quot;http://127.0.0.1:4204/CalculatorImplUsernameTokenHashedPassword?wsdl&quot;),
new QName(&quot;http://superbiz.org/wsdl&quot;, &quot;CalculatorWsService&quot;));
assertNotNull(calcService);
// for debugging (ie. TCPMon)
calcService.addPort(new QName(&quot;http://superbiz.org/wsdl&quot;,
&quot;CalculatorWsService2&quot;), SOAPBinding.SOAP12HTTP_BINDING,
&quot;http://127.0.0.1:8204/CalculatorImplUsernameTokenHashedPassword&quot;);
// CalculatorWs calc = calcService.getPort(
// new QName(&quot;http://superbiz.org/wsdl&quot;, &quot;CalculatorWsService2&quot;),
// CalculatorWs.class);
CalculatorWs calc = calcService.getPort(CalculatorWs.class);
Client client = ClientProxy.getClient(calc);
Endpoint endpoint = client.getEndpoint();
endpoint.getOutInterceptors().add(new SAAJOutInterceptor());
Map&lt;String, Object&gt; outProps = new HashMap&lt;String, Object&gt;();
outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
outProps.put(WSHandlerConstants.USER, &quot;jane&quot;);
outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_DIGEST);
outProps.put(WSHandlerConstants.PW_CALLBACK_REF, new CallbackHandler() {
@Override
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
pc.setPassword(&quot;waterfall&quot;);
}
});
WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps);
endpoint.getOutInterceptors().add(wssOut);
assertEquals(10, calc.sum(4, 6));
}
public void testCalculatorViaWsInterfaceWithUsernameTokenPlainPasswordEncrypt() throws Exception {
Service calcService = Service.create(new URL(&quot;http://127.0.0.1:4204/CalculatorImplUsernameTokenPlainPasswordEncrypt?wsdl&quot;),
new QName(&quot;http://superbiz.org/wsdl&quot;, &quot;CalculatorWsService&quot;));
assertNotNull(calcService);
// for debugging (ie. TCPMon)
calcService.addPort(new QName(&quot;http://superbiz.org/wsdl&quot;,
&quot;CalculatorWsService2&quot;), SOAPBinding.SOAP12HTTP_BINDING,
&quot;http://127.0.0.1:8204/CalculatorImplUsernameTokenPlainPasswordEncrypt&quot;);
// CalculatorWs calc = calcService.getPort(
// new QName(&quot;http://superbiz.org/wsdl&quot;, &quot;CalculatorWsService2&quot;),
// CalculatorWs.class);
CalculatorWs calc = calcService.getPort(CalculatorWs.class);
Client client = ClientProxy.getClient(calc);
Endpoint endpoint = client.getEndpoint();
endpoint.getOutInterceptors().add(new SAAJOutInterceptor());
Map&lt;String, Object&gt; outProps = new HashMap&lt;String, Object&gt;();
outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN
+ &quot; &quot; + WSHandlerConstants.ENCRYPT);
outProps.put(WSHandlerConstants.USER, &quot;jane&quot;);
outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
outProps.put(WSHandlerConstants.PW_CALLBACK_REF, new CallbackHandler() {
@Override
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
pc.setPassword(&quot;waterfall&quot;);
}
});
outProps.put(WSHandlerConstants.ENC_PROP_FILE, &quot;META-INF/CalculatorImplUsernameTokenPlainPasswordEncrypt-client.properties&quot;);
outProps.put(WSHandlerConstants.ENCRYPTION_USER, &quot;serveralias&quot;);
WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps);
endpoint.getOutInterceptors().add(wssOut);
assertEquals(10, calc.sum(4, 6));
}
public void testCalculatorViaWsInterfaceWithSign() throws Exception {
Service calcService = Service.create(new URL(&quot;http://127.0.0.1:4204/CalculatorImplSign?wsdl&quot;),
new QName(&quot;http://superbiz.org/wsdl&quot;, &quot;CalculatorWsService&quot;));
assertNotNull(calcService);
// for debugging (ie. TCPMon)
calcService.addPort(new QName(&quot;http://superbiz.org/wsdl&quot;,
&quot;CalculatorWsService2&quot;), SOAPBinding.SOAP12HTTP_BINDING,
&quot;http://127.0.0.1:8204/CalculatorImplSign&quot;);
// CalculatorWs calc = calcService.getPort(
// new QName(&quot;http://superbiz.org/wsdl&quot;, &quot;CalculatorWsService2&quot;),
// CalculatorWs.class);
CalculatorWs calc = calcService.getPort(CalculatorWs.class);
Client client = ClientProxy.getClient(calc);
Endpoint endpoint = client.getEndpoint();
endpoint.getOutInterceptors().add(new SAAJOutInterceptor());
Map&lt;String, Object&gt; outProps = new HashMap&lt;String, Object&gt;();
outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.SIGNATURE);
outProps.put(WSHandlerConstants.USER, &quot;clientalias&quot;);
outProps.put(WSHandlerConstants.PW_CALLBACK_REF, new CallbackHandler() {
@Override
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
pc.setPassword(&quot;clientPassword&quot;);
}
});
outProps.put(WSHandlerConstants.SIG_PROP_FILE, &quot;META-INF/CalculatorImplSign-client.properties&quot;);
outProps.put(WSHandlerConstants.SIG_KEY_ID, &quot;IssuerSerial&quot;);
WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps);
endpoint.getOutInterceptors().add(wssOut);
assertEquals(24, calc.multiply(4, 6));
}
//END SNIPPET: webservice
}
</code></pre>
<h2>CustomPasswordHandler</h2>
<pre><code>package org.superbiz.calculator;
import org.apache.ws.security.WSPasswordCallback;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import java.io.IOException;
public class CustomPasswordHandler implements CallbackHandler {
@Override
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
if (pc.getUsage() == WSPasswordCallback.USERNAME_TOKEN) {
// TODO get the password from the users.properties if possible
pc.setPassword(&quot;waterfall&quot;);
} else if (pc.getUsage() == WSPasswordCallback.DECRYPT) {
pc.setPassword(&quot;serverPassword&quot;);
} else if (pc.getUsage() == WSPasswordCallback.SIGNATURE) {
pc.setPassword(&quot;serverPassword&quot;);
}
}
}
</code></pre>
<h1>Running</h1>
<pre><code>generate keys:
do.sun.jdk:
[echo] *** Running on a Sun JDK ***
[echo] generate server keys
[java] Certificate stored in file &lt;/Users/dblevins/examples/webservice-ws-security/target/classes/META-INF/serverKey.rsa&gt;
[echo] generate client keys
[java] Certificate stored in file &lt;/Users/dblevins/examples/webservice-ws-security/target/test-classes/META-INF/clientKey.rsa&gt;
[echo] import client/server public keys in client/server keystores
[java] Certificate was added to keystore
[java] Certificate was added to keystore
do.ibm.jdk:
run:
[echo] Running JDK specific keystore creation target
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running org.superbiz.calculator.CalculatorTest
Apache OpenEJB 4.0.0-beta-1 build: 20111002-04:06
http://tomee.apache.org/
INFO - openejb.home = /Users/dblevins/examples/webservice-ws-security
INFO - openejb.base = /Users/dblevins/examples/webservice-ws-security
INFO - Configuring Service(id=Default Security Service, type=SecurityService, provider-id=Default Security Service)
INFO - Configuring Service(id=Default Transaction Manager, type=TransactionManager, provider-id=Default Transaction Manager)
INFO - Found EjbModule in classpath: /Users/dblevins/examples/webservice-ws-security/target/classes
INFO - Beginning load: /Users/dblevins/examples/webservice-ws-security/target/classes
INFO - Configuring enterprise application: /Users/dblevins/examples/webservice-ws-security/classpath.ear
INFO - Configuring Service(id=Default Stateless Container, type=Container, provider-id=Default Stateless Container)
INFO - Auto-creating a container for bean CalculatorImplTimestamp1way: Container(type=STATELESS, id=Default Stateless Container)
INFO - Enterprise application &quot;/Users/dblevins/examples/webservice-ws-security/classpath.ear&quot; loaded.
INFO - Assembling app: /Users/dblevins/examples/webservice-ws-security/classpath.ear
INFO - Jndi(name=CalculatorImplTimestamp1wayRemote) --&gt; Ejb(deployment-id=CalculatorImplTimestamp1way)
INFO - Jndi(name=global/classpath.ear/simple/CalculatorImplTimestamp1way!org.superbiz.calculator.CalculatorRemote) --&gt; Ejb(deployment-id=CalculatorImplTimestamp1way)
INFO - Jndi(name=global/classpath.ear/simple/CalculatorImplTimestamp1way) --&gt; Ejb(deployment-id=CalculatorImplTimestamp1way)
INFO - Jndi(name=CalculatorImplTimestamp2waysRemote) --&gt; Ejb(deployment-id=CalculatorImplTimestamp2ways)
INFO - Jndi(name=global/classpath.ear/simple/CalculatorImplTimestamp2ways!org.superbiz.calculator.CalculatorRemote) --&gt; Ejb(deployment-id=CalculatorImplTimestamp2ways)
INFO - Jndi(name=global/classpath.ear/simple/CalculatorImplTimestamp2ways) --&gt; Ejb(deployment-id=CalculatorImplTimestamp2ways)
INFO - Jndi(name=CalculatorImplUsernameTokenPlainPasswordRemote) --&gt; Ejb(deployment-id=CalculatorImplUsernameTokenPlainPassword)
INFO - Jndi(name=global/classpath.ear/simple/CalculatorImplUsernameTokenPlainPassword!org.superbiz.calculator.CalculatorRemote) --&gt; Ejb(deployment-id=CalculatorImplUsernameTokenPlainPassword)
INFO - Jndi(name=global/classpath.ear/simple/CalculatorImplUsernameTokenPlainPassword) --&gt; Ejb(deployment-id=CalculatorImplUsernameTokenPlainPassword)
INFO - Jndi(name=CalculatorImplUsernameTokenHashedPasswordRemote) --&gt; Ejb(deployment-id=CalculatorImplUsernameTokenHashedPassword)
INFO - Jndi(name=global/classpath.ear/simple/CalculatorImplUsernameTokenHashedPassword!org.superbiz.calculator.CalculatorRemote) --&gt; Ejb(deployment-id=CalculatorImplUsernameTokenHashedPassword)
INFO - Jndi(name=global/classpath.ear/simple/CalculatorImplUsernameTokenHashedPassword) --&gt; Ejb(deployment-id=CalculatorImplUsernameTokenHashedPassword)
INFO - Jndi(name=CalculatorImplUsernameTokenPlainPasswordEncryptRemote) --&gt; Ejb(deployment-id=CalculatorImplUsernameTokenPlainPasswordEncrypt)
INFO - Jndi(name=global/classpath.ear/simple/CalculatorImplUsernameTokenPlainPasswordEncrypt!org.superbiz.calculator.CalculatorRemote) --&gt; Ejb(deployment-id=CalculatorImplUsernameTokenPlainPasswordEncrypt)
INFO - Jndi(name=global/classpath.ear/simple/CalculatorImplUsernameTokenPlainPasswordEncrypt) --&gt; Ejb(deployment-id=CalculatorImplUsernameTokenPlainPasswordEncrypt)
INFO - Jndi(name=CalculatorImplSignRemote) --&gt; Ejb(deployment-id=CalculatorImplSign)
INFO - Jndi(name=global/classpath.ear/simple/CalculatorImplSign!org.superbiz.calculator.CalculatorRemote) --&gt; Ejb(deployment-id=CalculatorImplSign)
INFO - Jndi(name=global/classpath.ear/simple/CalculatorImplSign) --&gt; Ejb(deployment-id=CalculatorImplSign)
INFO - Jndi(name=CalculatorImplEncrypt2waysRemote) --&gt; Ejb(deployment-id=CalculatorImplEncrypt2ways)
INFO - Jndi(name=global/classpath.ear/simple/CalculatorImplEncrypt2ways!org.superbiz.calculator.CalculatorRemote) --&gt; Ejb(deployment-id=CalculatorImplEncrypt2ways)
INFO - Jndi(name=global/classpath.ear/simple/CalculatorImplEncrypt2ways) --&gt; Ejb(deployment-id=CalculatorImplEncrypt2ways)
INFO - Jndi(name=CalculatorImplSign2waysRemote) --&gt; Ejb(deployment-id=CalculatorImplSign2ways)
INFO - Jndi(name=global/classpath.ear/simple/CalculatorImplSign2ways!org.superbiz.calculator.CalculatorRemote) --&gt; Ejb(deployment-id=CalculatorImplSign2ways)
INFO - Jndi(name=global/classpath.ear/simple/CalculatorImplSign2ways) --&gt; Ejb(deployment-id=CalculatorImplSign2ways)
INFO - Jndi(name=CalculatorImplEncryptAndSign2waysRemote) --&gt; Ejb(deployment-id=CalculatorImplEncryptAndSign2ways)
INFO - Jndi(name=global/classpath.ear/simple/CalculatorImplEncryptAndSign2ways!org.superbiz.calculator.CalculatorRemote) --&gt; Ejb(deployment-id=CalculatorImplEncryptAndSign2ways)
INFO - Jndi(name=global/classpath.ear/simple/CalculatorImplEncryptAndSign2ways) --&gt; Ejb(deployment-id=CalculatorImplEncryptAndSign2ways)
INFO - Jndi(name=CalculatorImplRemote) --&gt; Ejb(deployment-id=CalculatorImpl)
INFO - Jndi(name=global/classpath.ear/simple/CalculatorImpl!org.superbiz.calculator.CalculatorRemote) --&gt; Ejb(deployment-id=CalculatorImpl)
INFO - Jndi(name=global/classpath.ear/simple/CalculatorImpl) --&gt; Ejb(deployment-id=CalculatorImpl)
INFO - Created Ejb(deployment-id=CalculatorImplUsernameTokenHashedPassword, ejb-name=CalculatorImplUsernameTokenHashedPassword, container=Default Stateless Container)
INFO - Created Ejb(deployment-id=CalculatorImpl, ejb-name=CalculatorImpl, container=Default Stateless Container)
INFO - Created Ejb(deployment-id=CalculatorImplSign, ejb-name=CalculatorImplSign, container=Default Stateless Container)
INFO - Created Ejb(deployment-id=CalculatorImplEncryptAndSign2ways, ejb-name=CalculatorImplEncryptAndSign2ways, container=Default Stateless Container)
INFO - Created Ejb(deployment-id=CalculatorImplTimestamp1way, ejb-name=CalculatorImplTimestamp1way, container=Default Stateless Container)
INFO - Created Ejb(deployment-id=CalculatorImplSign2ways, ejb-name=CalculatorImplSign2ways, container=Default Stateless Container)
INFO - Created Ejb(deployment-id=CalculatorImplEncrypt2ways, ejb-name=CalculatorImplEncrypt2ways, container=Default Stateless Container)
INFO - Created Ejb(deployment-id=CalculatorImplUsernameTokenPlainPassword, ejb-name=CalculatorImplUsernameTokenPlainPassword, container=Default Stateless Container)
INFO - Created Ejb(deployment-id=CalculatorImplTimestamp2ways, ejb-name=CalculatorImplTimestamp2ways, container=Default Stateless Container)
INFO - Created Ejb(deployment-id=CalculatorImplUsernameTokenPlainPasswordEncrypt, ejb-name=CalculatorImplUsernameTokenPlainPasswordEncrypt, container=Default Stateless Container)
INFO - Started Ejb(deployment-id=CalculatorImplUsernameTokenHashedPassword, ejb-name=CalculatorImplUsernameTokenHashedPassword, container=Default Stateless Container)
INFO - Started Ejb(deployment-id=CalculatorImpl, ejb-name=CalculatorImpl, container=Default Stateless Container)
INFO - Started Ejb(deployment-id=CalculatorImplSign, ejb-name=CalculatorImplSign, container=Default Stateless Container)
INFO - Started Ejb(deployment-id=CalculatorImplEncryptAndSign2ways, ejb-name=CalculatorImplEncryptAndSign2ways, container=Default Stateless Container)
INFO - Started Ejb(deployment-id=CalculatorImplTimestamp1way, ejb-name=CalculatorImplTimestamp1way, container=Default Stateless Container)
INFO - Started Ejb(deployment-id=CalculatorImplSign2ways, ejb-name=CalculatorImplSign2ways, container=Default Stateless Container)
INFO - Started Ejb(deployment-id=CalculatorImplEncrypt2ways, ejb-name=CalculatorImplEncrypt2ways, container=Default Stateless Container)
INFO - Started Ejb(deployment-id=CalculatorImplUsernameTokenPlainPassword, ejb-name=CalculatorImplUsernameTokenPlainPassword, container=Default Stateless Container)
INFO - Started Ejb(deployment-id=CalculatorImplTimestamp2ways, ejb-name=CalculatorImplTimestamp2ways, container=Default Stateless Container)
INFO - Started Ejb(deployment-id=CalculatorImplUsernameTokenPlainPasswordEncrypt, ejb-name=CalculatorImplUsernameTokenPlainPasswordEncrypt, container=Default Stateless Container)
INFO - Deployed Application(path=/Users/dblevins/examples/webservice-ws-security/classpath.ear)
INFO - Initializing network services
INFO - Creating ServerService(id=httpejbd)
INFO - Creating ServerService(id=cxf)
INFO - Creating ServerService(id=admin)
INFO - Creating ServerService(id=ejbd)
INFO - Creating ServerService(id=ejbds)
INFO - Initializing network services
** Starting Services **
NAME IP PORT
httpejbd 127.0.0.1 4204
admin thread 127.0.0.1 4200
ejbd 127.0.0.1 4201
ejbd 127.0.0.1 4203
-------
Ready!
Tests run: 7, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 4.582 sec
Results :
Tests run: 7, Failures: 0, Errors: 0, Skipped: 0
</code></pre>
</div>
</div>
</div>
<footer>
<div class="container">
<div class="row">
<div class="col-sm-6 text-center-mobile">
<h3 class="white">Be simple. Be certified. Be Tomcat.</h3>
<h5 class="light regular light-white">"A good application in a good server"</h5>
<ul class="social-footer">
<li><a href="https://www.facebook.com/ApacheTomEE/"><i class="fa fa-facebook"></i></a></li>
<li><a href="https://twitter.com/apachetomee"><i class="fa fa-twitter"></i></a></li>
<li><a href="https://plus.google.com/communities/105208241852045684449"><i class="fa fa-google-plus"></i></a></li>
</ul>
</div>
<div class="col-sm-6 text-center-mobile">
<div class="row opening-hours">
<div class="col-sm-3 text-center-mobile">
<h5><a href="../../latest/docs/" class="white">Documentation</a></h5>
<ul class="list-unstyled">
<li><a href="../../latest/docs/admin/configuration/index.html" class="regular light-white">How to configure</a></li>
<li><a href="../../latest/docs/admin/file-layout.html" class="regular light-white">Dir. Structure</a></li>
<li><a href="../../latest/docs/developer/testing/index.html" class="regular light-white">Testing</a></li>
<li><a href="../../latest/docs/admin/cluster/index.html" class="regular light-white">Clustering</a></li>
</ul>
</div>
<div class="col-sm-3 text-center-mobile">
<h5><a href="../../latest/examples/" class="white">Examples</a></h5>
<ul class="list-unstyled">
<li><a href="../../latest/examples/simple-cdi-interceptor.html" class="regular light-white">CDI Interceptor</a></li>
<li><a href="../../latest/examples/rest-cdi.html" class="regular light-white">REST with CDI</a></li>
<li><a href="../../latest/examples/ejb-examples.html" class="regular light-white">EJB</a></li>
<li><a href="../../latest/examples/jsf-managedBean-and-ejb.html" class="regular light-white">JSF</a></li>
</ul>
</div>
<div class="col-sm-3 text-center-mobile">
<h5><a href="../../community/index.html" class="white">Community</a></h5>
<ul class="list-unstyled">
<li><a href="../../community/contributors.html" class="regular light-white">Contributors</a></li>
<li><a href="../../community/social.html" class="regular light-white">Social</a></li>
<li><a href="../../community/sources.html" class="regular light-white">Sources</a></li>
</ul>
</div>
<div class="col-sm-3 text-center-mobile">
<h5><a href="../../security/index.html" class="white">Security</a></h5>
<ul class="list-unstyled">
<li><a href="http://apache.org/security" target="_blank" class="regular light-white">Apache Security</a></li>
<li><a href="http://apache.org/security/projects.html" target="_blank" class="regular light-white">Security Projects</a></li>
<li><a href="http://cve.mitre.org" target="_blank" class="regular light-white">CVE</a></li>
</ul>
</div>
</div>
</div>
</div>
<div class="row bottom-footer text-center-mobile">
<div class="col-sm-12 light-white">
<p>Copyright &copy; 1999-2016 The Apache Software Foundation, Licensed under the Apache License, Version 2.0. Apache TomEE, TomEE, Apache, the Apache feather logo, and the Apache TomEE project logo are trademarks of The Apache Software Foundation. All other marks mentioned may be trademarks or registered trademarks of their respective owners.</p>
</div>
</div>
</div>
</footer>
<!-- Holder for mobile navigation -->
<div class="mobile-nav">
<ul>
<li><a hef="../../latest/docs/admin/index.html">Administrators</a>
<li><a hef="../../latest/docs/developer/index.html">Developers</a>
<li><a hef="../../latest/docs/advanced/index.html">Advanced</a>
<li><a hef="../../community/index.html">Community</a>
</ul>
<a href="#" class="close-link"><i class="arrow_up"></i></a>
</div>
<!-- Scripts -->
<script src="../../js/jquery-1.11.1.min.js"></script>
<script src="../../js/owl.carousel.min.js"></script>
<script src="../../js/bootstrap.min.js"></script>
<script src="../../js/wow.min.js"></script>
<script src="../../js/typewriter.js"></script>
<script src="../../js/jquery.onepagenav.js"></script>
<script src="../../js/tree.jquery.js"></script>
<script src="../../js/highlight.pack.js"></script>
<script src="../../js/main.js"></script>
</body>
</html>