Merge branch 'jetty-9.4.x'

This commit is contained in:
Joakim Erdfelt 2016-07-12 11:44:57 -07:00
commit c3bcce1ce4
9 changed files with 346 additions and 698 deletions

View File

@ -77,7 +77,7 @@ Otherwise, create a `webapps/myapp.xml` file as follows:
==== Avoiding TLD Scans with precompiled JSPs ==== Avoiding TLD Scans with precompiled JSPs
Of course precompiling JSPs is an excellent way to improve the start time of a web application. Of course precompiling JSPs is an excellent way to improve the start time of a web application.
Since jetty 9.2.0, the Apache Jasper JSP implementation has been used and has been augmented to allow the TLD scan to be skipped. As of Jetty 9.2 the Apache Jasper JSP implementation has been used and has been augmented to allow the TLD scan to be skipped.
This can be done by adding a `context-param` to the `web.xml` file (this is done automatically by the Jetty Maven JSPC plugin): This can be done by adding a `context-param` to the `web.xml` file (this is done automatically by the Jetty Maven JSPC plugin):
[source, xml, subs="{sub-order}"] [source, xml, subs="{sub-order}"]

View File

@ -17,41 +17,21 @@
[[configuring-security-authentication]] [[configuring-security-authentication]]
=== Authentication === Authentication
There are two aspects to securing a web application(or context) within There are two aspects to securing a web application(or context) within the Jetty server:
the Jetty server:
Authentication:: Authentication::
The web application can be configured with a mechanism to determine The web application can be configured with a mechanism to determine the identity of the user.
the identity of the user. This is configured by a mix of standard This is configured by a mix of standard declarations and jetty specific mechanisms and is covered in this section.
declarations and jetty specific mechanisms and is covered in this
section.
Authorization:: Authorization::
Once the identify of the user is known (or not known), the web Once the identify of the user is known (or not known), the web application can be configured via standard descriptors with security constraints that declare what resources that user may access.
application can be configured via standard descriptors with security
constraints that declare what resources that user may access.
==== Configuring an Authentication mechanism ==== Configuring an Authentication mechanism
The jetty server supports several standard authentication mechanisms: The jetty server supports several standard authentication mechanisms: http://en.wikipedia.org/wiki/Basic_access_authentication[BASIC]; http://en.wikipedia.org/wiki/Digest_authentication[DIGEST]; http://en.wikipedia.org/wiki/Form-based_authentication[FORM]; CLIENT-CERT; and other mechanisms can be plugged in using the extensible http://docs.oracle.com/cd/E19462-01/819-6717/gcszc/index.html[JASPI] or http://en.wikipedia.org/wiki/SPNEGO[SPNEGO] mechanisms.
http://en.wikipedia.org/wiki/Basic_access_authentication[BASIC];
http://en.wikipedia.org/wiki/Digest_authentication[DIGEST];
http://en.wikipedia.org/wiki/Form-based_authentication[FORM];
CLIENT-CERT; and other mechanisms can be plugged in using the extensible
http://docs.oracle.com/cd/E19462-01/819-6717/gcszc/index.html[JASPI] or
http://en.wikipedia.org/wiki/SPNEGO[SPNEGO] mechanisms.
Internally, configurating an authentication mechanism is done by setting Internally, configuring an authentication mechanism is done by setting an instance of a the link:{JDURL}/org/eclipse/jetty/security/Authenticator.html[Authenticator] interface onto the link:{JDURL}/org/eclipse/jetty/security/SecurityHandler.html[SecurityHandler] of the context, but in most cases it is done by declaring a `< login-config>` element in the standard web.xml descriptor or via annotations.
an instance of a the
link:{JDURL}/org/eclipse/jetty/security/Authenticator.html[Authenticator]
interface onto the
link:{JDURL}/org/eclipse/jetty/security/SecurityHandler.html[SecurityHandler]
of the context, but in most cases it is done by declaring a `<
login-config>` element in the standard web.xml descriptor or via
annotations.
Below is an example taken from the Below is an example taken from the link:{GITBROWSEURL}/tests/test-webapps/test-jetty-webapp/src/main/webapp/WEB-INF/web.xml?h=release-9[jetty-test-webapp web.xml] that configures BASIC authentication:
link:{GITBROWSEURL}/tests/test-webapps/test-jetty-webapp/src/main/webapp/WEB-INF/web.xml?h=release-9[jetty-test-webapp
web.xml] that configures BASIC authentication:
[source, xml, subs="{sub-order}"] [source, xml, subs="{sub-order}"]
---- ----
@ -59,13 +39,10 @@ web.xml] that configures BASIC authentication:
<auth-method>BASIC</auth-method> <auth-method>BASIC</auth-method>
<realm-name>Test Realm</realm-name> <realm-name>Test Realm</realm-name>
</login-config> </login-config>
---- ----
The The link:{GITBROWSEURL}/tests/test-webapps/test-jetty-webapp/src/main/webapp/WEB-INF/web.xml?h=release-9[jetty-test-webapp web.xml] also includes commented out examples of other DIGEST and FORM configuration:
link:{GITBROWSEURL}/tests/test-webapps/test-jetty-webapp/src/main/webapp/WEB-INF/web.xml?h=release-9[jetty-test-webapp
web.xml] also includes commented out examples of other DIGEST and FORM
configuration:
[source, xml, subs="{sub-order}"] [source, xml, subs="{sub-order}"]
---- ----
@ -77,14 +54,11 @@ configuration:
<form-error-page>/logonError.html?param=test</form-error-page> <form-error-page>/logonError.html?param=test</form-error-page>
</form-login-config> </form-login-config>
</login-config> </login-config>
---- ----
With FORM Authentication, you must also configure URLs of pages to With FORM Authentication, you must also configure URLs of pages to generate a login form and handle errors.
generate a login form and handle errors. Below is a simple HTML form Below is a simple HTML form from the link:{GITBROWSEURL}/tests/test-webapps/test-jetty-webapp/src/main/webapp/logon.html?h=release-9[test webapp logon.html]:
from the
link:{GITBROWSEURL}/tests/test-webapps/test-jetty-webapp/src/main/webapp/logon.html?h=release-9[test
webapp logon.html]:
[source, xml, subs="{sub-order}"] [source, xml, subs="{sub-order}"]
---- ----
@ -108,78 +82,49 @@ webapp logon.html]:
</table> </table>
</form> </form>
</HTML> </HTML>
---- ----
The Authentication mechanism declared for a context / web application The Authentication mechanism declared for a context / web application defines how the server obtain authentication credentials from the
defines how the server obtain authentication credentials from the client, but it does not define how the server checks if those credentials are valid.
client, but it does not define how the server checks if those To check credentials, the server and/or context also need to be configured with a link:{JDURL}/org/eclipse/jetty/security/LoginService.html[LoginService] instance, which may be matched by the declared realm-name.
credentials are valid. To check credentials, the server and/or context
also need to be configured with a
link:{JDURL}/org/eclipse/jetty/security/LoginService.html[LoginService]
instance, which may be matched by the declared realm-name.
[[security-realms]] [[security-realms]]
==== Security Realms ==== Security Realms
Security realms allow you to secure your web applications against Security realms allow you to secure your web applications against unauthorized access.
unauthorized access. Protection is based on authentication that Protection is based on authentication that identifies who is requesting access to the webapp and access control that restricts what can be accessed and how it is accessed within the webapp.
identifies who is requesting access to the webapp and access control
that restricts what can be accessed and how it is accessed within the
webapp.
A webapp statically declares its security requirements in its web.xml A webapp statically declares its security requirements in its web.xml file.
file. Authentication is controlled by the <login-config> element. Access Authentication is controlled by the `<login-config>` element.
controls are specified by <security-constraint> and <security-role-ref> Access controls are specified by `<security-constraint>` and `<security-role-ref>` elements.
elements. When a request is received for a protected resource, the web When a request is received for a protected resource, the web container checks if the user performing the request is authenticated, and if the user has a role assignment that permits access to the requested resource.
container checks if the user performing the request is authenticated,
and if the user has a role assignment that permits access to the
requested resource.
The Servlet Specification does not address how the static security The Servlet Specification does not address how the static security information in the `WEB-INF/web.xml` file is mapped to the runtime environment of the container.
information in the `WEB-INF/web.xml` file is mapped to the runtime For Jetty, the link:{JDURL}/org/eclipse/jetty/security/LoginService.html[LoginService] performs this function.
environment of the container. For Jetty, the
link:{JDURL}/org/eclipse/jetty/security/LoginService.html[LoginService]
performs this function.
A LoginService has a unique name, and gives access to information about A LoginService has a unique name, and gives access to information about a set of users.
a set of users. Each user has authentication information (e.g. a Each user has authentication information (e.g. a password) and a set of roles associated with him/herself.
password) and a set of roles associated with him/herself.
You may configure one or many different LoginServices depending on your You may configure one or many different LoginServices depending on your needs.
needs. A single realm would indicate that you wish to share common A single realm would indicate that you wish to share common security information across all of your web applications.
security information across all of your web applications. Distinct Distinct realms allow you to partition your security information webapp by webapp.
realms allow you to partition your security information webapp by
webapp.
When a request to a web application requires authentication or When a request to a web application requires authentication or authorization, Jetty will use the `<realm-name>` sub-element inside `<login-config>` element in the web.xml file to perform an _exact match_ to a LoginService.
authorization, Jetty will use the <realm-name> sub-element inside
<login-config> element in the web.xml file to perform an _exact match_
to a LoginService.
==== Scoping Security Realms ==== Scoping Security Realms
A LoginService has a unique name, and is composed of a set of users. A LoginService has a unique name, and is composed of a set of users. Each user has authentication information (for example, a password) and a set of roles associated with him/herself.
Each user has authentication information (for example, a password) and a You can configure one or many different realms depending on your needs.
set of roles associated with him/herself. You can configure one or many
different realms depending on your needs.
* Configure a single LoginService to share common security information * Configure a single LoginService to share common security information across all of your web applications.
across all of your web applications. * Configure distinct LoginServices to partition your security information webapp by webapp.
* Configure distinct LoginServices to partition your security
information webapp by webapp.
===== Globally Scoped ===== Globally Scoped
A LoginService is available to all web applications on a Server instance A LoginService is available to all web applications on a Server instance if you add it as a bean to the Server.
if you add it as a bean to the Server. Such a definition would go into Such a definition would go into an xml file in your `${jetty.base}/etc` directory, e.g. `${jetty.base}/etc/my-realm.xml` and you would add this xml file to the execution path via `start.ini` or `start.d` (you may want to review the material in the link:#startup[Starting Jetty] chapter).
an xml file in your $\{jetty.base}/etc directory, eg Here's an example of an xml file that defines an in-memory type of LoginService called the link:{JDURL}/org/eclipse/jetty/security/HashLoginService.html[HashLoginService]:
$\{jetty.base}/etc/my-realm.xml and you would add this xml file to the
execution path via start.ini or start.d (you may want to review the
material in the link:#startup[Starting Jetty] chapter). Here's an
example of an xml file that defines an in-memory type of LoginService
called the
link:{JDURL}/org/eclipse/jetty/security/HashLoginService.html[HashLoginService]:
[source, xml, subs="{sub-order}"] [source, xml, subs="{sub-order}"]
---- ----
@ -196,14 +141,12 @@ link:{JDURL}/org/eclipse/jetty/security/HashLoginService.html[HashLoginService]:
</Call> </Call>
</Configure> </Configure>
---- ----
If you define more than one LoginService on a Server, you will need to If you define more than one LoginService on a Server, you will need to specify which one you want used for each context.
specify which one you want used for each context. You can do that by You can do that by telling the context the name of the LoginService, or passing it the LoginService instance.
telling the context the name of the LoginService, or passing it the Here's an example of doing both of these, using a link:#deployable-descriptor-file[context xml file]:
LoginService instance. Here's an example of doing both of these, using a
link:#deployable-descriptor-file[context xml file]:
[source, xml, subs="{sub-order}"] [source, xml, subs="{sub-order}"]
---- ----
@ -216,20 +159,19 @@ link:#deployable-descriptor-file[context xml file]:
<Set name="name">Test Realm</Set> <Set name="name">Test Realm</Set>
</New> </New>
</Set> </Set>
<!-- or if you defined a LoginService called "Test Realm" in jetty.xml : --> <!-- or if you defined a LoginService called "Test Realm" in jetty.xml : -->
<Set name="realmName">Test Realm</Set> <Set name="realmName">Test Realm</Set>
</Get> </Get>
---- ----
===== Per-Webapp Scoped ===== Per-Webapp Scoped
Alternatively, you can define a LoginService for just a single web Alternatively, you can define a LoginService for just a single web application.
application. Here's how to define the same HashLoginService, but inside Here's how to define the same HashLoginService, but inside a link:#deployable-descriptor-file[context xml file]:
a link:#deployable-descriptor-file[context xml file]:
[source, xml, subs="{sub-order}"] [source, xml, subs="{sub-order}"]
---- ----
@ -247,67 +189,47 @@ a link:#deployable-descriptor-file[context xml file]:
</Get> </Get>
</Configure> </Configure>
---- ----
Jetty provides a number of different LoginService types which can be Jetty provides a number of different LoginService types which can be seen in the next section.
seen in the next section.
[[configuring-login-service]] [[configuring-login-service]]
==== Configuring a LoginService ==== Configuring a LoginService
A A link:{JDURL}/org/eclipse/jetty/security/LoginService.html[LoginService] instance is required by each context/webapp that has a authentication mechanism, which is used to check the validity of the username and credentials collected by the authentication mechanism. Jetty provides the following implementations of LoginService:
link:{JDURL}/org/eclipse/jetty/security/LoginService.html[LoginService]
instance is required by each context/webapp that has a authentication
mechanism, which is used to check the validity of the username and
credentials collected by the authentication mechanism. Jetty provides
the following implementations of LoginService:
link:{JDURL}/org/eclipse/jetty/security/HashLoginService.html[HashLoginService]:: link:{JDURL}/org/eclipse/jetty/security/HashLoginService.html[HashLoginService]::
A user realm that is backed by a hash map that is filled either A user realm that is backed by a hash map that is filled either programatically or from a Java properties file.
programatically or from a java properties file.
link:{JDURL}/org/eclipse/jetty/security/JDBCLoginService.html[JDBCLoginService]:: link:{JDURL}/org/eclipse/jetty/security/JDBCLoginService.html[JDBCLoginService]::
Uses a JDBC connection to an SQL database for authentication Uses a JDBC connection to an SQL database for authentication
link:{JDURL}/org/eclipse/jetty/plus/security/DataSourceLoginService.html[DataSourceLoginService]:: link:{JDURL}/org/eclipse/jetty/plus/security/DataSourceLoginService.html[DataSourceLoginService]::
Uses a JNDI defined Uses a JNDI defined http://docs.oracle.com/javase/7/docs/api/javax/sql/DataSource.html[DataSource] for authentication
http://docs.oracle.com/javase/7/docs/api/javax/sql/DataSource.html[DataSource]
for authentication
link:{JDURL}/org/eclipse/jetty/jaas/JAASLoginService.html[JAASLoginService]:: link:{JDURL}/org/eclipse/jetty/jaas/JAASLoginService.html[JAASLoginService]::
Uses a Uses a http://en.wikipedia.org/wiki/Java_Authentication_and_Authorization_Service[JAAS] provider for authentication; see the section on
http://en.wikipedia.org/wiki/Java_Authentication_and_Authorization_Service[JAAS] link:#jaas-support[JAAS support] for more information
provider for authentication, See the section on
link:#jaas-support[JAAS support] for more information.
link:{JDURL}/org/eclipse/jetty/security/SpnegoLoginService.html[SpnegoLoginService]:: link:{JDURL}/org/eclipse/jetty/security/SpnegoLoginService.html[SpnegoLoginService]::
http://en.wikipedia.org/wiki/SPNEGO[SPNEGO] Authentication, See the http://en.wikipedia.org/wiki/SPNEGO[SPNEGO] Authentication; see the section on link:#spnego-support[SPNEGO support] for more information.
section on link:#spnego-support[SPNEGO support] for more information.
An instance of a LoginService can be matched to a context/webapp either An instance of a LoginService can be matched to a context/webapp by:
by:
* A LoginService instance may be set directly on the SecurityHandler * A LoginService instance may be set directly on the SecurityHandler instance via embedded code or IoC XML
instance via embedded code or IoC XML * Matching the realm-name defined in web.xml with the name of a LoginService instance that has been added to the Server instance as a dependent bean
* Matching the realm-name defined in web.xml with the name of a * If only a single LoginService instance has been set on the Server then it is used as the login service for the context
LoginService instance that has been added to the Server instance as a
dependent bean.
* If only a single LoginService instance has been set on the Server then
it is used as the login service for the context.
[[hash-login-service]] [[hash-login-service]]
===== HashLoginService ===== HashLoginService
The HashLoginService is a simple and efficient login service that loads The HashLoginService is a simple and efficient login service that loads usernames, credentials and roles from a Java properties file in the format:
usernames, credentials and roles from a java properties file in the
format:
[source,properties] [source,properties]
---- ----
username: password[,rolename ...] username: password[,rolename ...]
---- ----
where: Where:
username:: username::
is the user's unique identity is the user's unique identity
@ -325,11 +247,9 @@ admin: CRYPT:ad1ks..kc.1Ug,server-administrator,content-administrator,admin
other: OBF:1xmk1w261u9r1w1c1xmq other: OBF:1xmk1w261u9r1w1c1xmq
guest: guest,read-only guest: guest,read-only
---- ----
You configure the HashLoginService with a name and a reference to the You configure the HashLoginService with a name and a reference to the location of the properties file:
location of the properties file:
[source, xml, subs="{sub-order}"] [source, xml, subs="{sub-order}"]
---- ----
@ -341,12 +261,10 @@ location of the properties file:
</New> </New>
</Item> </Item>
---- ----
You can also configure it to check the properties file regularly for You can also configure it to check the properties file regularly for changes and reload when changes are detected.
changes and reload when changes are detected. The reloadInterval is in The `reloadInterval` is in seconds:
seconds:
[source, xml, subs="{sub-order}"] [source, xml, subs="{sub-order}"]
---- ----
@ -357,17 +275,15 @@ seconds:
<Set name="reloadInterval">5</Set> <Set name="reloadInterval">5</Set>
<Call name="start"></Call> <Call name="start"></Call>
</New> </New>
---- ----
[[jdbc-login-service]] [[jdbc-login-service]]
===== JDBCLoginService ===== JDBCLoginService
In this implementation, authentication and role information is stored in In this implementation, authentication and role information is stored in a database accessed via JDBC.
a database accessed via JDBC. A properties file defines the JDBC A properties file defines the JDBC connection and database table information.
connection and database table information. Here is an example of a Here is an example of a properties file for this realm implementation:
properties file for this realm implementation:
[source,properties] [source,properties]
---- ----
@ -388,7 +304,6 @@ userroletableuserkey = user_id
userroletablerolekey = role_id userroletablerolekey = role_id
cachetime = 300 cachetime = 300
---- ----
The format of the database tables is (pseudo-sql): The format of the database tables is (pseudo-sql):
@ -415,7 +330,6 @@ roles
role varchar(100) NOT NULL UNIQUE KEY role varchar(100) NOT NULL UNIQUE KEY
); );
---- ----
Where: Where:
@ -442,13 +356,9 @@ id::
role:: role::
a human-readable name for a role a human-readable name for a role
If you want to use obfuscated, MD5 hashed or encrypted passwords the If you want to use obfuscated, MD5 hashed or encrypted passwords the `pwd` column of the `users` table must be large enough to hold the obfuscated, hashed or encrypted password text plus the appropriate prefix.
'pwd' column of the 'users' table must be large enough to hold the
obfuscated, hashed or encrypted password text plus the appropriate
prefix.
You define a JDBCLoginService with the name of the realm and the You define a `JDBCLoginService` with the name of the realm and the location of the properties file describing the database:
location of the properties file describing the database:
[source, xml, subs="{sub-order}"] [source, xml, subs="{sub-order}"]
---- ----
@ -458,30 +368,22 @@ location of the properties file describing the database:
<Set name="config">etc/jdbcRealm.properties</Set> <Set name="config">etc/jdbcRealm.properties</Set>
</New> </New>
---- ----
==== Authorization ==== Authorization
As far as the As far as the http://jcp.org/aboutJava/communityprocess/final/jsr340/[Servlet Specification] is concerned, authorization is based on roles.
http://jcp.org/aboutJava/communityprocess/final/jsr340/[Servlet As we have seen, a LoginService associates a user with a set of roles.
Specification] is concerned, authorization is based on roles. As we have When a user requests a resource that is access protected, the LoginService will be asked to authenticate the user if they are not already, and then asked to confirm if that user possesses one of the roles permitted access to the resource.
seen, a LoginService associates a user with a set of roles. When a user
requests a resource that is access protected, the LoginService will be
asked to authenticate the user if they are not already, and then asked
to confirm if that user possesses one of the roles permitted access to
the resource.
Until Servlet 3.1, role-based authorization could define: Until Servlet 3.1, role-based authorization could define:
* access granted to a set of named roles * access granted to a set of named roles
* access totally forbidden, regardless of role * access totally forbidden, regardless of role
* access granted to a user in any of the roles defined in the effective * access granted to a user in any of the roles defined in the effective web.xml.
web.xml. This is indicated by the special value of "*" for the This is indicated by the special value of "*" for the `<role-name>` of a `<auth-constraint> `in the `<security-constraint>`
<role-name> of a <auth-constraint> in the <security-constraint>
With the advent of Servlet 3.1, there is now another authorization: With the advent of Servlet 3.1, there is now another authorization:
* access granted to any user who is authenticated, regardless of roles. * access granted to any user who is authenticated, regardless of roles.
This is indicated by the special value of "**" for the <role-name> of a This is indicated by the special value of "**" for the `<role-name>` of a `<auth-constraint>` in the `<security-constraint>`
<auth-constraint> in the <security-constraint>

