Merge branch 'jetty-9.3.x' into jetty-9.4.x

This commit is contained in:
Joakim Erdfelt 2016-07-12 11:44:16 -07:00
commit bdefbdfcf0
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
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):
[source, xml, subs="{sub-order}"]

View File

@ -17,41 +17,21 @@
[[configuring-security-authentication]]
=== Authentication
There are two aspects to securing a web application(or context) within
the Jetty server:
There are two aspects to securing a web application(or context) within the Jetty server:
Authentication::
The web application can be configured with a mechanism to determine
the identity of the user. This is configured by a mix of standard
declarations and jetty specific mechanisms and is covered in this
section.
The web application can be configured with a mechanism to determine the identity of the user.
This is configured by a mix of standard declarations and jetty specific mechanisms and is covered in this section.
Authorization::
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.
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.
==== Configuring an Authentication mechanism
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.
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.
Internally, configurating 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.
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.
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:
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:
[source, xml, subs="{sub-order}"]
----
@ -59,13 +39,10 @@ web.xml] that configures BASIC authentication:
<auth-method>BASIC</auth-method>
<realm-name>Test Realm</realm-name>
</login-config>
----
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:
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:
[source, xml, subs="{sub-order}"]
----
@ -77,14 +54,11 @@ configuration:
<form-error-page>/logonError.html?param=test</form-error-page>
</form-login-config>
</login-config>
----
With FORM Authentication, you must also configure URLs of pages to
generate a login form and handle errors. 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]:
With FORM Authentication, you must also configure URLs of pages to generate a login form and handle errors.
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]:
[source, xml, subs="{sub-order}"]
----
@ -108,78 +82,49 @@ webapp logon.html]:
</table>
</form>
</HTML>
----
The Authentication mechanism declared for a context / web application
defines how the server obtain authentication credentials from the
client, but it does not define how the server checks if those
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.
The Authentication mechanism declared for a context / web application defines how the server obtain authentication credentials from the
client, but it does not define how the server checks if those 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 allow you to secure your web applications against
unauthorized access. 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.
Security realms allow you to secure your web applications against unauthorized access.
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.
A webapp statically declares its security requirements in its web.xml
file. Authentication is controlled by the <login-config> element. Access
controls are specified by <security-constraint> and <security-role-ref>
elements. 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.
A webapp statically declares its security requirements in its web.xml file.
Authentication is controlled by the `<login-config>` element.
Access controls are specified by `<security-constraint>` and `<security-role-ref>` elements.
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.
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. For Jetty, the
link:{JDURL}/org/eclipse/jetty/security/LoginService.html[LoginService]
performs this function.
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.
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 set of users. Each user has authentication information (e.g. a
password) and a set of roles associated with him/herself.
A LoginService has a unique name, and gives access to information about a set of users.
Each user has authentication information (e.g. a password) and a set of roles associated with him/herself.
You may configure one or many different LoginServices depending on your
needs. A single realm would indicate that you wish to share common
security information across all of your web applications. Distinct
realms allow you to partition your security information webapp by
webapp.
You may configure one or many different LoginServices depending on your needs.
A single realm would indicate that you wish to share common security information across all of your web applications.
Distinct realms allow you to partition your security information webapp by webapp.
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.
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.
==== Scoping Security Realms
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. You can configure one or many
different realms depending on your needs.
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.
You can configure one or many different realms depending on your needs.
* Configure a single LoginService to share common security information
across all of your web applications.
* Configure distinct LoginServices to partition your security
information webapp by webapp.
* Configure a single LoginService to share common security information across all of your web applications.
* Configure distinct LoginServices to partition your security information webapp by webapp.
===== Globally Scoped
A LoginService is available to all web applications on a Server instance
if you add it as a bean to the Server. Such a definition would go into
an xml file in your $\{jetty.base}/etc directory, eg
$\{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]:
A LoginService is available to all web applications on a Server instance if you add it as a bean to the Server.
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).
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}"]
----
@ -196,14 +141,12 @@ link:{JDURL}/org/eclipse/jetty/security/HashLoginService.html[HashLoginService]:
</Call>
</Configure>
----
If you define more than one LoginService on a Server, you will need to
specify which one you want used for each context. You can do that by
telling the context the name of the LoginService, or passing it the
LoginService instance. Here's an example of doing both of these, using a
link:#deployable-descriptor-file[context xml file]:
If you define more than one LoginService on a Server, you will need to specify which one you want used for each context.
You can do that by telling the context the name of the LoginService, or passing it the 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}"]
----
@ -216,20 +159,19 @@ link:#deployable-descriptor-file[context xml file]:
<Set name="name">Test Realm</Set>
</New>
</Set>
<!-- or if you defined a LoginService called "Test Realm" in jetty.xml : -->
<Set name="realmName">Test Realm</Set>
</Get>
----
===== Per-Webapp Scoped
Alternatively, you can define a LoginService for just a single web
application. Here's how to define the same HashLoginService, but inside
a link:#deployable-descriptor-file[context xml file]:
Alternatively, you can define a LoginService for just a single web application.
Here's how to define the same HashLoginService, but inside a link:#deployable-descriptor-file[context xml file]:
[source, xml, subs="{sub-order}"]
----
@ -247,67 +189,47 @@ a link:#deployable-descriptor-file[context xml file]:
</Get>
</Configure>
----
Jetty provides a number of different LoginService types which can be
seen in the next section.
Jetty provides a number of different LoginService types which can be seen in the next section.
[[configuring-login-service]]
==== Configuring a LoginService
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:
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/HashLoginService.html[HashLoginService]::
A user realm that is backed by a hash map that is filled either
programatically or from a java properties file.
A user realm that is backed by a hash map that is filled either programatically or from a Java properties file.
link:{JDURL}/org/eclipse/jetty/security/JDBCLoginService.html[JDBCLoginService]::
Uses a JDBC connection to an SQL database for authentication
link:{JDURL}/org/eclipse/jetty/plus/security/DataSourceLoginService.html[DataSourceLoginService]::
Uses a JNDI defined
http://docs.oracle.com/javase/7/docs/api/javax/sql/DataSource.html[DataSource]
for authentication
Uses a JNDI defined http://docs.oracle.com/javase/7/docs/api/javax/sql/DataSource.html[DataSource] for authentication
link:{JDURL}/org/eclipse/jetty/jaas/JAASLoginService.html[JAASLoginService]::
Uses a
http://en.wikipedia.org/wiki/Java_Authentication_and_Authorization_Service[JAAS]
provider for authentication, See the section on
link:#jaas-support[JAAS support] for more information.
Uses a http://en.wikipedia.org/wiki/Java_Authentication_and_Authorization_Service[JAAS] provider for authentication; see the section on
link:#jaas-support[JAAS support] for more information
link:{JDURL}/org/eclipse/jetty/security/SpnegoLoginService.html[SpnegoLoginService]::
http://en.wikipedia.org/wiki/SPNEGO[SPNEGO] Authentication, See the
section on link:#spnego-support[SPNEGO support] for more information.
http://en.wikipedia.org/wiki/SPNEGO[SPNEGO] Authentication; see the section on link:#spnego-support[SPNEGO support] for more information.
An instance of a LoginService can be matched to a context/webapp either
by:
An instance of a LoginService can be matched to a context/webapp by:
* A LoginService instance may be set directly on the SecurityHandler
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.
* If only a single LoginService instance has been set on the Server then
it is used as the login service for the context.
* A LoginService instance may be set directly on the SecurityHandler 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
* 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]]
===== HashLoginService
The HashLoginService is a simple and efficient login service that loads
usernames, credentials and roles from a java properties file in the
format:
The HashLoginService is a simple and efficient login service that loads usernames, credentials and roles from a Java properties file in the format:
[source,properties]
----
username: password[,rolename ...]
----
where:
Where:
username::
is the user's unique identity
@ -325,11 +247,9 @@ admin: CRYPT:ad1ks..kc.1Ug,server-administrator,content-administrator,admin
other: OBF:1xmk1w261u9r1w1c1xmq
guest: guest,read-only
----
You configure the HashLoginService with a name and a reference to the
location of the properties file:
You configure the HashLoginService with a name and a reference to the location of the properties file:
[source, xml, subs="{sub-order}"]
----
@ -341,12 +261,10 @@ location of the properties file:
</New>
</Item>
----
You can also configure it to check the properties file regularly for
changes and reload when changes are detected. The reloadInterval is in
seconds:
You can also configure it to check the properties file regularly for changes and reload when changes are detected.
The `reloadInterval` is in seconds:
[source, xml, subs="{sub-order}"]
----
@ -357,17 +275,15 @@ seconds:
<Set name="reloadInterval">5</Set>
<Call name="start"></Call>
</New>
----
[[jdbc-login-service]]
===== JDBCLoginService
In this implementation, authentication and role information is stored in
a database accessed via JDBC. A properties file defines the JDBC
connection and database table information. Here is an example of a
properties file for this realm implementation:
In this implementation, authentication and role information is stored in a database accessed via JDBC.
A properties file defines the JDBC connection and database table information.
Here is an example of a properties file for this realm implementation:
[source,properties]
----
@ -388,7 +304,6 @@ userroletableuserkey = user_id
userroletablerolekey = role_id
cachetime = 300
----
The format of the database tables is (pseudo-sql):
@ -415,7 +330,6 @@ roles
role varchar(100) NOT NULL UNIQUE KEY
);
----
Where:
@ -442,13 +356,9 @@ id::
role::
a human-readable name for a role
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.
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.
You define a JDBCLoginService with the name of the realm and the
location of the properties file describing the database:
You define a `JDBCLoginService` with the name of the realm and the location of the properties file describing the database:
[source, xml, subs="{sub-order}"]
----
@ -458,30 +368,22 @@ location of the properties file describing the database:
<Set name="config">etc/jdbcRealm.properties</Set>
</New>
----
==== Authorization
As far as the
http://jcp.org/aboutJava/communityprocess/final/jsr340/[Servlet
Specification] is concerned, authorization is based on roles. As we have
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.
As far as the http://jcp.org/aboutJava/communityprocess/final/jsr340/[Servlet Specification] is concerned, authorization is based on roles.
As we have 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:
* access granted to a set of named roles
* access totally forbidden, regardless of role
* access granted to a user in any of the roles defined in the effective
web.xml. This is indicated by the special value of "*" for the
<role-name> of a <auth-constraint> in the <security-constraint>
* access granted to a user in any of the roles defined in the effective web.xml.
This is indicated by the special value of "*" for the `<role-name>` of a `<auth-constraint> `in the `<security-constraint>`
With the advent of Servlet 3.1, there is now another authorization:
* 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
<auth-constraint> in the <security-constraint>
This is indicated by the special value of "**" for the `<role-name>` of a `<auth-constraint>` in the `<security-constraint>`

