commit
917eb112ff
19 changed files with 197 additions and 38 deletions
|
@ -35,7 +35,7 @@ public class RSATokenVerifier {
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
throw new VerificationException("Token user was null.");
|
throw new VerificationException("Token user was null.");
|
||||||
}
|
}
|
||||||
if (!realm.equals(token.getAudience())) {
|
if (!realm.equals(token.getIssuer())) {
|
||||||
throw new VerificationException("Token audience doesn't match domain.");
|
throw new VerificationException("Token audience doesn't match domain.");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,7 +72,7 @@ public class RSAVerifierTest {
|
||||||
|
|
||||||
token = new AccessToken();
|
token = new AccessToken();
|
||||||
token.subject("CN=Client")
|
token.subject("CN=Client")
|
||||||
.audience("domain")
|
.issuer("domain")
|
||||||
.addAccess("service").addRole("admin");
|
.addAccess("service").addRole("admin");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,7 +213,7 @@ public class RSAVerifierTest {
|
||||||
public void testTokenAuth() throws Exception {
|
public void testTokenAuth() throws Exception {
|
||||||
token = new AccessToken();
|
token = new AccessToken();
|
||||||
token.subject("CN=Client")
|
token.subject("CN=Client")
|
||||||
.audience("domain")
|
.issuer("domain")
|
||||||
.addAccess("service").addRole("admin").verifyCaller(true);
|
.addAccess("service").addRole("admin").verifyCaller(true);
|
||||||
|
|
||||||
String encoded = new JWSBuilder()
|
String encoded = new JWSBuilder()
|
||||||
|
|
|
@ -85,6 +85,7 @@
|
||||||
<include>org.keycloak:keycloak-wildfly-adapter-dist:zip</include>
|
<include>org.keycloak:keycloak-wildfly-adapter-dist:zip</include>
|
||||||
<include>org.keycloak:keycloak-as7-adapter-dist:zip</include>
|
<include>org.keycloak:keycloak-as7-adapter-dist:zip</include>
|
||||||
<include>org.keycloak:keycloak-eap6-adapter-dist:zip</include>
|
<include>org.keycloak:keycloak-eap6-adapter-dist:zip</include>
|
||||||
|
<include>org.keycloak:keycloak-tomcat7-adapter-dist:zip</include>
|
||||||
</includes>
|
</includes>
|
||||||
<outputDirectory>adapters</outputDirectory>
|
<outputDirectory>adapters</outputDirectory>
|
||||||
</dependencySet>
|
</dependencySet>
|
||||||
|
|
|
@ -26,6 +26,12 @@
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
<type>zip</type>
|
<type>zip</type>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.keycloak</groupId>
|
||||||
|
<artifactId>keycloak-tomcat7-adapter-dist</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<type>zip</type>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<artifactId>keycloak-eap6-adapter-dist</artifactId>
|
<artifactId>keycloak-eap6-adapter-dist</artifactId>
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
<modules>
|
<modules>
|
||||||
<module>modules</module>
|
<module>modules</module>
|
||||||
<module>as7-adapter-zip</module>
|
<module>as7-adapter-zip</module>
|
||||||
|
<module>tomcat7-adapter-zip</module>
|
||||||
<module>eap6-adapter-zip</module>
|
<module>eap6-adapter-zip</module>
|
||||||
<module>wildfly-adapter-zip</module>
|
<module>wildfly-adapter-zip</module>
|
||||||
<module>examples-docs-zip</module>
|
<module>examples-docs-zip</module>
|
||||||
|
|
20
distribution/tomcat7-adapter-zip/assembly.xml
Executable file
20
distribution/tomcat7-adapter-zip/assembly.xml
Executable file
|
@ -0,0 +1,20 @@
|
||||||
|
<assembly>
|
||||||
|
<id>war-dist</id>
|
||||||
|
|
||||||
|
<formats>
|
||||||
|
<format>zip</format>
|
||||||
|
</formats>
|
||||||
|
<includeBaseDirectory>false</includeBaseDirectory>
|
||||||
|
|
||||||
|
<dependencySets>
|
||||||
|
<dependencySet>
|
||||||
|
<unpack>false</unpack>
|
||||||
|
<useTransitiveDependencies>true</useTransitiveDependencies>
|
||||||
|
<useTransitiveFiltering>true</useTransitiveFiltering>
|
||||||
|
<includes>
|
||||||
|
<include>org.keycloak:keycloak-tomcat7-adapter</include>
|
||||||
|
</includes>
|
||||||
|
<outputDirectory></outputDirectory>
|
||||||
|
</dependencySet>
|
||||||
|
</dependencySets>
|
||||||
|
</assembly>
|
53
distribution/tomcat7-adapter-zip/pom.xml
Executable file
53
distribution/tomcat7-adapter-zip/pom.xml
Executable file
|
@ -0,0 +1,53 @@
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<artifactId>keycloak-parent</artifactId>
|
||||||
|
<groupId>org.keycloak</groupId>
|
||||||
|
<version>1.1.0-Alpha1-SNAPSHOT</version>
|
||||||
|
<relativePath>../../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>keycloak-tomcat7-adapter-dist</artifactId>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
<name>Keycloak Tomcat 7 Adapter Distro</name>
|
||||||
|
<description/>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.keycloak</groupId>
|
||||||
|
<artifactId>keycloak-tomcat7-adapter</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-assembly-plugin</artifactId>
|
||||||
|
<version>2.4</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>assemble</id>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>single</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<descriptors>
|
||||||
|
<descriptor>assembly.xml</descriptor>
|
||||||
|
</descriptors>
|
||||||
|
<outputDirectory>
|
||||||
|
target
|
||||||
|
</outputDirectory>
|
||||||
|
<workDirectory>
|
||||||
|
target/assembly/work
|
||||||
|
</workDirectory>
|
||||||
|
<appendAssemblyId>false</appendAssemblyId>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
|
@ -31,6 +31,7 @@
|
||||||
<include>org.keycloak:keycloak-wildfly-adapter-dist:zip</include>
|
<include>org.keycloak:keycloak-wildfly-adapter-dist:zip</include>
|
||||||
<include>org.keycloak:keycloak-as7-adapter-dist:zip</include>
|
<include>org.keycloak:keycloak-as7-adapter-dist:zip</include>
|
||||||
<include>org.keycloak:keycloak-eap6-adapter-dist:zip</include>
|
<include>org.keycloak:keycloak-eap6-adapter-dist:zip</include>
|
||||||
|
<include>org.keycloak:keycloak-tomcat7-adapter-dist:zip</include>
|
||||||
</includes>
|
</includes>
|
||||||
<outputDirectory>adapters</outputDirectory>
|
<outputDirectory>adapters</outputDirectory>
|
||||||
</dependencySet>
|
</dependencySet>
|
||||||
|
|
|
@ -26,6 +26,12 @@
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
<type>zip</type>
|
<type>zip</type>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.keycloak</groupId>
|
||||||
|
<artifactId>keycloak-tomcat7-adapter-dist</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<type>zip</type>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<artifactId>keycloak-eap6-adapter-dist</artifactId>
|
<artifactId>keycloak-eap6-adapter-dist</artifactId>
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
<!ENTITY AdapterConfig SYSTEM "modules/adapter-config.xml">
|
<!ENTITY AdapterConfig SYSTEM "modules/adapter-config.xml">
|
||||||
<!ENTITY JBossAdapter SYSTEM "modules/jboss-adapter.xml">
|
<!ENTITY JBossAdapter SYSTEM "modules/jboss-adapter.xml">
|
||||||
<!ENTITY JavascriptAdapter SYSTEM "modules/javascript-adapter.xml">
|
<!ENTITY JavascriptAdapter SYSTEM "modules/javascript-adapter.xml">
|
||||||
|
<!ENTITY TomcatAdapter SYSTEM "modules/tomcat-adapter.xml">
|
||||||
<!ENTITY InstalledApplications SYSTEM "modules/installed-applications.xml">
|
<!ENTITY InstalledApplications SYSTEM "modules/installed-applications.xml">
|
||||||
<!ENTITY Logout SYSTEM "modules/logout.xml">
|
<!ENTITY Logout SYSTEM "modules/logout.xml">
|
||||||
<!ENTITY SAML SYSTEM "modules/saml.xml">
|
<!ENTITY SAML SYSTEM "modules/saml.xml">
|
||||||
|
@ -83,6 +84,7 @@ This one is short
|
||||||
</para>
|
</para>
|
||||||
&AdapterConfig;
|
&AdapterConfig;
|
||||||
&JBossAdapter;
|
&JBossAdapter;
|
||||||
|
&TomcatAdapter;
|
||||||
&JavascriptAdapter;
|
&JavascriptAdapter;
|
||||||
&InstalledApplications;
|
&InstalledApplications;
|
||||||
&Logout;
|
&Logout;
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
<itemizedlist>
|
<itemizedlist>
|
||||||
<listitem>UserSessionModel JPA and Mongo storage schema has changed as these interfaces have been refactored</listitem>
|
<listitem>UserSessionModel JPA and Mongo storage schema has changed as these interfaces have been refactored</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
Upgrade your adapters as REST API has changed. We're still supporting older adapters for now, but in future
|
Upgrade your adapters. We interpreted JSON Web Token and OIDC ID Token specification incorrectly. 'aud'
|
||||||
versions this backward compatibility will be removed.
|
claim must be the client id, we were storing the realm name in there and validating it.
|
||||||
</listitem>
|
</listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
</sect1>
|
</sect1>
|
||||||
|
|
|
@ -98,7 +98,7 @@
|
||||||
Multitenancy support. You can host and manage multiple realms for multiple organizations.
|
Multitenancy support. You can host and manage multiple realms for multiple organizations.
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
Supports JBoss AS7, EAP 6.x, Wildfly and Pure JavaScript applications. Plans to support Node.js, RAILS, GRAILS, and other non-Java deployments
|
Supports JBoss AS7, EAP 6.x, Wildfly, Tomcat 7 and Pure JavaScript applications. Plans to support Node.js, RAILS, GRAILS, and other non-Java deployments
|
||||||
</listitem>
|
</listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
</para>
|
</para>
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
<section id="jboss-adapter-installation">
|
<section id="jboss-adapter-installation">
|
||||||
<title>Adapter Installation</title>
|
<title>Adapter Installation</title>
|
||||||
<para>
|
<para>
|
||||||
This is a adapter zip file for AS7, EAP, and Wildfly in the <literal>adapters/</literal> directory in the Keycloak
|
There is a adapter zip file for AS7, EAP, and Wildfly in the <literal>adapters/</literal> directory in the Keycloak
|
||||||
distribution.
|
distribution.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
|
@ -135,7 +135,7 @@ public class CustomerService {
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
<section>
|
<section>
|
||||||
<title>Per WAR Configuration</title>
|
<title>Required Per WAR Configuration</title>
|
||||||
<para>
|
<para>
|
||||||
This section describes how to secure a WAR directly by adding config and editing files within your WAR package.
|
This section describes how to secure a WAR directly by adding config and editing files within your WAR package.
|
||||||
</para>
|
</para>
|
||||||
|
|
94
docbook/reference/en/en-US/modules/tomcat-adapter.xml
Executable file
94
docbook/reference/en/en-US/modules/tomcat-adapter.xml
Executable file
|
@ -0,0 +1,94 @@
|
||||||
|
<section id="tomcat-adapter">
|
||||||
|
<title>Tomcat 7 Adapter</title>
|
||||||
|
<para>
|
||||||
|
To be able to secure WAR apps deployed on Tomcat 7 you must install the Keycloak Tomcat 7 adapter
|
||||||
|
into your Tomcat installation. You then have to provide some extra configuration in each WAR you deploy to
|
||||||
|
Tomcat. Let's go over these steps.
|
||||||
|
</para>
|
||||||
|
<section id="tomcat-adapter-installation">
|
||||||
|
<title>Adapter Installation</title>
|
||||||
|
<para>
|
||||||
|
There is a adapter zip file for Tomcat 7 in the <literal>adapters/</literal> directory in the Keycloak appliance
|
||||||
|
or war distribution. You must unzip this file into Tomcat's <literal>lib/</literal> directory. Including
|
||||||
|
adapter's jars within your WEB-INF/lib directory will not work! The Keycloak adapter is implemented as a Valve
|
||||||
|
and valve code must reside in Tomcat's main lib/ directory.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
<programlisting>
|
||||||
|
$ cd $TOMCAT_HOME/lib
|
||||||
|
$ unzip keycloak-tomcat7-adapter-dist.zip
|
||||||
|
</programlisting>
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<title>Required Per WAR Configuration</title>
|
||||||
|
<para>
|
||||||
|
This section describes how to secure a WAR directly by adding config and editing files within your WAR package.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The first thing you must do is create a <literal>META-INF/context.xml</literal> file in your WAR package. This is
|
||||||
|
a Tomcat specific config file and you must define a Keycloak specific Valve.
|
||||||
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
<![CDATA[
|
||||||
|
<Context path="/your-context-path">
|
||||||
|
<Valve className="org.keycloak.adapters.tomcat7.KeycloakAuthenticatorValve"/>
|
||||||
|
</Context>]]>
|
||||||
|
</programlisting>
|
||||||
|
<para>
|
||||||
|
Next you must create
|
||||||
|
a <literal>keycloak.json</literal> adapter config file within the <literal>WEB-INF</literal> directory
|
||||||
|
of your WAR. The format of this config file is describe in the <link linkend='adapter-config'>general adapter configuration</link>
|
||||||
|
section.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Finally you must specify both a <literal>login-config</literal> and use standard servlet security to specify
|
||||||
|
role-base constraints on your URLs. Here's an example:
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
<programlisting>
|
||||||
|
<![CDATA[
|
||||||
|
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
||||||
|
version="3.0">
|
||||||
|
|
||||||
|
<module-name>customer-portal</module-name>
|
||||||
|
|
||||||
|
<security-constraint>
|
||||||
|
<web-resource-collection>
|
||||||
|
<web-resource-name>Customers</web-resource-name>
|
||||||
|
<url-pattern>/*</url-pattern>
|
||||||
|
</web-resource-collection>
|
||||||
|
<auth-constraint>
|
||||||
|
<role-name>user</role-name>
|
||||||
|
</auth-constraint>
|
||||||
|
</security-constraint>
|
||||||
|
|
||||||
|
<security-constraint>
|
||||||
|
<web-resource-collection>
|
||||||
|
<url-pattern>/*</url-pattern>
|
||||||
|
</web-resource-collection>
|
||||||
|
<user-data-constraint>
|
||||||
|
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
|
||||||
|
</user-data-constraint>
|
||||||
|
</security-constraint>
|
||||||
|
|
||||||
|
<login-config>
|
||||||
|
<auth-method>BASIC</auth-method>
|
||||||
|
<realm-name>this is ignored currently/realm-name>
|
||||||
|
</login-config>
|
||||||
|
|
||||||
|
<security-role>
|
||||||
|
<role-name>admin</role-name>
|
||||||
|
</security-role>
|
||||||
|
<security-role>
|
||||||
|
<role-name>user</role-name>
|
||||||
|
</security-role>
|
||||||
|
</web-app>
|
||||||
|
]]>
|
||||||
|
</programlisting>
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
</section>
|
|
@ -18,7 +18,6 @@
|
||||||
<groupId>org.jboss.logging</groupId>
|
<groupId>org.jboss.logging</groupId>
|
||||||
<artifactId>jboss-logging</artifactId>
|
<artifactId>jboss-logging</artifactId>
|
||||||
<version>${jboss.logging.version}</version>
|
<version>${jboss.logging.version}</version>
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
|
|
|
@ -222,7 +222,7 @@ public class TokenManager {
|
||||||
IDToken token = new IDToken();
|
IDToken token = new IDToken();
|
||||||
token.id(KeycloakModelUtils.generateId());
|
token.id(KeycloakModelUtils.generateId());
|
||||||
token.subject(user.getId());
|
token.subject(user.getId());
|
||||||
token.audience(realm.getName());
|
token.audience(claimer.getClientId());
|
||||||
token.issuedNow();
|
token.issuedNow();
|
||||||
token.issuedFor(client.getUsername());
|
token.issuedFor(client.getUsername());
|
||||||
token.issuer(realm.getName());
|
token.issuer(realm.getName());
|
||||||
|
@ -239,7 +239,7 @@ public class TokenManager {
|
||||||
AccessToken token = new AccessToken();
|
AccessToken token = new AccessToken();
|
||||||
token.id(KeycloakModelUtils.generateId());
|
token.id(KeycloakModelUtils.generateId());
|
||||||
token.subject(user.getId());
|
token.subject(user.getId());
|
||||||
token.audience(realm.getName());
|
token.audience(client.getClientId());
|
||||||
token.issuedNow();
|
token.issuedNow();
|
||||||
token.issuedFor(client.getClientId());
|
token.issuedFor(client.getClientId());
|
||||||
token.issuer(realm.getName());
|
token.issuer(realm.getName());
|
||||||
|
@ -343,7 +343,7 @@ public class TokenManager {
|
||||||
idToken = new IDToken();
|
idToken = new IDToken();
|
||||||
idToken.id(KeycloakModelUtils.generateId());
|
idToken.id(KeycloakModelUtils.generateId());
|
||||||
idToken.subject(accessToken.getSubject());
|
idToken.subject(accessToken.getSubject());
|
||||||
idToken.audience(realm.getName());
|
idToken.audience(client.getClientId());
|
||||||
idToken.issuedNow();
|
idToken.issuedNow();
|
||||||
idToken.issuedFor(accessToken.getIssuedFor());
|
idToken.issuedFor(accessToken.getIssuedFor());
|
||||||
idToken.issuer(accessToken.getIssuer());
|
idToken.issuer(accessToken.getIssuer());
|
||||||
|
|
|
@ -107,7 +107,7 @@ public class AuthenticationManager {
|
||||||
token.id(KeycloakModelUtils.generateId());
|
token.id(KeycloakModelUtils.generateId());
|
||||||
token.issuedNow();
|
token.issuedNow();
|
||||||
token.subject(user.getId());
|
token.subject(user.getId());
|
||||||
token.audience(realm.getName());
|
token.issuer(realm.getName());
|
||||||
if (session != null) {
|
if (session != null) {
|
||||||
token.setSessionState(session.getId());
|
token.setSessionState(session.getId());
|
||||||
}
|
}
|
||||||
|
|
|
@ -140,7 +140,7 @@ public class AdminRoot {
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new UnauthorizedException("Bearer token format error");
|
throw new UnauthorizedException("Bearer token format error");
|
||||||
}
|
}
|
||||||
String realmName = token.getAudience();
|
String realmName = token.getIssuer();
|
||||||
RealmManager realmManager = new RealmManager(session);
|
RealmManager realmManager = new RealmManager(session);
|
||||||
RealmModel realm = realmManager.getRealmByName(realmName);
|
RealmModel realm = realmManager.getRealmByName(realmName);
|
||||||
if (realm == null) {
|
if (realm == null) {
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
package org.keycloak.testsuite.tomcat7;
|
|
||||||
|
|
||||||
import org.apache.catalina.Context;
|
|
||||||
import org.apache.catalina.LifecycleException;
|
|
||||||
import org.apache.catalina.startup.Tomcat;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
|
||||||
* @version $Revision: 1 $
|
|
||||||
*/
|
|
||||||
public class TomcatAdapterTest {
|
|
||||||
public void startServer() throws LifecycleException {
|
|
||||||
Tomcat tomcat = new Tomcat();
|
|
||||||
tomcat.setPort(8080);
|
|
||||||
//tomcat.addWebapp()
|
|
||||||
File base = new File(System.getProperty("java.io.tmpdir"));
|
|
||||||
Context rootCtx = tomcat.addContext("/app", base.getAbsolutePath());
|
|
||||||
//Tomcat.addServlet(rootCtx, "dateServlet", new DatePrintServlet());
|
|
||||||
rootCtx.addServletMapping("/date", "dateServlet");
|
|
||||||
tomcat.start();
|
|
||||||
tomcat.getServer().await();
|
|
||||||
}}
|
|
Loading…
Reference in a new issue