View File

@ -17,52 +17,42 @@
[[configuring-form-size]] [[configuring-form-size]]
=== Limiting Form Content === Limiting Form Content
Form content sent to the server is processed by Jetty into a map of Form content sent to the server is processed by Jetty into a map of parameters to be used by the web application.
parameters to be used by the web application. This can be vulnerable to This can be vulnerable to denial of service (DOS) attacks since significant memory and CPU can be consumed if a malicious clients sends very large form content or large number of form keys.
denial of service (DOS) attacks since significant memory and CPU can be Thus Jetty limits the amount of data and keys that can be in a form posted to Jetty.
consumed if a malicious clients sends very large form content or large
number of form keys. Thus Jetty limits the amount of data and keys that
can be in a form posted to Jetty.
The default maximum size Jetty permits is 200000 bytes and 1000 keys. The default maximum size Jetty permits is 200000 bytes and 1000 keys.
You can change this default for a particular webapp or for all webapps You can change this default for a particular webapp or for all webapps on a particular Server instance.
on a particular Server instance.
==== Configuring Form Limits for a Webapp ==== Configuring Form Limits for a Webapp
To configure the form limits for a sinlge webapplication, the context To configure the form limits for a single web application, the context handler (or webappContext) instance must be configured using the following methods:
handler (or webappContext) instance must be configured using the
following methods:
[source, java, subs="{sub-order}"] [source, java, subs="{sub-order}"]
---- ----
ContextHandler.setMaxFormContentSize(int maxSizeInBytes); ContextHandler.setMaxFormContentSize(int maxSizeInBytes);
ContextHandler.setMaxFormKeys(int formKeys); ContextHandler.setMaxFormKeys(int formKeys);
---- ----
These methods may be called directly when embedding jetty, but more These methods may be called directly when embedding Jetty, but more commonly are configured from a context XML file or WEB-INF/jetty-web.xml file:
commonly are configured from a context XML file or WEB-INF/jetty-web.xml
file:
[source, xml, subs="{sub-order}"] [source, xml, subs="{sub-order}"]
---- ----
<Configure class="org.eclipse.jetty.webapp.WebAppContext"> <Configure class="org.eclipse.jetty.webapp.WebAppContext">
... ...
<Set name="maxFormContentSize">200000</Set> <Set name="maxFormContentSize">200000</Set>
<Set name="maxFormKeys">200</Set> <Set name="maxFormKeys">200</Set>
</Configure> </Configure>
---- ----
==== Configuring Form Limits for the Server ==== Configuring Form Limits for the Server
If a context does not have specific form limits configured, then the If a context does not have specific form limits configured, then the server attributes are inspected to see if a server wide limit has been set on the size or keys.
server attributes are inspected to see if a server wide limit has been The following XML shows how these attributes can be set in `jetty.xml`:
set on the size or keys. The following XML shows how these attributes
can be set in jetty.xml:
[source, xml, subs="{sub-order}"] [source, xml, subs="{sub-order}"]
---- ----
@ -78,6 +68,6 @@ can be set in jetty.xml:
<Arg>org.eclipse.jetty.server.Request.maxFormKeys</Arg> <Arg>org.eclipse.jetty.server.Request.maxFormKeys</Arg>
<Arg>2000</Arg> <Arg>2000</Arg>
</Call> </Call>
</configure> </configure>
---- ----

View File

@ -17,59 +17,40 @@
[[jaas-support]] [[jaas-support]]
=== JAAS Support === JAAS Support
JAAS implements a Java version of the standard Pluggable Authentication JAAS implements a Java version of the standard Pluggable Authentication Module (PAM) framework.
Module (PAM) framework.
JAAS can be used for two purposes: JAAS can be used for two purposes:
* for authentication of users, to reliably and securely determine who is * for authentication of users, to reliably and securely determine who is currently executing Java code, regardless of whether the code is running as an application, an applet, a bean, or a servlet
currently executing Java code, regardless of whether the code is running * for authorization of users to ensure they have the access control rights (permissions) required to do the actions performed
as an application, an applet, a bean, or a servlet; and
* for authorization of users to ensure they have the access control
rights (permissions) required to do the actions performed.
JAAS authentication is performed in a pluggable fashion. This permits JAAS authentication is performed in a pluggable fashion.
applications to remain independent from underlying authentication This permits applications to remain independent from underlying authentication technologies.
technologies. New or updated authentication technologies can be plugged New or updated authentication technologies can be plugged under an application without requiring modifications to the application itself.
under an application without requiring modifications to the application Applications enable the authentication process by instantiating a `LoginContext` object, which in turn references a configuration to determine the authentication technology(ies), or `LoginModule`(s), to be used in performing the authentication.
itself. Applications enable the authentication process by instantiating Typical `LoginModules` may prompt for and verify a username and password.
a LoginContext object, which in turn references a Configuration to Others may read and verify a voice or fingerprint sample.
determine the authentication technology(ies), or LoginModule(s), to be
used in performing the authentication. Typical LoginModules may prompt
for and verify a username and password. Others may read and verify a
voice or fingerprint sample.
See Java Authentication and Authorization Service (JAAS) See Java Authentication and Authorization Service (JAAS) http://java.sun.com/javase/6/docs/technotes/guides/security/jaas/JAASRefGuide.html[Reference Guide] for more information about JAAS.
http://java.sun.com/javase/6/docs/technotes/guides/security/jaas/JAASRefGuide.html[Reference
Guide] for more information about JAAS.
[[jetty-jaas]] [[jetty-jaas]]
==== Jetty and JAAS ==== Jetty and JAAS
Many application servers support JAAS as a means of bringing greater Many application servers support JAAS as a means of bringing greater flexibility to the declarative security models of the J2EE (now known as the JavaEE) http://java.sun.com/javaee/index.jsp[specification].
flexibility to the declarative security models of the J2EE (now known as Jetty support for JAAS provides greater alternatives for servlet security, and increases the portability of web applications.
the JavaEE) http://java.sun.com/javaee/index.jsp[specification]. Jetty
support for JAAS provides greater alternatives for servlet security, and
increases the portability of web applications.
The JAAS support aims to dictate as little as possible whilst providing The JAAS support aims to dictate as little as possible whilst providing a sufficiently flexible infrastructure to allow users to drop in their
a sufficiently flexible infrastructure to allow users to drop in their own custom http://java.sun.com/j2se/1.4.2/docs/guide/security/jaas/JAASLMDevGuide.html[LoginModules].
own custom
http://java.sun.com/j2se/1.4.2/docs/guide/security/jaas/JAASLMDevGuide.html[LoginModules].
[[jaas-configuration]] [[jaas-configuration]]
==== Configuration ==== Configuration
Using JAAS with jetty is very simply a matter of declaring a Using JAAS with Jetty is very simply a matter of declaring a `org.eclipse.jetty.jaas.JAASLoginService`, creating a JAAS login module configuration file and specifying it on the Jetty run line.
`org.eclipse.jetty.jaas.JAASLoginService`, creating a jaas login module Let's look at an example.
configuration file and specifying it on the jetty run line. Let's look
at an example.
===== Step 1 ===== Step 1
Configure a jetty `org.eclipse.jetty.jaas.JAASLoginService` to match the Configure a Jetty `org.eclipse.jetty.jaas.JAASLoginService` to match the `<realm-name>` in your `web.xml` file. For example, if the `web.xml` contains a realm called "xyz" like so:
<realm-name> in your web.xml file. For example, if the `web.xml`
contains a realm called "xyz" like so:
[source, xml, subs="{sub-order}"] [source, xml, subs="{sub-order}"]
---- ----
@ -83,8 +64,7 @@ contains a realm called "xyz" like so:
</login-config> </login-config>
---- ----
Then you need to create a JAASLoginService with the matching name of Then you need to create a `JAASLoginService` with the matching name of "xyz":
"xyz":
[source, xml, subs="{sub-order}"] [source, xml, subs="{sub-order}"]
---- ----
@ -96,15 +76,13 @@ Then you need to create a JAASLoginService with the matching name of
____ ____
[CAUTION] [CAUTION]
The name of the realm-name that you declare in `web.xml` must match exactly the name of your JAASLoginService. The name of the realm-name that you declare in `web.xml` must match exactly the name of your `JAASLoginService`.
____ ____
You can declare your JAASLoginService in a couple of different ways: You can declare your `JAASLoginService` in a couple of different ways:
1. If you have more than one webapp that you would like to use the same 1. If you have more than one webapp that you would like to use the same security infrastructure, then you can declare your `JAASLoginService` in a top-level Jetty xml file as a bean that is added to the `org.eclipse.jetty.server.Server`.
security infrastructure, then you can declare your JAASLoginService in a An example:
top-level jetty xml file as a bean that is added to the
org.eclipse.jetty.server.Server. Here's an example:
+ +
[source, xml, subs="{sub-order}"] [source, xml, subs="{sub-order}"]
---- ----
@ -121,9 +99,7 @@ org.eclipse.jetty.server.Server. Here's an example:
</Configure> </Configure>
---- ----
2. Alternatively, you can use a JAASLoginService with just a specific 2. Alternatively, you can use a `JAASLoginService` with just a specific webapp by creating a link:#deployable-descriptor-file[context xml] file for the webapp, and specifying the `JAASLoginService` in it:
webapp by creating a link:#deployable-descriptor-file[context xml] file
for the webapp, and specifying the JAASLoginService in it:
+ +
[source, xml, subs="{sub-order}"] [source, xml, subs="{sub-order}"]
---- ----
@ -146,9 +122,7 @@ for the webapp, and specifying the JAASLoginService in it:
[[jaas-step-2]] [[jaas-step-2]]
===== Step 2 ===== Step 2
Set up your `LoginModule` in a configuration file, following the Set up your `LoginModule` in a configuration file, following the http://java.sun.com/j2se/1.4.2/docs/api/javax/security/auth/login/Configuration.html[syntax rules] :
http://java.sun.com/j2se/1.4.2/docs/api/javax/security/auth/login/Configuration.html[syntax
rules] :
[source,ini] [source,ini]
---- ----
@ -159,24 +133,20 @@ xyz {
____ ____
[CAUTION] [CAUTION]
It is imperative that the application name on the first line is exactly the same as the `LoginModuleName` of your JAASLoginService. It is imperative that the application name on the first line is exactly the same as the `LoginModuleName` of your `JAASLoginService`.
____ ____
You may find it convenient to name this configuration file as You may find it convenient to name this configuration file as `etc/login.conf` because, as we will see below, some of the wiring up for JAAS has been done for you.
`etc/login.conf` because, as we will see below, some of the wiring up
for jaas has been done for you.
===== Step 3 ===== Step 3
You now need to invoke jetty with support for jaas. There are 2 aspects You now need to invoke Jetty with support for JAAS.
to this: There are 2 aspects to this:
* adding jaas-related jars to the jetty container classpath * adding JAAS-related jars to the Jetty container classpath
* setting the System property `java.security.auth.login.config` * setting the System property `java.security.auth.login.config`
To accomplish the above, use the jetty link:#startup-overview[startup] To accomplish the above, use the Jetty link:#startup-overview[startup] link:#startup-modules[modules mechanism] to add the JAAS link:#startup-modules[module]:
link:#startup-modules[modules mechanism] to add the jaas
link:#startup-modules[module]:
[source,bash] [source,bash]
---- ----
@ -185,10 +155,8 @@ java -jar start.jar --add-to-startd=jaas
____ ____
[NOTE] [NOTE]
The top level of the distribution does not have the jaas module enabled The top level of the distribution does not have the JAAS module enabled by default.
by default. However, there are several link:#demo-webapps-base[demo However, there are several link:#demo-webapps-base[demo webapps] - including a JAAS webapp - available in the `demo-base` directory of the distribution which has pre-enabled the JAAS module.
webapps] - including a jaas webapp - available in the `demo-base`
directory of the distribution which has pre-enabled the jaas module.
____ ____
Now you will have a file named `start.d/jaas.ini`, which contains: Now you will have a file named `start.d/jaas.ini`, which contains:
@ -199,28 +167,19 @@ Now you will have a file named `start.d/jaas.ini`, which contains:
jaas.login.conf=etc/login.conf jaas.login.conf=etc/login.conf
---- ----
The `jaas.login.conf` property refers to the location of your The `jaas.login.conf` property refers to the location of your `LoginModule` configuration file that you established in link:#jaas-step-2[Step 2].
LoginModule configuration file that you established in If you called it `etc/login.conf`, then your work is done. Otherwise, change the value of the `jaas.login.conf` property to be the location of your LoginModule configuration file.
link:#jaas-step-2[Step 2]. If you called it `etc/login.conf`, then your Jetty will automatically use this property to set the value of the System property `java.security.auth.login.config.`
work is done. Otherwise, change the value of the` jaas.login.conf`
property to be the location of your LoginModule configuration file.
Jetty will automatically use this property to set the value of the
System property `java.security.auth.login.config.`
==== A Closer Look at JAASLoginService ==== A Closer Look at JAASLoginService
To allow the greatest degree of flexibility in using JAAS with web To allow the greatest degree of flexibility in using JAAS with web applications, the `JAASLoginService` supports a couple of configuration options.
applications, the `JAASLoginService` supports a couple of configuration Note that you don't ordinarily need to set these explicitly, as Jetty has defaults which will work in 99% of cases.
options. Note that you don't ordinarily need to set these explicitly, as However, should you need to, you can configure:
jetty has defaults which will work in 99% of cases. However, should you
need to, you can configure:
* a policy for role-based authorization (Default: * a policy for role-based authorization (Default: `org.eclipse.jetty.jaas.StrictRoleCheckPolicy`)
`org.eclipse.jetty.jaas.StrictRoleCheckPolicy`) * a CallbackHandler (Default: `org.eclipse.jetty.jaas.callback.DefaultCallbackHandler`)
* a CallbackHandler (Default: * a list of classnames for the Principal implementation that equate to a user role (Default: `org.eclipse.jetty.jaas.JAASRole`)
`org.eclipse.jetty.jaas.callback.DefaultCallbackHandler`)
* a list of classnames for the Principal implementation that equate to a
user role (Default: `org.eclipse.jetty.jaas.JAASRole`)
Here's an example of setting each of these (to their default values): Here's an example of setting each of these (to their default values):
@ -245,46 +204,25 @@ Here's an example of setting each of these (to their default values):
===== RoleCheckPolicy ===== RoleCheckPolicy
The RoleCheckPolicy must be an implementation of the The `RoleCheckPolicy` must be an implementation of the `org.eclipse.jetty.jaas.RoleCheckPolicy` interface and its purpose is to help answer the question "is User X in Role Y" for role-based authorization requests.
`org.eclipse.jetty.jaas.RoleCheckPolicy` interface and its purpose is to The default implementation distributed with Jetty is the `org.eclipse.jetty.jaas.StrictRoleCheckPolicy`, which will assess a user as having a particular role if that role is at the top of the stack of roles that have been temporarily pushed onto the user.
help answer the question "is User X in Role Y" for role-based If the user has no temporarily assigned roles, the role is amongst those configured for the user.
authorization requests. The default implementation distributed with
jetty is the `org.eclipse.jetty.jaas.StrictRoleCheckPolicy`, which will
assess a user as having a particular role iff that role is at the top of
the stack of roles that have been temporarily pushed onto the user or if
the user has no temporarily assigned roles, the role is amongst those
configured for the user.
Roles can be temporarily assigned to a user programmatically by using Roles can be temporarily assigned to a user programmatically by using the `pushRole(String rolename)` method of the `org.eclipse.jetty.jaas.JAASUserPrincipal` class.
the pushRole(String rolename) method of the
`org.eclipse.jetty.jaas.JAASUserPrincipal` class.
For the majority of webapps, the default StrictRoleCheckPolicy will be For the majority of webapps, the default `StrictRoleCheckPolicy` will be quite adequate, however you may provide your own implementation and set it on your `JAASLoginService` instance.
quite adequate, however you may provide your own implementation and set
it on your JAASLoginService instance.
===== CallbackHandler ===== CallbackHandler
A CallbackHandler is responsible for interfacing with the user to obtain A CallbackHandler is responsible for interfacing with the user to obtain usernames and credentials to be authenticated.
usernames and credentials to be authenticated.
Jetty ships with the `org.eclipse.jetty.jaas.DefaultCallbackHandler` Jetty ships with the `org.eclipse.jetty.jaas.DefaultCallbackHandler` which interfaces the information contained in the request to the Callbacks that are requested by `LoginModules`.
which interfaces the information contained in the request to the You can replace this default with your own implementation if you have specific requirements not covered by the default.
Callbacks that are requested by LoginModules. You can replace this
default with your own implementation if you have specific requirements
not covered by the default.
===== Role Principal Implementation Class ===== Role Principal Implementation Class
When LoginModules authenticate a user, they usually also gather all of When `LoginModules` authenticate a user, they usually also gather all of the roles that a user has and place them inside the JAAS Subject.
the roles that a user has and place them inside the JAAS Subject. As As `LoginModules` are free to use their own implementation of the JAAS Principal to put into the Subject, Jetty needs to know which Principals represent the user and which represent his/her roles when performing authorization checks on `<security-constraint>`. The example `LoginModules` that ship with Jetty all use the `org.eclipse.jetty.jaas.JAASRole` class. However, if you have plugged in other `LoginModules`, you must configure the classnames of their role Principal implementations.
LoginModules are free to use their own implementation of the JAAS
Principal to put into the Subject, jetty needs to know which Principals
represent the user and which represent his/her roles when performing
authorization checks on <security-constraint>s. The example LoginModules
that ship with jetty all use the `org.eclipse.jetty.jaas.JAASRole`
class. However, if you have plugged in some other LoginModules, you must
configure the classnames of their role Principal implementations.
===== Sample LoginModules ===== Sample LoginModules
@ -296,21 +234,16 @@ configure the classnames of their role Principal implementations.
____ ____
[NOTE] [NOTE]
Passwords can be stored in clear text, obfuscated or checksummed. Passwords can be stored in clear text, obfuscated or checksummed.
The class link:{JDURL}/org/eclipse/jetty/util/security/Password.html[`org.eclipse.jetty.util.security.Password`] should be used to generate all varieties of passwords,the output from which can be cut and pasted into property files or entered into database tables. The class link:{JDURL}/org/eclipse/jetty/util/security/Password.html[`org.eclipse.jetty.util.security.Password`] should be used to generate all varieties of passwords,the output from which can be put in to property files or entered into database tables.
+
See more on this under the Configuration section on link:#configuring-security-secure-passwords[securing passwords]. See more on this under the Configuration section on link:#configuring-security-secure-passwords[securing passwords].
____ ____
===== JDBCLoginModule ===== JDBCLoginModule
The JDBCLoginModule stores user passwords and roles in a database that The `JDBCLoginModule` stores user passwords and roles in a database that are accessed via JDBC calls.
are accessed via JDBC calls. You can configure the JDBC connection You can configure the JDBC connection information, as well as the names of the table and columns storing the username and credential, and the names of the table and columns storing the roles.
information, as well as the names of the table and columns storing the
username and credential, and the name of the table and columns storing
the roles.
Here is an example login module configuration file entry for it using an Here is an example login module configuration file entry for it using an HSQLDB driver:
HSQLDB driver:
[source,ini] [source,ini]
---- ----
@ -330,34 +263,28 @@ jdbc {
}; };
---- ----
There is no particular schema required for the database tables storing There is no particular schema required for the database tables storing the authentication and role information.
the authentication and role information. The properties userTable, The properties `userTable`, `userField`, `credentialField`, `userRoleTable`, `userRoleUserField`, `userRoleRoleField` configure the names of the tables and the columns within them that are used to format the following queries:
userField, credentialField, userRoleTable, userRoleUserField,
userRoleRoleField configure the names of the tables and the columns
within them that are used to format the following queries:
* `select <credentialField> from <userTable> [source,sql]
where <userField> =?` ----
* `select <userRoleRoleField> from select <credentialField> from <userTable>
<userRoleTable> where <userRoleUserField> where <userField> =?
=?` select <userRoleRoleField> from <userRoleTable>
where <userRoleUserField> =?
----
Credential and role information is lazily read from the database when a Credential and role information is lazily read from the database when a previously unauthenticated user requests authentication.
previously unauthenticated user requests authentication. Note that this Note that this information is _only_ cached for the length of the authenticated session.
information is only cached for the length of the authenticated session. When the user logs out or the session expires, the information is flushed from memory.
When the user logs out or the session expires, the information is
flushed from memory.
Note that passwords can be stored in the database in plain text or Note that passwords can be stored in the database in plain text or encoded formats - see the note on "Passwords/Credentials" above.
encoded formats - see "Passwords/Credentials" note above.
===== DataSourceLoginModule ===== DataSourceLoginModule
Similar to the JDBCLoginModule, but this LoginModule uses a DataSource Similar to the `JDBCLoginModule`, but this `LoginModule` uses a `DataSource` to connect to the database instead of a JDBC driver. The `DataSource` is obtained by performing a JNDI lookup on `java:comp/env/${dnJNDIName}`.
to connect to the database instead of a jdbc driver. The DataSource is
obtained by doing a jndi lookup on `java:comp/env/${dnJNDIName}`
Here is a sample login module configuration for it: A sample login module configuration using this method:
[source,ini] [source,ini]
---- ----
@ -377,12 +304,10 @@ ds {
===== PropertyFileLoginModule ===== PropertyFileLoginModule
With this login module implementation, the authentication and role With this login module implementation, the authentication and role information is read from a property file.
information is read from a property file.
[source,ini] [source,ini]
---- ----
props { props {
org.eclipse.jetty.jaas.spi.PropertyFileLoginModule required org.eclipse.jetty.jaas.spi.PropertyFileLoginModule required
debug="true" debug="true"
@ -390,12 +315,11 @@ props {
}; };
---- ----
The file parameter is the location of a properties file of the same The file parameter is the location of a properties file of the same format as the `etc/realm.properties` example file.
format as the etc/realm.properties example file. The format is: The format is:
[source,text] [source,text]
---- ----
<username>: <password>[,<rolename> ...] <username>: <password>[,<rolename> ...]
---- ----
@ -403,15 +327,13 @@ Here's an example:
[source,ini] [source,ini]
---- ----
fred: OBF:1xmk1w261u9r1w1c1xmq,user,admin fred: OBF:1xmk1w261u9r1w1c1xmq,user,admin
harry: changeme,user,developer harry: changeme,user,developer
tom: MD5:164c88b302622e17050af52c89945d44,user tom: MD5:164c88b302622e17050af52c89945d44,user
dick: CRYPT:adpexzg3FUZAk,admin dick: CRYPT:adpexzg3FUZAk,admin
---- ----
The contents of the file are fully read in and cached in memory the The contents of the file are fully read in and cached in memory the first time a user requests authentication.
first time a user requests authentication.
===== LdapLoginModule ===== LdapLoginModule
@ -444,47 +366,28 @@ ldaploginmodule {
==== Writing your Own LoginModule ==== Writing your Own LoginModule
If you want to implement your own custom LoginModule, there are two If you want to implement your own custom `LoginModule`, there are two classes to be familiar with: `org.eclipse.jetty.jaas.spi.AbstractLoginModule` and `org.eclipse.jetty.jaas.spi.UserInfo`.
classes to be familiar with
`org.eclipse.jetty.jaas.spi.AbstractLoginModule` and
`org.eclipse.jetty.jaas.spi.UserInfo`.
The `org.eclipse.jetty.jaas.spi.AbstractLoginModule` implements all of The `org.eclipse.jetty.jaas.spi.AbstractLoginModule` implements all of the `javax.security.auth.spi.LoginModule` methods.
the `javax.security.auth.spi.LoginModule` methods. All you need to do is All you need to do is to implement the `getUserInfo` method to return a `org.eclipse.jetty.jaas.UserInfo` instance which encapsulates the username, password and role names (note: as `java.lang.Strings`) for a user.
to implement the getUserInfo method to return a
`org.eclipse.jetty.jaas.UserInfo` instance which encapsulates the
username, password and role names (note: as java.lang.Strings) for a
user.
The AbstractLoginModule does not support any caching, so if you want to The `AbstractLoginModule` does not support any caching, so if you want to cache UserInfo (eg as does the `org.eclipse.jetty.jaas.spi.PropertyFileLoginModule`) then you must provide this yourself.
cache UserInfo (eg as does the
`org.eclipse.jetty.jaas.spi.PropertyFileLoginModule`) then you must
provide this yourself.
==== Other Goodies ==== Other Goodies
===== RequestParameterCallback ===== RequestParameterCallback
As all servlet containers intercept and process a form submission with As all servlet containers intercept and process a form submission with action `j_security_check`, it is usually not possible to insert any extra input fields onto a login form with which to perform authentication: you may only pass `j_username` and `j_password`.
action j_security_check, it is usually not possible to insert any extra For those rare occasions when this is not good enough, and you require more information from the user in order to authenticate them, you can use the JAAS callback handler `org.eclipse.jetty.jaas.callback.RequestParameterCallback`.
input fields onto a login form with which to perform authentication: you This callback handler gives you access to all parameters that were passed in the form submission.
may only pass `j_username` and `j_password`. For those rare occasions To use it, in the `login()` method of your custom login module, add the `RequestParameterCallback` to the list of callback handlers the login module uses, tell it which params you are interested in, and then get the value of the parameter back.
when this is not good enough, and you require more information from the Here is an example:
user in order to authenticate them, you can use the JAAS callback
handler `org.eclipse.jetty.jaas.callback.RequestParameterCallback`. This
callback handler gives you access to all parameters that were passed in
the form submission. To use it, in the login() method of your custom
login module, add the RequestParameterCallback to the list of callback
handlers the login module uses, tell it which params you are interested
in, and then get the value of the parameter back. Here's an example:
[source, java, subs="{sub-order}"] [source, java, subs="{sub-order}"]
---- ----
public class FooLoginModule extends AbstractLoginModule public class FooLoginModule extends AbstractLoginModule
{ {
public boolean login() public boolean login()
throws LoginException throws LoginException
{ {
@ -497,7 +400,7 @@ public class FooLoginModule extends AbstractLoginModule
//use one RequestParameterCallback() instance for each param you want to access //use one RequestParameterCallback() instance for each param you want to access
callbacks[2] = new RequestParameterCallback (); callbacks[2] = new RequestParameterCallback ();
((RequestParameterCallback)callbacks[2]).setParameterName ("extrainfo"); ((RequestParameterCallback)callbacks[2]).setParameterName ("extrainfo");
callbackHandler.handle(callbacks); callbackHandler.handle(callbacks);
String userName = ((NameCallback)callbacks[0]).getName(); String userName = ((NameCallback)callbacks[0]).getName();
@ -508,12 +411,11 @@ public class FooLoginModule extends AbstractLoginModule
//authenticate the user //authenticate the user
} }
}
---- ----
===== Example JAAS WebApp ===== Example JAAS WebApp
An example webapp using jaas can be found in our git repo: An example webapp using JAAS can be found in the Jetty GitHub repository:
* link:{GITBROWSEURL}/tests/test-webapps/test-jaas-webapp[https://github.com/eclipse/jetty.project/tree/master/tests/test-webapps/test-jaas-webapp] * link:{GITBROWSEURL}/tests/test-webapps/test-jaas-webapp[https://github.com/eclipse/jetty.project/tree/master/tests/test-webapps/test-jaas-webapp]

View File

@ -18,46 +18,36 @@
=== Using the $\{jetty.home} and $\{jetty.base} Concepts to Configure === Using the $\{jetty.home} and $\{jetty.base} Concepts to Configure
Security Security
Jetty 9.1 introduces `${jetty.base}` and `${jetty.home}`. Jetty 9.1 introduced `${jetty.base}` and `${jetty.home}`.
* `${jetty.home}` is the directory location for the jetty distribution * `${jetty.home}` is the directory location for the jetty distribution (the binaries).
(the binaries). * `${jetty.base}` is the directory location for your customizations to the distribution.
* `${jetty.base}` is the directory location for your customizations to
the distribution.
This separation: This separation:
* Allows you to manage multiple Jetty installations. * Allows you to manage multiple Jetty installations.
* Makes it simple to retain your current configuration when you upgrade * Makes it simple to retain your current configuration when you upgrade your Jetty distribution.
your Jetty distribution.
For more information, see xref:startup-base-and-home[]. For more information, see xref:startup-base-and-home[].
Further, Jetty 9.1 parameterizes all of the standard configuration XMLs. Further, Jetty 9.1 parameterized all of the standard configuration XMLs.
For SSL, parameters are now just properties in the `start.ini`, reducing For SSL, parameters are now properties in the `start.ini` or `start.d\ssl.ini`, reducing to eliminating the need to edit XML files.
to eliminating the need to edit XML files.
Jetty 9.1 also introduces modules. Instead of explicitly listing all the Instead of explicitly listing all the libraries, properties, and XML files for a feature, Jetty 9.1 introduced a new module system.
libraries, properties, and XML files for a feature, Jetty includes A module is defined in a `modules/*.mod` file, including the libraries, dependencies, XML, and template INI files for a Jetty feature.
software modules, and the `start.jar` mechanism allows you to create new Thus you can use a single `--module=name` command line option as the equivalent of specifying many `--lib=location, feature.xml, name=value` arguments for a feature and all its dependencies.
modules. You define a module in a `modules/*.mod` file, including the Modules use their dependencies to control the ordering of libraries and XML files.
libraries, dependencies, XML, and template INI files for a Jetty For more information, see xref:startup-modules[].
feature. Thus you can use a single `--module=name` command line option
as the equivalent of specifying many `--lib=location, feature.xml,
name=value` arguments for a feature and all its dependencies. Modules
use their dependencies to control the ordering of libraries and XML
files. For more information, see xref:startup-modules[].
[[configuring-security-jetty91]] [[configuring-security-jetty91]]
==== Configuring SSL in with modules ==== Configuring SSL in with modules
This page describes how to configure SSL in Jetty with modules. It This page describes how to configure SSL in Jetty with modules.
provides an example of using the `${jetty.home}` and `${jetty.base}` to It provides an example of using the `${jetty.home}` and `${jetty.base}` to maximum effect.
maximum effect. It also includes a detailed explanation of how modules It also includes a detailed explanation of how modules work.
work.
This example assumes you have the jetty-distribution unpacked in This example assumes you have the jetty-distribution unpacked in `/home/user/jetty-distribution-{VERSION}`.
`/home/user/jetty-distribution-{VERSION}.` It also assumes you are using `start.ini` to configure your server features.
1. Create a base directory anywhere. 1. Create a base directory anywhere.
+ +
@ -67,6 +57,7 @@ This example assumes you have the jetty-distribution unpacked in
[/home/user]$ cd my-base [/home/user]$ cd my-base
.... ....
2. Add the modules for SSL, HTTP, and webapp deployment. 2. Add the modules for SSL, HTTP, and webapp deployment.
Adding modules in this way will append the associated module properties to the `${jetty.base}/start.ini` file.
+ +
[source, screen, subs="{sub-order}"] [source, screen, subs="{sub-order}"]
.... ....
@ -214,7 +205,7 @@ Properties:
Jetty Server Classpath: Jetty Server Classpath:
----------------------- -----------------------
Version Information on 11 entries in the classpath. Version Information on 11 entries in the classpath.
Note: order presented here is how they would appear on the classpath. : order presented here is how they would appear on the classpath.
changes to the --module=name command line options will be reflected here. changes to the --module=name command line options will be reflected here.
0: 3.1.0 | ${jetty.home}/lib/servlet-api-3.1.jar 0: 3.1.0 | ${jetty.home}/lib/servlet-api-3.1.jar
1: 3.1.RC0 | ${jetty.home}/lib/jetty-schemas-3.1.jar 1: 3.1.RC0 | ${jetty.home}/lib/jetty-schemas-3.1.jar
@ -262,9 +253,7 @@ First notice the separation of `${jetty.base}` and `${jetty.home}`.
[[modules]] [[modules]]
===== Modules ===== Modules
Notice that you have `--module=<name>` here and there; you have wrapped Notice that you have `--module=<name>` here and there; you have wrapped up the goal of a module (libs, configuration XMLs, and properties) into a single unit, with dependencies on other modules.
up the goal of a module (libs, configuration XMLs, and properties) into
a single unit, with dependencies on other modules.
You can see the list of modules: You can see the list of modules:
@ -449,12 +438,9 @@ Jetty Active Module Tree:
+ Module: deploy [enabled] + Module: deploy [enabled]
.... ....
These are the modules by name, the libraries they bring in, the XML These are the modules by name, the libraries they bring in, the XML configurations they use, the other modules they depend on (even optional ones), and if the module is in use, where it was enabled.
configurations they use, the other modules they depend on (even optional
ones), and if the module is in use, where it was enabled.
While you can manage the list of active modules yourself, it is much While you can manage the list of active modules yourself, it is much easier to edit the `${jetty.base}/start.ini`.
easier to edit the `${jetty.base}/start.ini`.
If you want to start using a new module: If you want to start using a new module:
@ -463,71 +449,58 @@ If you want to start using a new module:
[my-base] $ java -jar ../jetty-distribution-{VERSION}/start.jar --add-to-start=https [my-base] $ java -jar ../jetty-distribution-{VERSION}/start.jar --add-to-start=https
.... ....
This adds the `--module=` lines and associated properties (the This adds the `--module=` lines and associated properties (the parameterized values mentioned above), to your `start.ini`.
parameterized values mentioned above), to your `start.ini`.
____ ____
[IMPORTANT] [IMPORTANT]
Leave the modules and XML files alone in the `${jetty.home}` directory; there is no need to be moving or copying them unless you want to make your own modules or override the behavior of an existing module. Do not edit the modules and XML files in the `${jetty.home}` directory; there is no need to be moving or copying them unless you want to make your own modules or override the behavior of an existing module.
____ ____
Notice that your `${jetty.base}/start.ini` has no references to the XML Notice that your `${jetty.base}/start.ini` has no references to the XML files.
files. That's because the module system and its graph of dependencies That's because the module system and its graph of dependencies now dictate all of the XML files, and their load order.
now dictate all of the XML files, and their load order.
[[parameterizing]] [[parameterizing]]
===== Parameters ===== Parameters
Next is parameterizing all of the standard configuration XMLs. In this Next is parameterizing all of the standard configuration XMLs.
example all of the SSL parameters are now just properties in the In this example all of the SSL parameters are now just properties in the `start.ini`, reducing or eliminating the need to edit XML files.
`start.ini`, reducing or eliminating the need to edit XML files.
[[override-jetty.home]] [[override-jetty.home]]
===== Overriding $\{jetty.home} in $\{jetty.base} ===== Overriding $\{jetty.home} in $\{jetty.base}
Finally, you can override anything you see in `${jetty.home}` in Finally, you can override anything you see in `${jetty.home}` in `${jetty.base}`, even XML configurations and libraries.
`${jetty.base}`, even XML configurations and libraries.
For more information on the `start.jar` in 9.1, see xref:start-jar[]. For more information on the `start.jar` in 9.1, see xref:start-jar[].
[[summary-configuring-SSL-Jetty-91]] [[summary-configuring-SSL-Jetty]]
==== Summary of Configuring SSL in Jetty 9.1 ==== Summary of Configuring SSL
1. Download and unpack Jetty 9.1 into 1. Download and unpack Jetty into `/home/user/jetty-distribution-{VERSION}`.
`/home/user/jetty-distribution-{VERSION}`.
2. Go to your base directory and just use the distribution, no editing. 2. Go to your base directory and just use the distribution, no editing.
+ +
[source, screen, subs="{sub-order}"] [source, screen, subs="{sub-order}"]
.... ....
[my-base]$ java -jar /home/user/jetty-distribution-{VERSION}/start.jar [my-base]$ java -jar /home/user/jetty-distribution-{VERSION}/start.jar
.... ....
* The Jetty 9.1 distribution provides, out of the box, the XML * The Jetty distribution provides, out of the box, the XML configuration files, in this case `jetty-http.xml` and `jetty-ssl.xml`.
configuration files, in this case `jetty-http.xml` and `jetty-ssl.xml`. These can be found in the `${jetty.home}/etc/` directory.
You can find them in `${jetty.home}/etc/` directory.
* We have parameterized all of the configurable values in those XMLs. * We have parameterized all of the configurable values in those XMLs.
You can now set the values using simple properties, either on the You can now set the values using simple properties, either on the command line, or within the `${jetty.base}/start.ini`.
command line, or within the `${jetty.base}/start.ini`. * When you activate the module for HTTP or HTTPs, Jetty automatically adds the appropriate libraries and XML to start Jetty.
* When you activate the module for HTTP or HTTPs, Jetty automatically Unless you have a highly custom setup (such as listening on two different ports, using SSL on each, each with its own keystore and configuration), there is no need to muck around in XML files.
adds the appropriate libraries and XML to start Jetty. Unless you have a
highly custom setup (such as listening on two different ports, using SSL
on each, each with its own keystore and configuration), you should have
no need to be mucking around in XML files.
3. Use modules to configure HTTPS: 3. Use modules to configure HTTPS:
* http -> server * http -> server
* https -> ssl -> server * https -> ssl -> server
+ +
You can find the details about the modules in `${jetty.home}/modules/`. You can find the details about the modules in `${jetty.home}/modules/`.
For SSL they include `modules/http.mod`, `modules/https.mod`, For SSL they include `modules/http.mod`, `modules/https.mod`, `modules/ssl.mod`, and `modules/server.mod`.
`modules/ssl.mod`, and `modules/server.mod`.
+ +
Ideally, this level of detail is not important to you. What is important Ideally, this level of detail is not important to you.
is that you want to use HTTPS and want to configure it. You accomplish What is important is that you want to use HTTPS and want to configure it.
that by adding the `--module=https` to your `start.ini`. By default, the You accomplish that by adding the `--module=https` to your `start.ini`.
module system keeps things sane, and transitively includes all dependent By default, the module system keeps things sane, and transitively includes all dependent modules as well.
modules as well.
You can see what the configuration looks like, after all of the modules You can see what the configuration looks like, after all of the modules are resolved, without starting Jetty via:
are resolved, without starting Jetty via:
[source, screen, subs="{sub-order}"] [source, screen, subs="{sub-order}"]
.... ....
@ -537,9 +510,9 @@ are resolved, without starting Jetty via:
Just because the JARs exist on disk does not mean that they are in use. Just because the JARs exist on disk does not mean that they are in use.
The configuration controls what is used. The configuration controls what is used.
Use the `--list-config` to see the configuration. Notice that only a Use the `--list-config` to see the configuration.
subset of the JARs from the distribution are in use. The modules you Notice that only a subset of the JARs from the distribution are in use.
have anabled determine that subset. The modules you have enabled determine that subset.
[source, screen, subs="{sub-order}"] [source, screen, subs="{sub-order}"]
.... ....

View File

@ -17,24 +17,16 @@
[[configuring-security-secure-passwords]] [[configuring-security-secure-passwords]]
=== Secure Password Obfuscation === Secure Password Obfuscation
There are many places where you might want to use and store a password, There are many places where you might want to use and store a password, for example for the SSL connectors and user passwords in realms.
for example for the SSL connectors and user passwords in realms.
Passwords can be stored in clear text, obfuscated, checksummed or Passwords can be stored in clear text, obfuscated, checksummed or encrypted in order of increasing security.
encrypted in order of increasing security. The choice of method to The choice of method to secure a password depends on where you are using the password.
secure a password depends on where you are using the password. In some In some cases such as keystore passwords and digest authentication, the system must retrieve the original password, which requires the obfuscation method.
cases such as keystore passwords and digest authentication, the system The drawback of the obfuscation algorithm is that it protects passwords from casual viewing only.
must retrieve the original password, which requires the obfuscation
method. The drawback of the obfuscation algorithm is that it protects
passwords from casual viewing only.
When the stored password is compared to one a user enters, the handling When the stored password is compared to one a user enters, the handling code can apply the same algorithm that secures the stored password to the user input and compare results, making password authentication more secure.
code can apply the same algorithm that secures the stored password to
the user input and compare results, making password authentication more
secure.
The class `org.eclipse.jetty.util.security.Password` can be used to The class `org.eclipse.jetty.util.security.Password` can be used to generate all varieties of passwords.
generate all varieties of passwords.
Run it without arguments to see usage instructions: Run it without arguments to see usage instructions:
@ -47,11 +39,9 @@ $ java -cp lib/jetty-util-$JETTY_VERSION.jar org.eclipse.jetty.util.security.Pas
Usage - java org.eclipse.jetty.util.security.Password [<user>] <password> Usage - java org.eclipse.jetty.util.security.Password [<user>] <password>
If the password is ?, the user will be prompted for the password If the password is ?, the user will be prompted for the password
.... ....
For example, to generate a secured version of the password "blah" for For example, to generate a secured version of the password "blah" for the user "me":
the user "me", do:
[source, screen, subs="{sub-order}"] [source, screen, subs="{sub-order}"]
.... ....
@ -63,15 +53,11 @@ OBF:20771x1b206z
MD5:639bae9ac6b3e1a84cebb7b403297b79 MD5:639bae9ac6b3e1a84cebb7b403297b79
CRYPT:me/ks90E221EY CRYPT:me/ks90E221EY
.... ....
You can now cut and paste whichever secure version you choose into your You can now cut and paste whichever secure version you choose into your configuration file or Java code.
configuration file or java code.
For example, the last line below shows how you would cut and paste the For example, the last line below shows how you would implement the encrypted password generated above into the properties file for a `LoginService`:
encrypted password generated above into the properties file for a
`LoginService`:
[source,bash] [source,bash]
---- ----
@ -81,7 +67,6 @@ other: OBF:1xmk1w261u9r1w1c1xmq
guest: guest,read-only guest: guest,read-only
me:CRYPT:me/ks90E221EY me:CRYPT:me/ks90E221EY
---- ----
____ ____
@ -89,9 +74,8 @@ ____
Don't forget to also copy the OBF:, MD5: or CRYPT: prefix on the generated password. It will not be usable by Jetty without it. Don't forget to also copy the OBF:, MD5: or CRYPT: prefix on the generated password. It will not be usable by Jetty without it.
____ ____
You can also use obfuscated passwords in jetty xml files where a plain You can also use obfuscated passwords in jetty xml files where a plain text password is usually needed.
text password is usually needed. Here's an example setting the password Here's an example setting the password for a JDBC Datasource with obfuscation:
for a JDBC Datasource with obfuscation:
[source, xml, subs="{sub-order}"] [source, xml, subs="{sub-order}"]
---- ----
@ -116,7 +100,5 @@ for a JDBC Datasource with obfuscation:
</New> </New>
</Arg> </Arg>
</New> </New>
---- ----

View File

@ -17,104 +17,61 @@
[[serving-aliased-files]] [[serving-aliased-files]]
=== Aliased Files and Symbolic links === Aliased Files and Symbolic links
Web applciations will often server static content from the file system Web applications will often server static content from the file system provided by the operating system running underneath the JVM.
provided by the operating system running underneatth the JVM. However However because file systems often implement multiple aliased names for the same file, then security constraints and other servlet URI space mappings my inadvertently be bypassed by aliases.
because file systems often implement multiple aliased names for the same
file, then security constraints and other servlet URI space mappings my
inadvertantly be bypassed by aliases.
I key example of this is case insensitivety and 8.3 names implemented by A key example of this is case insensitivity and 8.3 filenames implemented by the Windows file system.
the Windows File system. If a file within a webapplication called If a file within a web application called `/mysecretfile.txt` is protected by a security constraint on the URI `/mysecretfile.txt`, then a request to `/MySecretFile.TXT` will not match the URI constraint because URIs are case sensitive, but the Windows file system will report that a file does exist at that name and it will be served despite the security constraint.
`/mysecretfile.txt` is protected by a security constraint on the URI Less well known than case insensitivity is that Windows files systems also support http://en.wikipedia.org/wiki/8.3_filename[8.3 filenames] for compatibility with legacy programs.
` /mysecretfile.txt`, then a request to `/MySecretFile.TXT` will not Thus a request to a URI like `/MYSECR~1.TXT` will again not match the security constraint, but will be reported as an existing file by the file system and served.
match the URI constraint because URIs are case sensitive, but the
windows file system will report that a file does exist at that name and
it will be served despite the security constraint. Less well known than
case insensitivity is that windows files systems also support
http://en.wikipedia.org/wiki/8.3_filename[8.3 filenames] for
compatibility with legacy programs. Thus a request to a URI like
`/MYSECR~1.TXT` will again not match the security constraint, but will
be reported as an existing file by the file system and served.
There are many examples of aliases, not just on windows: There are many examples of aliases, not just on Windows:
* NTFS Alternate stream names like c:\test\file.txt::$DATA:name * NTFS Alternate stream names like `c:\test\file.txt::$DATA:name`
* OpenVMS support file versionig so that `/mysecret.txt;N` refers to * OpenVMS support file versionig so that `/mysecret.txt;N` refers to version N of `/mysecret.txt` and is essentially an alias.
version N of ` * The clearcase software configuration management system provides a file system where `@@` in a file name is an alias to a specific version.
/mysecret.txt` and is essentially an alias. * The Unix files system supports `/./foo.txt` as and alias for `/foo.txt`
* The clearcase software configuration management system provides a file * Many JVM implementations incorrectly assume the null character is a string terminator, so that a file name resulting from `/foobar.txt%00` is an alias for `/foobar.txt`
system where @@ in a file name is an alias to a specific version. * Unix symbolic links and hard links are a form of aliases that allow the same file or directory to have multiple names.
* The unix files system supports `/./foo.txt` as and alias for
`/foo.txt`
* Many JVM implementations incorrectly assume the null character is a
string terminator, so that a file name resulting from `/foobar.txt%00`
is an alias for `/foobar.txt`
* Unix symbolic links and hard links are a form of aliases that allow
the same file or directory to have multiple names.
In addition, it is not just URI security constraints that can be In addition, it is not just URI security constraints that can be bypassed. For example the mapping of the URI pattern `*.jsp` to the JSP
bypassed. For example the mapping of the URI pattern `*.jsp` to the JSP Servlet may be bypassed by an a request to an alias like `/foobar.jsp%00`, thus rather than execute the JSP, the source code of the JSP is returned by the file system.
Servlet may be bypassed by an a request to an alias like `
/foobar.jsp%00`, thus rather than execute the JSP, the source code of
the JSP is returned by the file system.
==== Good Security Practise ==== Good Security Practise
Part of the problem with aliases is that the standard web application Part of the problem with aliases is that the standard web application security model is to allow all requests except the ones that are specifically denied by security constraints.
security model is to allow all requests except the ones that are A best practice for security is to deny all requests and to permit only those that are specifically identified as allowable.
specifically denied by security constraints. A best practise for While it is possible to design web application security constraints in this style, it can be difficult in all circumstances and it is not the default. T
security is to deny all requests and to permit only those that are hus it is important for Jetty to be able to detect and deny requests to aliased static content.
specifically identified as allowable. While it is possible to design web
application security constraints in this style, it can be difficult in
all circumstances and it is not the default. Thus it is important for
Jetty to be able to detect and deny requests to aliased static content.
[[file-alias-detection]] [[file-alias-detection]]
==== Alias detection ==== Alias detection
It is impossible for Jetty to know of all the aliases that may be It is impossible for Jetty to know of all the aliases that may be implemented by the file system running beneath it, thus it does not attempt to make any specific checks for any know aliases.
implemented by the file system running beneath it, thus it does not Instead Jetty detects aliases by using the canonical path of a file.
attempt to make any specific checks for any know aliases. Instead jetty If a file resource handled by jetty has a canonical name that differs from the name used to request the resource, then Jetty determines that the resource is an aliased request and it will not be returned by the `ServletContext.getResource(String)` method (or similar) and thus will not be served as static content nor used as the basis of a JSP.
detects aliases by using the canonical path of a file. If a file
resource handled by jetty has a canonical name that differs from the
name used to request the resource, then Jetty determines that the
resource is an aliased request and it will not be returned by the
`ServletContext.getResource(String)` method (or similar) and thus will
not be served as static content nor used as the basis of a JSP.
This if Jetty is running on a windows operation system, then a file This if Jetty is running on a Windows operating system, then a file called `/MySecret.TXT` will have a canonical name that exactly matches that case.
called `/MySecret.TXT` will have a canonical name that exactly matches So while a request to `/mysecret.txt` or `/MYSECR~1.TXT` will result in a File Resource that matches the file, the different canonical name will indicate that those requests are aliases and they will not be served as static content and instead a 404 response returned.
that case. So while a request to `/mysecret.txt` or ` /MYSECR~1.TXT`
will result in a File Resource that matches the file, the different
canonical name will indicate that those requests are aliases and they
will not be served as static content and instead a 404 response
returned.
Unfortunately this approach denies all aliases, including symbolic Unfortunately this approach denies all aliases, including symbolic links, which can be useful in assembling complex web applications.
links, which can be useful in assembling complex web applications.
[[file-alias-serving]] [[file-alias-serving]]
==== Serving Aliases and Symbolic Links ==== Serving Aliases and Symbolic Links
Not all aliases are bad nor should be seen as attempts to subvert Not all aliases are bad nor should be seen as attempts to subvert security constraints.
security constraints. Specifically symbolic links can be very useful Specifically symbolic links can be very useful when assembling complex web applications, yet by default Jetty will not serve them.
when assembling complex web applications, yet by default Jetty will not Thus Jetty contexts support an extensible `AliasCheck` mechanism to allow aliases resources to be inspected an conditionally served.
serve them. Thus Jetty contexts support an extensible AliasCheck In this way, "good" aliases can be detected and served.
mechanism to allow aliases resources to be inspected an conditionally Jetty provides several utility implementations of the `AliasCheck` interface as nested classes with `ContextHandler`:
served. In this way, "good" aliases can be detected and served. Jetty
provides several utility implementations of the AliasCheck interface as
nested classes with ContextHandler:
ApproveAliases:: ApproveAliases::
Approve all aliases (USE WITH CAUTION!). Approve all aliases (*Use with caution!*).
AllowSymLinkAliasChecker:: AllowSymLinkAliasChecker::
Approve Aliases using the java-7 Files.readSymbolicLink(path) and Approve Aliases using the java-7 `Files.readSymbolicLink(path)` and `Path.toRealPath(...)` APIs to check that aliases are valid symbolic links.
Path.toRealPath(...) APIs to check that alias are valid symbolic
links.
An application is free to implement its own Alias checking. Alias An application is free to implement its own Alias checking.
Checkers can be installed in a context via the following XML used in a Alias Checkers can be installed in a context via the following XML used in a context deployer file or `WEB-INF/jetty-web.xml`:
context deployer file or `WEB-INF/jetty-web.xml`:
[source, xml, subs="{sub-order}"] [source, xml, subs="{sub-order}"]
---- ----
@ -122,5 +79,5 @@ context deployer file or `WEB-INF/jetty-web.xml`:
<Call name="addAliasCheck"> <Call name="addAliasCheck">
<Arg><New class="org.eclipse.jetty.server.handler.AllowSymLinkAliasChecker"/></Arg> <Arg><New class="org.eclipse.jetty.server.handler.AllowSymLinkAliasChecker"/></Arg>
</Call> </Call>
---- ----

View File

@ -17,47 +17,33 @@
[[spnego-support]] [[spnego-support]]
=== Spnego Support === Spnego Support
Spnego or Simple and Protected GSSAPI Negotiation Mechanism is a way for Simple and Protected GSSAPI Negotiation Mechanism (Spnego) is a way for users to be seamlessly authenticated when running on a Windows or Active Directory based network.
users to be seamlessly authenticated when running on a Windows or Active Jetty supports this type of authentication and authorization through the JDK (which has been enabled since the later versions of Java 6 and 7).
Directory based network. Jetty supports this type of authentication and Also important to note is that this is an _incredibly_ fragile setup where everything needs to be configured just right for things to work, otherwise it can fail in fun and exciting, not to mention obscure, ways.
authorization through the JDK so you must be using a JDK that supports
it, which recent versions of Java 6 and 7 do. Also important to note is
that this is an incredibly fragile setup where everything needs to be
configured just right for things to work, otherwise it can fail in fun
and exciting, not to mention obscure ways.
There is a substantial amount of configuration and testing required to There is a substantial amount of configuration and testing required to enable this feature as well as knowledge and access to central systems on a Windows network such as the Active Domain Controller and the ability to create and maintain service users.
enable this feature as well as knowledge and access to central systems
on a Windows network such as the Active Domain Controller and the
ability to create and maintain service users.
==== Configuring Jetty and Spnego ==== Configuring Jetty and Spnego
To run with spengo enabled the following command line options are To run with Spengo enabled the following command line options are required:
required:
....
[source,screen, subs="{sub-order}"]
----
-Djava.security.krb5.conf=/path/to/jetty/etc/krb5.ini \ -Djava.security.krb5.conf=/path/to/jetty/etc/krb5.ini \
-Djava.security.auth.login.config=/path/to/jetty/etc/spnego.conf \ -Djava.security.auth.login.config=/path/to/jetty/etc/spnego.conf \
-Djavax.security.auth.useSubjectCredsOnly=false -Djavax.security.auth.useSubjectCredsOnly=false
----
....
For debugging the spengo authentication the following options are very For debugging the Spengo authentication the following options are very helpful:
helpful:
....
[source,screen, subs="{sub-order}"]
----
-Dorg.eclipse.jetty.LEVEL=debug \ -Dorg.eclipse.jetty.LEVEL=debug \
-Dsun.security.spnego.debug=all -Dsun.security.spnego.debug=all
----
Spengo Authentication must be enabled in the webapp in the following way.
.... The name of the role will be different for your network.
Spengo Authentication must be enabled in the webapp in the following
way. The name of the role will be different for your network.
[source, xml, subs="{sub-order}"] [source, xml, subs="{sub-order}"]
---- ----
@ -69,7 +55,7 @@ way. The name of the role will be different for your network.
</web-resource-collection> </web-resource-collection>
<auth-constraint> <auth-constraint>
<!-- this is the domain that the user is a member of --> <!-- this is the domain that the user is a member of -->
<role-name>MORTBAY.ORG</role-name> <role-name>MORTBAY.ORG</role-name>
</auth-constraint> </auth-constraint>
</security-constraint> </security-constraint>
<login-config> <login-config>
@ -81,13 +67,11 @@ way. The name of the role will be different for your network.
</spnego-login-config> </spnego-login-config>
</login-config> </login-config>
---- ----
A corresponding UserRealm needs to be created either programmatically if A corresponding `UserRealm` needs to be created either programmatically if embedded, via the `jetty.xml` or in a context file for the webapp.
embedded, via the jetty.xml or in a context file for the webapp.
This is what the configuration within a jetty xml file would look like. This is what the configuration within a Jetty xml file would look like.
[source, xml, subs="{sub-order}"] [source, xml, subs="{sub-order}"]
---- ----
@ -101,11 +85,9 @@ This is what the configuration within a jetty xml file would look like.
</Arg> </Arg>
</Call> </Call>
---- ----
This is what the configuration within a context xml file would look This is what the configuration within a context xml file would look like.
like.
[source, xml, subs="{sub-order}"] [source, xml, subs="{sub-order}"]
---- ----
@ -113,7 +95,7 @@ like.
<Get name="securityHandler"> <Get name="securityHandler">
<Set name="loginService"> <Set name="loginService">
<New class="org.eclipse.jetty.security.SpnegoLoginService"> <New class="org.eclipse.jetty.security.SpnegoLoginService">
<Set name="name">Test Realm</Set> <Set name="name">Test Realm</Set>
<Set name="config"> <Set name="config">
<SystemProperty name="jetty.home" default="."/>/etc/spnego.properties <SystemProperty name="jetty.home" default="."/>/etc/spnego.properties
</Set> </Set>
@ -122,12 +104,11 @@ like.
<Set name="checkWelcomeFiles">true</Set> <Set name="checkWelcomeFiles">true</Set>
</Get> </Get>
---- ----
There are a number of important configuration files with spnego that are There are a number of important configuration files with S3pnego that are required. The default values for these configuration files from this
required. The default values for these configuration files from this test example are found in the `/etc` folder of the Jetty distribution.
test example are found in the jetty-distribution.
spnego.properties:: spnego.properties::
configures the user realm with runtime properties configures the user realm with runtime properties
@ -136,70 +117,55 @@ krb5.ini::
spnego.conf:: spnego.conf::
configures the glue between gssapi and kerberos configures the glue between gssapi and kerberos
It is important to note that the keytab file referenced in the krb5.ini It is important to note that the keytab file referenced in the `krb5.ini` and the `spengo.conf` files needs to contain the keytab for the `targetName` for the http server.
and the spengo.conf files needs to contain the keytab for the targetName To do this use a process similar to this:
for the http server. To do this use a process similar to this:
On the windows active domain controller run: On the Windows Active Domain Controller run:
[source, screen, subs="{sub-order}"] [source, screen, subs="{sub-order}"]
.... ----
$ setspn -A HTTP/linux.mortbay.org ADUser $ setspn -A HTTP/linux.mortbay.org ADUser
----
....
To create the keytab file use the following process: To create the keytab file use the following process:
[source, screen, subs="{sub-order}"] [source, screen, subs="{sub-order}"]
.... ----
$ ktpass -out c:\dir\krb5.keytab -princ HTTP/linux.mortbay.org@MORTBAY.ORG -mapUser ADUser -mapOp set -pass ADUserPWD -crypto RC4-HMAC-NT -pType KRB5_NT_PRINCIPAL $ ktpass -out c:\dir\krb5.keytab -princ HTTP/linux.mortbay.org@MORTBAY.ORG -mapUser ADUser -mapOp set -pass ADUserPWD -crypto RC4-HMAC-NT -pType KRB5_NT_PRINCIPAL
----
This step will give you the keytab file which should then be copied to the machine running the http server and referenced from the configuration files.
.... For our testing we put the keytab into the `/etc` directory of Jetty and referenced it from there.
This step should give you the keytab file which should then be copied
over to the machine running this http server and referenced from the
configuration files. For our testing we put the keytab into the etc
directory of jetty and referenced it from there.
==== Configuring Firefox ==== Configuring Firefox
The follows steps have been required to inform Firefox that it should The follows steps have been required to inform Firefox that it should use a negotiation dialog to authenticate.
use a negotiation dialog to authenticate.
1. browse to about:config and agree to the warnings 1. Browse to about:config and agree to the warnings
2. search through to find the 'network' settings 2. Search through to find the 'network' settings
3. set network.negotiate-auth.delegation-uris to http://,https:// 3. Set `network.negotiate-auth.delegation-uris` to http://,https://
4. set network.negotiate-auth.trusted-uris to http://,https:// 4. Set `network.negotiate-auth.trusted-uris` to http://,https://
==== Configuring Internet Explorer ==== Configuring Internet Explorer
The follows steps have been required to inform Internet Explorer that it The follows steps have been required to inform Internet Explorer that it should use a negotiation dialog to authenticate.
should use a negotiation dialog to authenticate.
1. Tools -> Options -> Security -> Local Intranet -> Sites (everything 1. Tools -> Options -> Security -> Local Intranet -> Sites (everything should be checked here)
should be checked here) 2. Tools -> Options -> Security -> Local Intranet -> Sites -> Advanced (add url to server (http:// and/or https:// use the hostname!)
2. Tools -> Options -> Security -> Local Intranet -> Sites -> Advanced 3. Tools -> Options -> Security -> Local Intranet -> Sites -> Advanced -> Close
(add url to server (http:// and/or https:// use the hostname!)
3. Tools -> Options -> Security -> Local Intranet -> Sites -> Advanced
-> Close
4. Tools -> Options -> Security -> Local Intranet -> Sites -> Ok 4. Tools -> Options -> Security -> Local Intranet -> Sites -> Ok
5. Tools -> Options -> Advanced -> Security (in the checkbox list) 5. Tools -> Options -> Advanced -> Security (in the checkbox list)
6. locate and check 'Enable Integrated Windows Authentication' 6. Locate and check 'Enable Integrated Windows Authentication'
7. Tools -> Options -> Advanced -> Security -> Ok 7. Tools -> Options -> Advanced -> Security -> Ok
8. close IE then reopen and browse to your spengo protected resource 8. Close IE then reopen and browse to your Spengo protected resource
____ ____
[NOTE] [NOTE]
You must go to the hostname and not the IP, if you go to the IP it will default to NTLM authentication...the following conditions must be You must go to the hostname and not the IP.
true for Spnego authentication to work. If you go to the IP it will default to NTLM authentication...the following conditions must be true for Spnego authentication to work:
+
* You must be within the Intranet Zone of the network * You must be within the Intranet Zone of the network
* Accessing the server using a Hostname rather then IP * Accessing the server using a Hostname rather thAn IP
* Integrated Windows Authentication in IE is enabled and the host is trusted in Firefox * Integrated Windows Authentication in IE is enabled and the host is trusted in Firefox
* The server is not local to the browser, it can't be running on localhost. * The server is not local to the browser, it can't be running on localhost
* The client's Kerberos system is authenticated to a domain controller * The client's Kerberos system is authenticated to a domain controller
____ ____

View File

@ -29,9 +29,11 @@ import org.eclipse.jetty.util.resource.Resource;
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** Symbolic Link AliasChecker.
/**
* Symbolic Link AliasChecker.
* <p>An instance of this class can be registered with {@link ContextHandler#addAliasCheck(AliasCheck)} * <p>An instance of this class can be registered with {@link ContextHandler#addAliasCheck(AliasCheck)}
* to check resources that are aliased to other locations. The checker uses the * to check resources that are aliased to other locations. The checker uses the
* Java {@link Files#readSymbolicLink(Path)} and {@link Path#toRealPath(java.nio.file.LinkOption...)} * Java {@link Files#readSymbolicLink(Path)} and {@link Path#toRealPath(java.nio.file.LinkOption...)}
* APIs to check if a file is aliased with symbolic links.</p> * APIs to check if a file is aliased with symbolic links.</p>
*/ */
@ -46,7 +48,7 @@ public class AllowSymLinkAliasChecker implements AliasCheck
if (!(resource instanceof PathResource)) if (!(resource instanceof PathResource))
return false; return false;
PathResource pathResource = (PathResource)resource; PathResource pathResource = (PathResource) resource;
try try
{ {
@ -56,62 +58,14 @@ public class AllowSymLinkAliasChecker implements AliasCheck
if (path.equals(alias)) if (path.equals(alias))
return false; // Unknown why this is an alias return false; // Unknown why this is an alias
// is the file itself a symlink? if (hasSymbolicLink(path) && Files.isSameFile(path, alias))
if (Files.isSymbolicLink(path))
{
alias = path.getParent().resolve(alias);
if (LOG.isDebugEnabled())
{
LOG.debug("path ={}",path);
LOG.debug("alias={}",alias);
}
if (Files.isSameFile(path,alias))
{
if (LOG.isDebugEnabled())
LOG.debug("Allow symlink {} --> {}",resource,pathResource.getAliasPath());
return true;
}
}
// No, so let's check each element ourselves
boolean linked=true;
Path target=path;
int loops=0;
while (linked)
{
if (++loops>100)
{
if (LOG.isDebugEnabled())
LOG.debug("Too many symlinks {} --> {}",resource,target);
return false;
}
linked=false;
Path d = target.getRoot();
for (Path e:target)
{
Path r=d.resolve(e);
d=r;
while (Files.exists(d) && Files.isSymbolicLink(d))
{
Path link=Files.readSymbolicLink(d);
if (!link.isAbsolute())
link=d.getParent().resolve(link).normalize();
d=link;
linked=true;
}
}
target=d;
}
if (pathResource.getAliasPath().equals(target))
{ {
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
LOG.debug("Allow path symlink {} --> {}",resource,target); LOG.debug("Allow symlink {} --> {}", resource, pathResource.getAliasPath());
return true; return true;
} }
} }
catch(Exception e) catch (Exception e)
{ {
LOG.ignore(e); LOG.ignore(e);
} }
@ -119,4 +73,26 @@ public class AllowSymLinkAliasChecker implements AliasCheck
return false; return false;
} }
private boolean hasSymbolicLink(Path path)
{
// Is file itself a symlink?
if (Files.isSymbolicLink(path))
{
return true;
}
// Lets try each path segment
Path base = path.getRoot();
for (Path segment : path)
{
base = base.resolve(segment);
if (Files.isSymbolicLink(base))
{
return true;
}
}
return false;
}
} }