View File

@ -17,52 +17,42 @@
[[configuring-form-size]]
=== Limiting Form Content
Form content sent to the server is processed by Jetty into a map of
parameters to be used by the web application. 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. Thus Jetty limits the amount of data and keys that
can be in a form posted to Jetty.
Form content sent to the server is processed by Jetty into a map of parameters to be used by the web application.
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.
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.
You can change this default for a particular webapp or for all webapps
on a particular Server instance.
You can change this default for a particular webapp or for all webapps on a particular Server instance.
==== Configuring Form Limits for a Webapp
To configure the form limits for a sinlge webapplication, the context
handler (or webappContext) instance must be configured using the
following methods:
To configure the form limits for a single web application, the context handler (or webappContext) instance must be configured using the following methods:
[source, java, subs="{sub-order}"]
----
ContextHandler.setMaxFormContentSize(int maxSizeInBytes);
ContextHandler.setMaxFormKeys(int formKeys);
ContextHandler.setMaxFormKeys(int formKeys);
----
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:
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:
[source, xml, subs="{sub-order}"]
----
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
...
<Set name="maxFormContentSize">200000</Set>
<Set name="maxFormKeys">200</Set>
</Configure>
</Configure>
----
==== Configuring Form Limits for the Server
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. The following XML shows how these attributes
can be set in jetty.xml:
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.
The following XML shows how these attributes can be set in `jetty.xml`:
[source, xml, subs="{sub-order}"]
----
@ -78,6 +68,6 @@ can be set in jetty.xml:
<Arg>org.eclipse.jetty.server.Request.maxFormKeys</Arg>
<Arg>2000</Arg>
</Call>
</configure>
</configure>
----

