Merge branch 'jetty-9.3.x' into jetty-9.4.x
This commit is contained in:
commit
bdefbdfcf0
|
@ -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}"]
|
||||
|
|
|
@ -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>`
|
||||
|
|
|
@ -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>
|
||||
|
||||
----
|
||||
|
|
|
@ -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]
|
||||
|
||||
|
||||
|
|
|
@ -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}"]
|
||||
....
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
||||
|
||||
----
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
||||
----
|
||||
|
|
|
@ -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
|
||||
____
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue