public class HttpSecurityService
extends java.lang.Object
SecurityProvider
.
Any SecurityProvider that supports authentication can be used with the HttpSecurityService including the Jespa NtlmSecurityProvider
and LdapSecurityProvider
.
HttpSecurityFilter
class is a minimal implementation of a Servlet Filter that extends this class.
The most important property is provider.classname which determines the underlying SecurityProvider
to be used.
SecurityProvider behavior is also driven entirely by properties. All properties that being with "jespa." will be stripped of this prefix and passed to the designated SecurityProvider constructor. All other properties are used only by the HttpSecurityService.
The following table describes all properties used by HttpSecurityService and are therefore not specific to the SecurityProvider that is used:
Name | Description | Example | ||||||
---|---|---|---|---|---|---|---|---|
properties.path | The path to a text file containing properties and values described in this section.
If the path refers to a readable file, the properties will be read and overwrite any properties in the Map supplied to init().
If the file is modified during the runtime of the program, the properties file will be automatically reloaded.
The onPropertiesUpdate(java.util.Map) method will be called whenever the properties file is loaded or reloaded.
This path may be a relative path relative to the context root or an absolute path prefixed with
Note: The
This parameter is not required. By default, properties are supplied through the Map passed to init().
file:/ is simply an escape sequence that indicates to the HttpSecurityService that the file is an absolute path.
The prefix is removed and the remaining path is used with the conventional file interface.
|
/WEB-INF/example_ntlm.prp | ||||||
provider.classname | The name of the jespa.security.SecurityProvider subclass that should be used.
This parameter is not required. By default, the jespa.ntlm.NtlmSecurityProvider will be used. |
jespa.ntlm.NtlmSecurityProvider | ||||||
fallback.location | The absolute path or URL to which the client should be redirected if it cannot participate in authentication. For example, if this property is set and the user clicks "Cancel" after being presented with the Network Password Dialog, they should be redirected to this URL. This value is ultimately used to set the window.location on the client using JavaScript (the value is not escaped).
This parameter is not required. If it is not specified and authentication cannot proceed, the client will resceive a 401 Unauthorized or 403 Forbidden response which browsers handle in different ways and may be a simple as to display a blank page. |
/ErrorSupport.html | ||||||
excludes | A comma separated list of paths relative to the webapp base that should be excluded from protection by this Filter.
Caution: The paths in this list effectively bypass the Filter. These paths will be completely unprotected!
Warning: These expressions have no knowledge of path separators.
Wildcard characters are not limited to matching path labels and may traverse separators.
For example, the expression
/images/*.png would match the path /images/secret/d8siek20.png .
Note: To include a literal comma in a path, put the element in quotes.
To include a literal quote in a path, put the element in quotes and escape the literal quote by preceeding it with another quote.
For example, the path
See The Excludes List section in the Jespa Operator's Manual for example wildcard expressions.
/action.jsp,,"cart", would require an excludes element of "/action.jsp,,""cart""," .
|
/account/login,/contact.html | ||||||
http.parameter.username.name | The name of an HTTP request parameter used to submit a username for performing an HTTP parameter-based login. See the HTTPS Form Based Logins section below for details. | username | ||||||
http.parameter.password.name | The name of an HTTP request parameter used to submit a password for performing an HTTP parameter-based login. See the HTTPS Form Based Logins section below for details. | password | ||||||
http.parameter.logout.name | The name of an HTTP request parameter that triggers the Filter to destroy the SecurityProvider's session state and effectively log out the client.
No additional code is required to facilitate a logout (although you may need to be conscientious about ignoring this parameter throughout your application).
Note that the actual parameter value is ignored.
For example, if this property is set to "logout", an HTTP request like https://www.example.com/Login.jsp?logout=1 might be used to logout the user and present them with a login form so that they can enter alternative credentials. |
logout | ||||||
http.parameter.anonymous.name | The name of an HTTP request parameter that bypasses authentication and installs an anonymous identity.
Caution: This feature allows any client to completely bypass authentication.
Before you enable this feature, please carefully read the Anonymous Access section below.
|
anon | ||||||
groups.allowed | A comma separated list of group and account names that identify the users who are permitted access through the HttpSecurityService. If this parameter is not set, the default behavior is to permit access. See the Group Based Access Control section below for details. | EXMAPLE\Engineers,EXAMPLE\Managers | ||||||
groups.denied | A comma separated list of group and account names that identify the users who are explicitly not permitted access through the HttpSecurityService. This parameter makes it easy to deny users who would otherwise be permitted access by the groups.allowed list. See the Group Based Access Control section below for details. | EXAMPLE\Sales | ||||||
jespa.log.path | The absoltute path to a file into which the Jespa library should log information.
Note: The Jespa log path and level values are global and static and therefore these may affect or be affected by other components in the same application that also use or set these values. For example, if you have two filter sections in a web.xml with different jespa.log.* values, the last filter to load will set the logging values for both filters.
See the LogStream class for more information about logging in Jespa.
This parameter is not required. If no path is supplied, log messages will be written to the default LogStream which, unless specified elsewhere, is System.err. | /tmp/jespa.log | ||||||
jespa.log.level | A small integer that indicates the level of information that the Jespa library should log.
Values are 0 - nothing; 1 - critical; 2 - basic (can be logged under load); 3 - more detail; 4+ - for debugging only.
See also the note for jespa.log.path.
This parameter is not required. The default value is 1. |
|||||||
bindings.targetSpns.policy | Controls how the HSS behaves if the client does not submit a valid SPN.
Possible values are:
|
2 | ||||||
bindings.targetSpns | A comma separated list of SPNs that this server accepts.
An SPN is just a scheme and host like HTTP/www.example.com (the scheme is always HTTP even if TLS is being used).
If TLS is being used (it should be) and the server certificate has dNSName or iPAddress SubjectAltName entries (it should), they will be used to generate SPNs automatically in which case it should not be necessary to set this property at all (but it can be set to add additional SPNs).
Note: This feature requires that the SecurityProvider being used implements the targetSpn property correctly (to retrieve the SPN submitted by the client during authentication if any).
|
HTTP/as5.example.com,HTTP/10.2.3.4 | ||||||
bindings.cert.hash.policy | Controls how the HSS behaves if the client does not submit valid channel bindings.
Possible values are:
|
2 | ||||||
bindings.cert.hash | Explicitly sets the channel bindings hash to a specific value in hex. If this property is set, all other bindings.cert.* properties will be ignored. Values for this property may be observed in the Jespa log file (although if a MITM attack was affected the value could be incorrect). | 531B8FFAC96ED512AD94EAB3687658A3 | ||||||
bindings.cert.keystore.path | The path to the keystore file containing the certificate from which to calculate the channel bindings hash. If this property is not set, the HSS will not use a keystore and all other bindings.cert.keystore.* properties will be ignored. | etc/alma92as5.p12 | ||||||
bindings.cert.keystore.type | The type of the keystore containing the certificate from which to calculate the channel bindings hash. The default value is PKCS12. | JKS | ||||||
bindings.cert.keystore.provider | The provider of the keystore containing the certificate from which to calculate the channel bindings hash. The default value is SunJSSE. | SUN | ||||||
bindings.cert.keystore.password | The password of the keystore containing the certificate from which to calculate the channel bindings hash. If this property is not set (which is not equivalent to an empty value), a value of null will be used with KeyStore.load() to indicate that a password is not required. | alma92as5 | ||||||
bindings.cert.pem.path | The path to a PEM file containing the PEM encoded certificate from which to calculate the channel bindings hash. | etc/alma92as5.pem | ||||||
bindings.cert.pem | The PEM encoded certificate from which to calculate the channel bindings hash.
Linebreaks will be ignored so that the entire certificate can be set on one line such as within a properties file like: -----BEGIN CERTIFICATE-----MIICmDC...77txZ2sZ8=-----END CERTIFICATE-----
|
|||||||
bindings.cert.url | An HTTPS URL serving the certificate from which to calculate the channel bindings hash.
If other bindings.cert.* properties are not set, the HSS will query this URL (using a "dummy" TLS trust manager) to retrieve the server certificate and calculate the channel bindings hash.
Note: While using only this property is convenient, it is not the most secure option.
If a MITM attack occurs when the channel bindings are initialized, the incorrect hash could be generated.
Properly secured installations should use the bindings.cert.keystore.* or bindings.cert.pem* properties instead.
If this value is not set, the value returned by |
https://ext2.example.com |
The HttpSecurityService also examines the SecurityProvider properties flags.capabilities.accept.ntlmssp and flags.capabilities.accept.spnego to determine if the SecurityProvider supports NTLM and/or SPNEGO.
If the flags.capabilities.accept.ntlmssp property is not true, the HttpSecurityService will not challenge the client with WWW-Authenticate: NTLM
.
If the flags.capabilities.accept.spnego property is not true, the HttpSecurityService will not challenge the client with WWW-Authenticate: Negotiate
(although currently no Jespa SecurityProvider supports SPNEGO anyway).
By default, without any bindings.* properties set, the HSS will automatically retrieve SPNs and calculate channel bindings from the server certificate.
However, the default policy is to not reject clients and only log the results. Also, automatically retrieving the TLS certificate is not the most secure option as an attacker could intercept this request during (re)initialization and defeat the channel bindings protection. The most secure option is to change the policy to require both SPN and channel bindings and to use the bindings.cert.keystore.* properties to explicitly and safely provide access to the server certifiate.
See also the bindings.targetSpns* properties above.
See also the bindings.keystore.* properties above.
1.3.6.1.5.5.7.3.1
) will be loaded from it.
See also the bindings.cert.* properties above.
Both properties must be set for the HttpSecurityService to perform HTTP parameter based logins.
Once authenticated, the client's identity will be maintained in HTTP session state. To "logout", see the http.parameter.logout.name property.
For example, if this property is set to "anon", an HTTP request like http://www.example.com/Whoami.jsp?anon=1 would bypass authentication and install the anonymous identity.
If the anonymous identity is installed, the getRemoteUser, getUserPrincipal, getAccount and getAuthType methods will return null. Additionally the isUserInRole method will always return false.
If this feature is enabled, access control becomes the responsibility of the developer. In particular, if getRemoteUser (or getUserPrincipal) returns null, the client has not authenticated and therefore they are "anonymous".
For example, if the HttpSecurityFilter is used with the NtlmSecurityProvider, the following init-param would restrict access to filtered content to only users in the named Windows groups.
<init-param> <param-name>groups.allowed</param-name> <param-value>EXMAPLE\Engineers,EXAMPLE\Managers,EXAMPLE\Wiki Admins</param-value> </init-param>
abaker@example.com
were used in the list above, that specific user would also be allowed access.
The groups.denied property is also a comma separated list of group names. If a user is found to be in the any one of these groups, they will immediately be denied access without further checking. The groups.denied list is checked before the groups.allowed list.
The following table describes properties that are specific to the NtlmSecurityProvider. These properties will be passed to the NtlmSecurityProvider constructor in a properties map (minus the "jespa." prefix) and therefore the NtlmSecurityProvider documentation should be considered authoritative. These properties are reiterated here only for convenience or because the description includes special information in the context of the HttpSecurityService.
Name | Description | Example |
---|---|---|
jespa.bindstr | The fully qualified DNS domain name of the Active Directory domain against which the NtlmSecurityProvider should try to authenticate clients.
This property is required.
This property may also be a fully qualified DNS hostname of a specific AD server.
This property must not be an IP address. If an IP address is used, a STATUS_INVALID_COMPUTER_NAME error will occur. If the domain or specific server identified by this property is not in the same (sub)domain as the HTTP service account, a STATUS_NO_TRUST_SAM_ACCOUNT error will occur. The specific AD server that the Jespa library will use is determined using DNS SRV queries. If a hostname of a specific AD server is supplied, that server must still be in the list of servers advertised by DNS as authorities for the target domain (unless DNS SRV lookups are disabled using the authority.dns.names.resolve property). |
example.com |
jespa.service.acctname | The name of the Computer account used for NETLOGON communication. See the Jespa Operator's Manual for details regarding how to create a Computer account and set it's password. As shown in the example to the right, the Computer account name should be the name followed by a $ sign followed by an @ sign followed by the DNS domain name (the backslash form like EXAMPLE\jespa1$ should also work). This property is required.
Note: The service account must be a Computer account. A regular User account will not work.
| JESPA1$@EXAMPLE.COM |
jespa.service.password | The password of the above mentioned Computer account. This property is required. | a89609c53443ce1c72e59275a8a1e1ce |
jespa.dns.servers | A comma separated list of IP addresses for Microsoft DNS servers that are authorities for the DNS SRV records used to locate AD services. See the DNS Requirements and Properties section in the Jespa Operator's Manual for details about this property and other DNS properties supported by the HttpSecurityService. | 192.168.10.10,192.168.20.20 |
jespa.dns.site | The Active Directory Sites & Services site that the service is in. See the Active Directory Sites & Services section in the Jespa Operator's Manual for details about this property and other DNS properties supported by the HttpSecurityService. | Paris |
jespa.account.canonicalForm | A small integer indicating the canonical form of the name returned by HttpServletRequest.getRemoteUser() and the SecurityPrincipal.getName() and toString methods of the Principal returned by HttpServletRequest.getUserPrincipal(). The four possible canonical forms are:
|
3 |
jespa.localhost.netbios.name | This property is deprecated and should not be used. |
C: GET /jespa/Whoami.jsp S: 401 Unauthorized WWW-Authenticate: NTLM C: GET /jespa/Whoami.jsp Authorization: NTLM TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA= S: 401 Unauthorized WWW-Authenticate: NTLM TlRMTVNTUAACAAAAAAAAA...AC4AZgBvAG8ALgBuAGUAdAAAAAAA C: GET /jespa/Whoami.jsp Authorization: NTLM TlRMTVNTUAADAAAAGAAYAFgA...AAAYABgAcAwATPGDh0OrwyZcJ9CEoJw== S: 200 OK
Note that this means doFilter will be called multiple times before the FilterChain.doFilter method is called. This is important to keep in mind if you are creating a custom HTTP security solution.
After authentication has completed, the HttpSecurityService stores a byte[] array attribute in the HTTP session. The key is "jespa.provider.state". The presence of this attribute suppresses redundant authentications. If it is removed, the client will be required to reauthenticate.
Authorization: NTLM TlRMTVNTUAABAAA...
but without the POST parameters. In this case the HttpSecurityService will complete the authentication, receive the POST parameters in the third request and continue as usual.
Constructor and Description |
---|
HttpSecurityService() |
Modifier and Type | Method and Description |
---|---|
void |
destroy()
This method closes the log stream opened if the jespa.log.path property is set.
|
void |
doFilter(javax.servlet.ServletRequest request,
javax.servlet.ServletResponse response,
javax.servlet.FilterChain chain)
The HttpSecurityService request handler.
|
protected int |
getBindingsCertHashPolicy(SecurityProvider ctx,
javax.servlet.http.HttpServletRequest req,
javax.servlet.http.HttpServletResponse rsp,
int defaultPolicy)
This protected method is called by doFilter after authentication to determine how the channel bindings checking should be performed for this client.
|
protected int |
getBindingsTargetSpnsPolicy(SecurityProvider ctx,
javax.servlet.http.HttpServletRequest req,
javax.servlet.http.HttpServletResponse rsp,
int defaultPolicy)
This protected method is called by doFilter after authentication to determine how the target SPN checking should be performed for this client.
|
protected java.lang.String |
getConnectionId(javax.servlet.http.HttpServletRequest req)
This protected method is called by doFilter to compute a String that uniquely identifies the client's connection so that stateful multi-request authentication can be conducted with multiple independent clients concurrently.
|
protected java.lang.Object |
getRequestCredential(javax.servlet.http.HttpServletRequest request)
This protected method is called by doFilter to both a) determine if explicit credential based authentication should be performed and b) retrieve that credential for authentication.
|
protected java.lang.String |
getRequestPath(javax.servlet.http.HttpServletRequest request)
This protected method is called internally to obtain the canonicalized and decoded path of the HTTP request.
|
javax.servlet.ServletContext |
getServletContext()
Returns the ServletContext provided to init.
|
void |
init(java.util.Map props)
Deprecated.
As of Jespa 1.1 use
init(String, ServletContext, Map) |
void |
init(java.lang.String name,
javax.servlet.ServletContext servletContext,
java.util.Map props)
Initialize this HttpSecurityService with the supplied name, ServletContext and properties.
|
protected void |
isAllowedAccess(SecurityProvider provider,
javax.servlet.http.HttpServletRequest req,
javax.servlet.http.HttpServletResponse rsp)
This protected method is called by doFilter after authentication to determine if the client is allowed access to resources protected by this HttpSecurityService.
|
protected boolean |
isAnonymous(javax.servlet.http.HttpServletRequest request)
This protected method is called by doFilter to determine if the special "anonymous" identity should be installed.
|
protected boolean |
isLogout(javax.servlet.http.HttpServletRequest request)
This protected method is called by doFilter to determine if this is a request to "logout" the current user.
|
protected boolean |
isProtected(javax.servlet.http.HttpServletRequest request)
This protected method is called by doFilter to determine if the request is for a protected resource which may only be accessed by an authenticated client.
|
protected static int |
matchWildcard(java.lang.String[] wildcards,
java.lang.String str)
Case-sensitive compare the supplied string to the list of DOS-style wildcard expressions with * and ? to match zero-or-more and one-or-more characters respectively and return the index of the expression that matched or -1 to indicat that no expression matched.
|
protected void |
onException(SecurityProviderException spe,
javax.servlet.http.HttpServletRequest req,
javax.servlet.http.HttpServletResponse rsp,
SecurityProvider provider)
This protected method is called from doFilter when a SecurityProviderException occurs trying to call either SecurityProvider.acceptSecContext or SecurityProvider.authenticate.
|
protected void |
onPropertiesUpdate(java.util.Map props)
This protected method is called from init and whenever the file identified by properties.path has been modified (but it will not be called more than once within a 5 second period).
|
java.lang.String |
toString() |
public void init(java.util.Map props) throws SecurityProviderException
init(String, ServletContext, Map)
props
- The HttpSecurityService and SecurityProvider properties.SecurityProviderException
public void init(java.lang.String name, javax.servlet.ServletContext servletContext, java.util.Map props) throws SecurityProviderException
name
- The name of this HttpSecurityService instanceservletContext
- The ServletContext that is initializing this HttpSecurityService instanceprops
- The HttpSecurityService and SecurityProvider propertiesSecurityProviderException
public void destroy()
protected void onPropertiesUpdate(java.util.Map props) throws SecurityProviderException
The default implementation just initializes the jespa.util.LogStream. Subclasses may override this method (and should call super.onPropertiesUpdate(props) within it) to re-initialize things that depend on properties loaded from the properties.path file.
props
- The updated list of properties. The properties Map should not be modified.SecurityProviderException
public javax.servlet.ServletContext getServletContext()
public java.lang.String toString()
toString
in class java.lang.Object
protected java.lang.Object getRequestCredential(javax.servlet.http.HttpServletRequest request) throws SecurityProviderException
This method is exposed to the developer so that a subclass can override the default behavior. For example, an implementation might return a custom credential required by a custom SecurityProvider.
The default implementation returns a PasswordCredential constructed with the username and password extracted from HTTP request parameters identified by the http.parameter.username.name and http.parameter.password.name properties.
If token-based authentication is not already being conducted this method will be called. If a non-null value is returned, an instance of the configured SecurityProvider will be created and it's authenticate() method will be called with the credential object. If this method returns null, explicit authentication is not performed.
request
- the HttpServletRequest passed to doFilterSecurityProviderException
protected boolean isLogout(javax.servlet.http.HttpServletRequest request) throws javax.servlet.ServletException
This method is exposed to the developer as a protected method so that a subclass can override the default behavior. For example, an implementation might look at the request path to determine if it is a logout request (as opposed to looking at an HTTP parameter).
The default implementation returns true if the HTTP parameter http.parameter.logout.name is present (note that the actual value of the parameter is ignored).
request
- the HttpServletRequest passed to doFilterjavax.servlet.ServletException
protected boolean isAnonymous(javax.servlet.http.HttpServletRequest request) throws javax.servlet.ServletException
anonymous = 1
and this special "dummy" SecurityProvider will be installed into the HTTP session to persist the "anonymous" identity.
This method protected method so that a subclass can override the default behavior. For example, an implementation might return true if the HttpSecurityService should be bypassed because another component will be providing security for the application.
The "anonymous" SecurityProvider that is installed into the HTTP session will have no identity or default account. The getIdentity and getAccount methods will return null and isUserInRole will always return false.
The default implementation returns true if the HTTP parameter http.parameter.anonymous.name is present (note that the actual value of the parameter is ignored).
To re-enable security provided by the HttpSecurityService, un-install the "anonymous" SecurityProvider state by having isLogout return true (or by removing the "jespa.provider.state" attribute from the HttpSession).
request
- the HttpServletRequest passed to doFilterjavax.servlet.ServletException
protected static int matchWildcard(java.lang.String[] wildcards, java.lang.String str) throws javax.servlet.ServletException
See The Excludes List section in the Jespa Operator's Manual for example wildcard expressions.
javax.servlet.ServletException
protected java.lang.String getRequestPath(javax.servlet.http.HttpServletRequest request) throws javax.servlet.ServletException
This method is exposed to the developer as a protected method so that a subclass can override the default behavior.
The default implementation simply normalizes the return value of HttpServletRequest.getRequestURI.
request
- the HttpServletRequest object passed to doFilterjavax.servlet.ServletException
protected boolean isProtected(javax.servlet.http.HttpServletRequest request) throws javax.servlet.ServletException
The default implementation of this method retrieves the request path with getRequestPath and then compares it to the excludes list specified with the excludes property which is a list of paths that may contain DOS-style wildcard expressions. If the request path matches an excludes path, this method returns false to indicate that the request is not protected. Otherwise, true is returned.
request
- the HttpServletRequest object passed to doFilter for the protected resourcejavax.servlet.ServletException
protected int getBindingsTargetSpnsPolicy(SecurityProvider ctx, javax.servlet.http.HttpServletRequest req, javax.servlet.http.HttpServletResponse rsp, int defaultPolicy) throws SecurityProviderException
The default behavior is to simply return the defaultPolicy value (defined by the bindings.targetSpns.policy property).
An alternative implementation might inspect the request and return a value that would allow (or not allow) the client to proceed if the supplied SPN did not match the list of permitted SPNs.
Code like String targetSpn = (String)ctx.getProperty("targetSpn", null)
will return the SPN supplied by the client or null if the client did not supply an SPN or if the SecurityProvider does not support the targetSpn property.
SecurityProviderException
protected int getBindingsCertHashPolicy(SecurityProvider ctx, javax.servlet.http.HttpServletRequest req, javax.servlet.http.HttpServletResponse rsp, int defaultPolicy) throws SecurityProviderException
The default behavior is to simply return the defaultPolicy value (defined by the bindings.cert.hash.policy property).
An alternative implementation might inspect the request and return a value that would allow (or not allow) the client to proceed if no channel bindings were supplied or did not match the expected value.
Code like byte[] channelBindings = (byte[])ctx.getProperty("channelBindings", null)
should return the channel bindings value supplied by the client or null if the client did not supply channel bindings or if the SecurityProvider does not support the channelBindings property.
SecurityProviderException
protected void isAllowedAccess(SecurityProvider provider, javax.servlet.http.HttpServletRequest req, javax.servlet.http.HttpServletResponse rsp) throws SecurityProviderException
The default implementation denies access if the user being authenticated is either:
Account acct = provider.getAccount(null, null); if (acct.isMemberOf("BUSICORP\\Engineers")) return; throw new SecurityProviderException(SecurityProviderException.STATUS_ACCESS_DENIED, provider.getIdentity() + " denied access because not in group BUSICORP\Engineers");
If rsp.setStatus(HttpServletResponse.SC_FORBIDDEN)
is called within this method, the HttpSecurityService will not challenge the client for authentication again (because it 403 Forbidden is sent instead of 401 Unauthorized) whereas the default behavior is to repeatedly challenge the client until it is successfully authenticated (which may repeatedly trigger the browser password dialog).
provider
- the SecurityProvider used to authenticate the userreq
- the HttpServletRequest object passed to doFilter that triggered authenticationrsp
- the HttpServletResponse object passed to doFilterSecurityProviderException
protected java.lang.String getConnectionId(javax.servlet.http.HttpServletRequest req) throws SecurityProviderException
The default implementation of this method attempts to determine the client's remote IP address and port number and returns a value like "192.168.10.11:12345". The header REMOTE_PORT may be used to help determine this value. However, if the header Jespa-Connection-Id is present, it's value will be used as the connection ID.
req
- the HttpServletRequest passed to doFilterSecurityProviderException
protected void onException(SecurityProviderException spe, javax.servlet.http.HttpServletRequest req, javax.servlet.http.HttpServletResponse rsp, SecurityProvider provider) throws SecurityProviderException
For example, if authentication fails because the user's password is incorrect, an implimentation may wish to retrieve the error code or text and store it into the HttpSession so that it can be retrieved later for display to the user. The default implementation only logs the Exception message.
Override this method in your custom HttpSecurityService to enable your application to display authentication related errors to users. Specifically, save the error message in the HttpSession with code like the following:
protected void onException(SecurityProviderException spe, HttpServletRequest req, HttpServletResponse rsp, SecurityProvider sp) throws SecurityProviderException { HttpSession ssn = req.getSession(true); ssn.setAttribute("jespa.message", spe.getMessage()); }
You may also want to examine the status code and create custom messages (for at least SecurityProviderException.STATUS_ACCOUNT_NOT_FOUND and STATUS_INVALID_CREDENTIALS). Then get (and remove) the message from the HttpSession when you generate the page displayed to users for authentication failures (specified by the fallback.location property). The following JSP fragment might be used to do this:
<% HttpSession ssn = request.getSession(false); if (ssn != null) { String message = (String)ssn.getAttribute("jespa.message"); if (message != null) { ssn.removeAttribute("jespa.message"); out.println("<div class='errmsg'>"); out.println(message); out.println("</div>"); } } %>
rsp.setStatus(HttpServletResponse.SC_FORBIDDEN)
here. This might seem like a way to stop the browser's builtin password dialog (403 Forbidden instead of 401 Unauthorized will stop the client from authenticating) but in truth the authentication will silently fail repeatedly until the browser is restarted because browsers can (and generally do) cache and reuse the incorrect credentials. There is no way for the server tell the client not to use the builtin password dialog.
SecurityProviderException
public void doFilter(javax.servlet.ServletRequest request, javax.servlet.ServletResponse response, javax.servlet.FilterChain chain) throws java.io.IOException, javax.servlet.ServletException
request
- the HttpServletRequest being handledresponse
- the HttpServletResponse being handledchain
- the FilterChain to call if the client successfully traverses the HttpSecurityService's security controlsjava.io.IOException
javax.servlet.ServletException