View File

@ -17,59 +17,40 @@
[[jaas-support]]
=== JAAS Support
JAAS implements a Java version of the standard Pluggable Authentication
Module (PAM) framework.
JAAS implements a Java version of the standard Pluggable Authentication Module (PAM) framework.
JAAS can be used for two purposes:
* 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; and
* for authorization of users to ensure they have the access control
rights (permissions) required to do the actions performed.
* 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
* 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
applications to remain independent from underlying authentication
technologies. New or updated authentication technologies can be plugged
under an application without requiring modifications to the application
itself. 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. Typical LoginModules may prompt
for and verify a username and password. Others may read and verify a
voice or fingerprint sample.
JAAS authentication is performed in a pluggable fashion.
This permits applications to remain independent from underlying authentication technologies.
New or updated authentication technologies can be plugged under an application without requiring modifications to the application itself.
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.
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)
http://java.sun.com/javase/6/docs/technotes/guides/security/jaas/JAASRefGuide.html[Reference
Guide] for more information about 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.
[[jetty-jaas]]
==== Jetty and JAAS
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]. Jetty
support for JAAS provides greater alternatives for servlet security, and
increases the portability of web applications.
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].
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
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].
The JAAS support aims to dictate as little as possible whilst providing 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].
[[jaas-configuration]]
==== Configuration
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. Let's look
at an example.
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.
Let's look at an example.
===== Step 1
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:
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:
[source, xml, subs="{sub-order}"]
----
@ -83,8 +64,7 @@ contains a realm called "xyz" like so:
</login-config>
----
Then you need to create a JAASLoginService with the matching name of
"xyz":
Then you need to create a `JAASLoginService` with the matching name of "xyz":
[source, xml, subs="{sub-order}"]
----
@ -96,15 +76,13 @@ Then you need to create a JAASLoginService with the matching name of
____
[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
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. Here's an example:
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`.
An example:
+
[source, xml, subs="{sub-order}"]
----
@ -121,9 +99,7 @@ org.eclipse.jetty.server.Server. Here's an example:
</Configure>
----
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:
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:
+
[source, xml, subs="{sub-order}"]
----
@ -146,9 +122,7 @@ for the webapp, and specifying the JAASLoginService in it:
[[jaas-step-2]]
===== Step 2
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] :
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] :
[source,ini]
----
@ -159,24 +133,20 @@ xyz {
____
[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
`etc/login.conf` because, as we will see below, some of the wiring up
for jaas has been done for you.
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.
===== Step 3
You now need to invoke jetty with support for jaas. There are 2 aspects
to this:
You now need to invoke Jetty with support for JAAS.
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`
To accomplish the above, use the jetty link:#startup-overview[startup]
link:#startup-modules[modules mechanism] to add the jaas
link:#startup-modules[module]:
To accomplish the above, use the Jetty link:#startup-overview[startup] link:#startup-modules[modules mechanism] to add the JAAS link:#startup-modules[module]:
[source,bash]
----
@ -185,10 +155,8 @@ java -jar start.jar --add-to-startd=jaas
____
[NOTE]
The top level of the distribution does not have the jaas module enabled
by default. 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.
The top level of the distribution does not have the JAAS module enabled by default.
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.
____
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
----
The `jaas.login.conf` property refers to the location of your
LoginModule configuration file that you established in
link:#jaas-step-2[Step 2]. 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.
Jetty will automatically use this property to set the value of the
System property `java.security.auth.login.config.`
The `jaas.login.conf` property refers to the location of your `LoginModule` configuration file that you established in link:#jaas-step-2[Step 2].
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.
Jetty will automatically use this property to set the value of the System property `java.security.auth.login.config.`
==== A Closer Look at JAASLoginService
To allow the greatest degree of flexibility in using JAAS with web
applications, the `JAASLoginService` supports a couple of configuration
options. Note that you don't ordinarily need to set these explicitly, as
jetty has defaults which will work in 99% of cases. However, should you
need to, you can configure:
To allow the greatest degree of flexibility in using JAAS with web applications, the `JAASLoginService` supports a couple of configuration options.
Note that you don't ordinarily need to set these explicitly, as 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:
`org.eclipse.jetty.jaas.StrictRoleCheckPolicy`)
* a CallbackHandler (Default:
`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`)
* a policy for role-based authorization (Default: `org.eclipse.jetty.jaas.StrictRoleCheckPolicy`)
* a CallbackHandler (Default: `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):
@ -245,46 +204,25 @@ Here's an example of setting each of these (to their default values):
===== RoleCheckPolicy
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. 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.
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.
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.
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
the pushRole(String rolename) method of the
`org.eclipse.jetty.jaas.JAASUserPrincipal` class.
Roles can be temporarily assigned to a user programmatically by using the `pushRole(String rolename)` method of the `org.eclipse.jetty.jaas.JAASUserPrincipal` class.
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.
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.
===== CallbackHandler
A CallbackHandler is responsible for interfacing with the user to obtain
usernames and credentials to be authenticated.
A CallbackHandler is responsible for interfacing with the user to obtain usernames and credentials to be authenticated.
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. You can replace this
default with your own implementation if you have specific requirements
not covered by the default.
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`.
You can replace this default with your own implementation if you have specific requirements not covered by the default.
===== Role Principal Implementation Class
When LoginModules authenticate a user, they usually also gather all of
the roles that a user has and place them inside the JAAS Subject. 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>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.
When `LoginModules` authenticate a user, they usually also gather all of the roles that a user has and place them inside the JAAS Subject.
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.
===== Sample LoginModules
@ -296,21 +234,16 @@ configure the classnames of their role Principal implementations.
____
[NOTE]
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].
____
===== JDBCLoginModule
The JDBCLoginModule stores user passwords and roles in a database that
are accessed via JDBC calls. You can configure the JDBC connection
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.
The `JDBCLoginModule` stores user passwords and roles in a database that are accessed via JDBC calls.
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.
Here is an example login module configuration file entry for it using an
HSQLDB driver:
Here is an example login module configuration file entry for it using an HSQLDB driver:
[source,ini]
----
@ -330,34 +263,28 @@ jdbc {
};
----
There is no particular schema required for the database tables storing
the authentication and role information. 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:
There is no particular schema required for the database tables storing the authentication and role information.
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:
* `select <credentialField> from <userTable>
where <userField> =?`
* `select <userRoleRoleField> from
<userRoleTable> where <userRoleUserField>
=?`
[source,sql]
----
select <credentialField> from <userTable>
where <userField> =?
select <userRoleRoleField> from <userRoleTable>
where <userRoleUserField> =?
----
Credential and role information is lazily read from the database when a
previously unauthenticated user requests authentication. Note that this
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.
Credential and role information is lazily read from the database when a previously unauthenticated user requests authentication.
Note that this 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.
Note that passwords can be stored in the database in plain text or
encoded formats - see "Passwords/Credentials" note above.
Note that passwords can be stored in the database in plain text or encoded formats - see the note on "Passwords/Credentials" above.
===== DataSourceLoginModule
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 doing a jndi lookup on `java:comp/env/${dnJNDIName}`
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}`.
Here is a sample login module configuration for it:
A sample login module configuration using this method:
[source,ini]
----
@ -377,12 +304,10 @@ ds {
===== PropertyFileLoginModule
With this login module implementation, the authentication and role
information is read from a property file.
With this login module implementation, the authentication and role information is read from a property file.
[source,ini]
----
props {
org.eclipse.jetty.jaas.spi.PropertyFileLoginModule required
debug="true"
@ -390,12 +315,11 @@ props {
};
----
The file parameter is the location of a properties file of the same
format as the etc/realm.properties example file. The format is:
The file parameter is the location of a properties file of the same format as the `etc/realm.properties` example file.
The format is:
[source,text]
----
<username>: <password>[,<rolename> ...]
----
@ -403,15 +327,13 @@ Here's an example:
[source,ini]
----
fred: OBF:1xmk1w261u9r1w1c1xmq,user,admin
harry: changeme,user,developer
tom: MD5:164c88b302622e17050af52c89945d44,user
dick: CRYPT:adpexzg3FUZAk,admin
----
The contents of the file are fully read in and cached in memory the
first time a user requests authentication.
The contents of the file are fully read in and cached in memory the first time a user requests authentication.
===== LdapLoginModule
@ -444,47 +366,28 @@ ldaploginmodule {
==== Writing your Own LoginModule
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`.
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`.
The `org.eclipse.jetty.jaas.spi.AbstractLoginModule` implements all of
the `javax.security.auth.spi.LoginModule` methods. 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.
The `org.eclipse.jetty.jaas.spi.AbstractLoginModule` implements all of the `javax.security.auth.spi.LoginModule` methods.
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.
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.
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.
==== Other Goodies
===== RequestParameterCallback
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`. 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`. 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:
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`.
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`.
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 is an example:
[source, java, subs="{sub-order}"]
----
public class FooLoginModule extends AbstractLoginModule
{
public boolean login()
throws LoginException
{
@ -497,7 +400,7 @@ public class FooLoginModule extends AbstractLoginModule
//use one RequestParameterCallback() instance for each param you want to access
callbacks[2] = new RequestParameterCallback ();
((RequestParameterCallback)callbacks[2]).setParameterName ("extrainfo");
callbackHandler.handle(callbacks);
String userName = ((NameCallback)callbacks[0]).getName();
@ -508,12 +411,11 @@ public class FooLoginModule extends AbstractLoginModule
//authenticate the user
}
}
----
===== 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]

View File

@ -18,46 +18,36 @@
=== Using the $\{jetty.home} and $\{jetty.base} Concepts to Configure
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
(the binaries).
* `${jetty.base}` is the directory location for your customizations to
the distribution.
* `${jetty.home}` is the directory location for the jetty distribution (the binaries).
* `${jetty.base}` is the directory location for your customizations to the distribution.
This separation:
* Allows you to manage multiple Jetty installations.
* Makes it simple to retain your current configuration when you upgrade
your Jetty distribution.
* Makes it simple to retain your current configuration when you upgrade your Jetty distribution.
For more information, see xref:startup-base-and-home[].
Further, Jetty 9.1 parameterizes all of the standard configuration XMLs.
For SSL, parameters are now just properties in the `start.ini`, reducing
to eliminating the need to edit XML files.
Further, Jetty 9.1 parameterized all of the standard configuration XMLs.
For SSL, parameters are now properties in the `start.ini` or `start.d\ssl.ini`, reducing to eliminating the need to edit XML files.
Jetty 9.1 also introduces modules. Instead of explicitly listing all the
libraries, properties, and XML files for a feature, Jetty includes
software modules, and the `start.jar` mechanism allows you to create new
modules. You define a module in a `modules/*.mod` file, including the
libraries, dependencies, XML, and template INI files for a Jetty
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[].
Instead of explicitly listing all the libraries, properties, and XML files for a feature, Jetty 9.1 introduced a new module system.
A module is defined in a `modules/*.mod` file, including the libraries, dependencies, XML, and template INI files for a Jetty 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 SSL in with modules
This page describes how to configure SSL in Jetty with modules. It
provides an example of using the `${jetty.home}` and `${jetty.base}` to
maximum effect. It also includes a detailed explanation of how modules
work.
This page describes how to configure SSL in Jetty with modules.
It provides an example of using the `${jetty.home}` and `${jetty.base}` to maximum effect.
It also includes a detailed explanation of how modules work.
This example assumes you have the jetty-distribution unpacked in
`/home/user/jetty-distribution-{VERSION}.`
This example assumes you have the jetty-distribution unpacked in `/home/user/jetty-distribution-{VERSION}`.
It also assumes you are using `start.ini` to configure your server features.
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
....
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}"]
....
@ -214,7 +205,7 @@ Properties:
Jetty Server 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.
0: 3.1.0 | ${jetty.home}/lib/servlet-api-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
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.
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.
You can see the list of modules:
@ -449,12 +438,9 @@ Jetty Active Module Tree:
+ Module: deploy [enabled]
....
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.
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.
While you can manage the list of active modules yourself, it is much
easier to edit the `${jetty.base}/start.ini`.
While you can manage the list of active modules yourself, it is much easier to edit the `${jetty.base}/start.ini`.
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
....
This adds the `--module=` lines and associated properties (the
parameterized values mentioned above), to your `start.ini`.
This adds the `--module=` lines and associated properties (the parameterized values mentioned above), to your `start.ini`.
____
[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
files. That's because the module system and its graph of dependencies
now dictate all of the XML files, and their load order.
Notice that your `${jetty.base}/start.ini` has no references to the XML files.
That's because the module system and its graph of dependencies now dictate all of the XML files, and their load order.
[[parameterizing]]
===== Parameters
Next is parameterizing all of the standard configuration XMLs. 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.
Next is parameterizing all of the standard configuration XMLs.
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.
[[override-jetty.home]]
===== Overriding $\{jetty.home} in $\{jetty.base}
Finally, you can override anything you see in `${jetty.home}` in
`${jetty.base}`, even XML configurations and libraries.
Finally, you can override anything you see in `${jetty.home}` in `${jetty.base}`, even XML configurations and libraries.
For more information on the `start.jar` in 9.1, see xref:start-jar[].
[[summary-configuring-SSL-Jetty-91]]
==== Summary of Configuring SSL in Jetty 9.1
[[summary-configuring-SSL-Jetty]]
==== Summary of Configuring SSL
1. Download and unpack Jetty 9.1 into
`/home/user/jetty-distribution-{VERSION}`.
1. Download and unpack Jetty into `/home/user/jetty-distribution-{VERSION}`.
2. Go to your base directory and just use the distribution, no editing.
+
[source, screen, subs="{sub-order}"]
....
[my-base]$ java -jar /home/user/jetty-distribution-{VERSION}/start.jar
....
* The Jetty 9.1 distribution provides, out of the box, the XML
configuration files, in this case `jetty-http.xml` and `jetty-ssl.xml`.
You can find them in `${jetty.home}/etc/` directory.
* The Jetty distribution provides, out of the box, the XML configuration files, in this case `jetty-http.xml` and `jetty-ssl.xml`.
These can be found in the `${jetty.home}/etc/` directory.
* We have parameterized all of the configurable values in those XMLs.
You can now set the values using simple properties, either on the
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. 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.
You can now set the values using simple properties, either on the 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.
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.
3. Use modules to configure HTTPS:
* http -> server
* https -> ssl -> server
+
You can find the details about the modules in `${jetty.home}/modules/`.
For SSL they include `modules/http.mod`, `modules/https.mod`,
`modules/ssl.mod`, and `modules/server.mod`.
For SSL they include `modules/http.mod`, `modules/https.mod`, `modules/ssl.mod`, and `modules/server.mod`.
+
Ideally, this level of detail is not important to you. What is important
is that you want to use HTTPS and want to configure it. You accomplish
that by adding the `--module=https` to your `start.ini`. By default, the
module system keeps things sane, and transitively includes all dependent
modules as well.
Ideally, this level of detail is not important to you.
What is important is that you want to use HTTPS and want to configure it.
You accomplish that by adding the `--module=https` to your `start.ini`.
By default, the module system keeps things sane, and transitively includes all dependent modules as well.
You can see what the configuration looks like, after all of the modules
are resolved, without starting Jetty via:
You can see what the configuration looks like, after all of the modules are resolved, without starting Jetty via:
[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.
The configuration controls what is used.
Use the `--list-config` to see the configuration. Notice that only a
subset of the JARs from the distribution are in use. The modules you
have anabled determine that subset.
Use the `--list-config` to see the configuration.
Notice that only a subset of the JARs from the distribution are in use.
The modules you have enabled determine that subset.
[source, screen, subs="{sub-order}"]
....

View File

@ -17,24 +17,16 @@
[[configuring-security-secure-passwords]]
=== Secure Password Obfuscation
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.
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.
Passwords can be stored in clear text, obfuscated, checksummed or
encrypted in order of increasing security. The choice of method to
secure a password depends on where you are using the password. In some
cases such as keystore passwords and digest authentication, the system
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.
Passwords can be stored in clear text, obfuscated, checksummed or encrypted in order of increasing security.
The choice of method to secure a password depends on where you are using the password.
In some cases such as keystore passwords and digest authentication, the system 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
code can apply the same algorithm that secures the stored password to
the user input and compare results, making password authentication more
secure.
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.
The class `org.eclipse.jetty.util.security.Password` can be used to
generate all varieties of passwords.
The class `org.eclipse.jetty.util.security.Password` can be used to generate all varieties of passwords.
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>
If the password is ?, the user will be prompted for the password
....
For example, to generate a secured version of the password "blah" for
the user "me", do:
For example, to generate a secured version of the password "blah" for the user "me":
[source, screen, subs="{sub-order}"]
....
@ -63,15 +53,11 @@ OBF:20771x1b206z
MD5:639bae9ac6b3e1a84cebb7b403297b79
CRYPT:me/ks90E221EY
....
You can now cut and paste whichever secure version you choose into your
configuration file or java code.
You can now cut and paste whichever secure version you choose into your configuration file or Java code.
For example, the last line below shows how you would cut and paste the
encrypted password generated above into the properties file for a
`LoginService`:
For example, the last line below shows how you would implement the encrypted password generated above into the properties file for a `LoginService`:
[source,bash]
----
@ -81,7 +67,6 @@ other: OBF:1xmk1w261u9r1w1c1xmq
guest: guest,read-only
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.
____
You can also use obfuscated passwords in jetty xml files where a plain
text password is usually needed. Here's an example setting the password
for a JDBC Datasource with obfuscation:
You can also use obfuscated passwords in jetty xml files where a plain text password is usually needed.
Here's an example setting the password for a JDBC Datasource with obfuscation:
[source, xml, subs="{sub-order}"]
----
@ -116,7 +100,5 @@ for a JDBC Datasource with obfuscation:
</New>
</Arg>
</New>
----

View File

@ -17,104 +17,61 @@
[[serving-aliased-files]]
=== Aliased Files and Symbolic links
Web applciations will often server static content from the file system
provided by the operating system running underneatth the JVM. However
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.
Web applications will often server static content from the file system provided by the operating system running underneath the JVM.
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.
I key example of this is case insensitivety and 8.3 names implemented by
the Windows File system. If a file within a webapplication 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. 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.
A key example of this is case insensitivity and 8.3 filenames implemented by the Windows file system.
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.
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
* OpenVMS support file versionig so that `/mysecret.txt;N` refers to
version N of `
/mysecret.txt` and is essentially an alias.
* The clearcase software configuration management system provides a file
system where @@ in a file name is an alias to a specific version.
* 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.
* NTFS Alternate stream names like `c:\test\file.txt::$DATA:name`
* OpenVMS support file versionig so that `/mysecret.txt;N` refers to version N of `/mysecret.txt` and is essentially an alias.
* The clearcase software configuration management system provides a file system where `@@` in a file name is an alias to a specific version.
* 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
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.
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
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
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. A best practise for
security is to deny all requests and to permit only those that are
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.
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.
A best practice for security is to deny all requests and to permit only those that are 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. T
hus it is important for Jetty to be able to detect and deny requests to aliased static content.
[[file-alias-detection]]
==== Alias detection
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. Instead jetty
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.
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.
Instead Jetty 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
called `/MySecret.TXT` will have a canonical name that exactly matches
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.
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.
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
links, which can be useful in assembling complex web applications.
Unfortunately this approach denies all aliases, including symbolic links, which can be useful in assembling complex web applications.
[[file-alias-serving]]
==== Serving Aliases and Symbolic Links
Not all aliases are bad nor should be seen as attempts to subvert
security constraints. Specifically symbolic links can be very useful
when assembling complex web applications, yet by default Jetty will not
serve them. Thus Jetty contexts support an extensible AliasCheck
mechanism to allow aliases resources to be inspected an conditionally
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:
Not all aliases are bad nor should be seen as attempts to subvert security constraints.
Specifically symbolic links can be very useful when assembling complex web applications, yet by default Jetty will not serve them.
Thus Jetty contexts support an extensible `AliasCheck` mechanism to allow aliases resources to be inspected an conditionally 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::
Approve all aliases (USE WITH CAUTION!).
Approve all aliases (*Use with caution!*).
AllowSymLinkAliasChecker::
Approve Aliases using the java-7 Files.readSymbolicLink(path) and
Path.toRealPath(...) APIs to check that alias are valid symbolic
links.
Approve Aliases using the java-7 `Files.readSymbolicLink(path)` and `Path.toRealPath(...)` APIs to check that aliases are valid symbolic links.
An application is free to implement its own Alias checking. Alias
Checkers can be installed in a context via the following XML used in a
context deployer file or `WEB-INF/jetty-web.xml`:
An application is free to implement its own Alias checking.
Alias Checkers can be installed in a context via the following XML used in a context deployer file or `WEB-INF/jetty-web.xml`:
[source, xml, subs="{sub-order}"]
----
@ -122,5 +79,5 @@ context deployer file or `WEB-INF/jetty-web.xml`:
<Call name="addAliasCheck">
<Arg><New class="org.eclipse.jetty.server.handler.AllowSymLinkAliasChecker"/></Arg>
</Call>
----

View File

@ -17,47 +17,33 @@
[[spnego-support]]
=== Spnego Support
Spnego or Simple and Protected GSSAPI Negotiation Mechanism is a way for
users to be seamlessly authenticated when running on a Windows or Active
Directory based network. Jetty supports this type of authentication and
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.
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.
Jetty supports this type of authentication and authorization through the JDK (which has been enabled since the later versions of Java 6 and 7).
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
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.
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.
==== Configuring Jetty and Spnego
To run with spengo enabled the following command line options are
required:
....
To run with Spengo enabled the following command line options are required:
[source,screen, subs="{sub-order}"]
----
-Djava.security.krb5.conf=/path/to/jetty/etc/krb5.ini \
-Djava.security.auth.login.config=/path/to/jetty/etc/spnego.conf \
-Djavax.security.auth.useSubjectCredsOnly=false
....
----
For debugging the spengo authentication the following options are very
helpful:
....
For debugging the Spengo authentication the following options are very helpful:
[source,screen, subs="{sub-order}"]
----
-Dorg.eclipse.jetty.LEVEL=debug \
-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}"]
----
@ -69,7 +55,7 @@ way. The name of the role will be different for your network.
</web-resource-collection>
<auth-constraint>
<!-- 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>
</security-constraint>
<login-config>
@ -81,13 +67,11 @@ way. The name of the role will be different for your network.
</spnego-login-config>
</login-config>
----
A corresponding UserRealm needs to be created either programmatically if
embedded, via the jetty.xml or in a context file for the webapp.
A corresponding `UserRealm` needs to be created either programmatically if 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}"]
----
@ -101,11 +85,9 @@ This is what the configuration within a jetty xml file would look like.
</Arg>
</Call>
----
This is what the configuration within a context xml file would look
like.
This is what the configuration within a context xml file would look like.
[source, xml, subs="{sub-order}"]
----
@ -113,7 +95,7 @@ like.
<Get name="securityHandler">
<Set name="loginService">
<New class="org.eclipse.jetty.security.SpnegoLoginService">
<Set name="name">Test Realm</Set>
<Set name="name">Test Realm</Set>
<Set name="config">
<SystemProperty name="jetty.home" default="."/>/etc/spnego.properties
</Set>
@ -122,12 +104,11 @@ like.
<Set name="checkWelcomeFiles">true</Set>
</Get>
----
There are a number of important configuration files with spnego that are
required. The default values for these configuration files from this
test example are found in the jetty-distribution.
There are a number of important configuration files with S3pnego that are required. The default values for these configuration files from this
test example are found in the `/etc` folder of the Jetty distribution.
spnego.properties::
configures the user realm with runtime properties
@ -136,70 +117,55 @@ krb5.ini::
spnego.conf::
configures the glue between gssapi and kerberos
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. To do this use a process similar to this:
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.
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}"]
....
----
$ setspn -A HTTP/linux.mortbay.org ADUser
....
----
To create the keytab file use the following process:
[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
----
....
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.
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.
==== Configuring Firefox
The follows steps have been required to inform Firefox that it should
use a negotiation dialog to authenticate.
The follows steps have been required to inform Firefox that it should use a negotiation dialog to authenticate.
1. browse to about:config and agree to the warnings
2. search through to find the 'network' settings
3. set network.negotiate-auth.delegation-uris to http://,https://
4. set network.negotiate-auth.trusted-uris to http://,https://
1. Browse to about:config and agree to the warnings
2. Search through to find the 'network' settings
3. Set `network.negotiate-auth.delegation-uris` to http://,https://
4. Set `network.negotiate-auth.trusted-uris` to http://,https://
==== Configuring Internet Explorer
The follows steps have been required to inform Internet Explorer that it
should use a negotiation dialog to authenticate.
The follows steps have been required to inform Internet Explorer that it should use a negotiation dialog to authenticate.
1. Tools -> Options -> Security -> Local Intranet -> Sites (everything
should be checked here)
2. Tools -> Options -> Security -> Local Intranet -> Sites -> Advanced
(add url to server (http:// and/or https:// use the hostname!)
3. Tools -> Options -> Security -> Local Intranet -> Sites -> Advanced
-> Close
1. Tools -> Options -> Security -> Local Intranet -> Sites (everything should be checked here)
2. Tools -> Options -> Security -> Local Intranet -> Sites -> Advanced (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
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
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]
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
true for Spnego authentication to work.
+
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 true for Spnego authentication to work:
* 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
* 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
____

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)}
* 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...)}
* 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))
return false;
PathResource pathResource = (PathResource)resource;
PathResource pathResource = (PathResource) resource;
try
{
@ -56,62 +58,14 @@ public class AllowSymLinkAliasChecker implements AliasCheck
if (path.equals(alias))
return false; // Unknown why this is an alias
// is the file itself a symlink?
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 (hasSymbolicLink(path) && Files.isSameFile(path, alias))
{
if (LOG.isDebugEnabled())
LOG.debug("Allow path symlink {} --> {}",resource,target);
LOG.debug("Allow symlink {} --> {}", resource, pathResource.getAliasPath());
return true;
}
}
catch(Exception e)
catch (Exception e)
{
LOG.ignore(e);
}
@ -119,4 +73,26 @@ public class AllowSymLinkAliasChecker implements AliasCheck
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;
}
}