Skip to content

Commit

Permalink
Expand the session attribute filtering options
Browse files Browse the repository at this point in the history
- new option to filter based on implementation class of value
- new option to log a warning message if an attribute is filtered out
- always log a message at at least debug level if an attribute is filtered out

git-svn-id: https://svn.apache.org/repos/asf/tomcat/tc7.0.x/trunk@1726923 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
markt-asf committed Jan 26, 2016
1 parent 07cb67a commit 79e8ad0
Show file tree
Hide file tree
Showing 8 changed files with 258 additions and 20 deletions.
4 changes: 3 additions & 1 deletion java/org/apache/catalina/ha/session/ClusterManagerBase.java
Expand Up @@ -193,7 +193,9 @@ protected void clone(ClusterManagerBase copy) {
copy.setMaxInactiveInterval(getMaxInactiveInterval());
copy.setProcessExpiresFrequency(getProcessExpiresFrequency());
copy.setNotifyListenersOnReplication(isNotifyListenersOnReplication());
copy.setSessionAttributeFilter(getSessionAttributeFilter());
copy.setSessionAttributeNameFilter(getSessionAttributeNameFilter());
copy.setSessionAttributeValueClassNameFilter(getSessionAttributeValueClassNameFilter());
copy.setWarnOnSessionAttributeFilterFailure(getWarnOnSessionAttributeFilterFailure());
copy.setSecureRandomClass(getSecureRandomClass());
copy.setSecureRandomProvider(getSecureRandomProvider());
copy.setSecureRandomAlgorithm(getSecureRandomAlgorithm());
Expand Down
16 changes: 16 additions & 0 deletions java/org/apache/catalina/ha/session/mbeans-descriptors.xml
Expand Up @@ -345,6 +345,14 @@
name="sessionAttributeNameFilter"
descritpion="The string pattern used for including session attributes in replication. Null means all attributes are included."
type="java.lang.String"/>
<attribute
name="sessionAttributeValueClassNameFilter"
description="The regular expression used to filter session attributes based on the implementation class of the value. The regular expression is anchored and must match the fully qualified class name."
type="java.lang.String"/>
<attribute
name="warnOnSessionAttributeFilterFailure"
description="Should a WARN level log message be generated if a session attribute fails to match sessionAttributeNameFilter or sessionAttributeClassNameFilter?"
type="boolean"/>
<operation
name="expireSession"
description="Expired the given session"
Expand Down Expand Up @@ -576,6 +584,14 @@
name="sessionAttributeNameFilter"
descritpion="The string pattern used for including session attributes in replication. Null means all attributes are included."
type="java.lang.String"/>
<attribute
name="sessionAttributeValueClassNameFilter"
description="The regular expression used to filter session attributes based on the implementation class of the value. The regular expression is anchored and must match the fully qualified class name."
type="java.lang.String"/>
<attribute
name="warnOnSessionAttributeFilterFailure"
description="Should a WARN level log message be generated if a session attribute fails to match sessionAttributeNameFilter or sessionAttributeClassNameFilter?"
type="boolean"/>
<operation
name="expireSession"
description="Expired the given session"
Expand Down
2 changes: 2 additions & 0 deletions java/org/apache/catalina/session/LocalStrings.properties
Expand Up @@ -35,6 +35,8 @@ JDBCStore.commitSQLException=SQLException committing connection before closing
managerBase.createRandom=Created random number generator for session ID generation in {0}ms.
managerBase.contextNull=The Container must be set to a non-null Context instance before the Manager is used
managerBase.createSession.ise=createSession: Too many active sessions
managerBase.sessionAttributeNameFilter=Skipped session attribute named [{0}] because it did not match the name filter [{1}]
managerBase.sessionAttributeValueClassNameFilter=Skipped session attribute named [{0}] because the value type [{1}] did not match the filter [{2}]
managerBase.sessionTimeout=Invalid session timeout setting {0}
managerBase.setContextNotNew=It is illegal to call setContext() to change the Context associated with a Manager if the Manager is not in the NEW state
serverSession.value.iae=null value
Expand Down
120 changes: 116 additions & 4 deletions java/org/apache/catalina/session/ManagerBase.java
Expand Up @@ -35,6 +35,7 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

import org.apache.catalina.Container;
import org.apache.catalina.Context;
Expand Down Expand Up @@ -222,6 +223,10 @@ public abstract class ManagerBase extends LifecycleMBeanBase

private Pattern sessionAttributeNamePattern;

private Pattern sessionAttributeValueClassNamePattern;

private boolean warnOnSessionAttributeFilterFailure;


// ------------------------------------------------------------- Properties

Expand All @@ -248,8 +253,86 @@ protected Pattern getSessionAttributeNamePattern() {


/**
* Return the Container with which this Manager is associated.
* Obtain the regular expression used to filter session attribute based on
* the implementation class of the value. The regular expression is anchored
* and must match the fully qualified class name.
*
* @return The regular expression currently used to filter class names.
* {@code null} means no filter is applied. If an empty string is
* specified then no names will match the filter and all attributes
* will be blocked.
*/
public String getSessionAttributeValueClassNameFilter() {
if (sessionAttributeValueClassNamePattern == null) {
return null;
}
return sessionAttributeValueClassNamePattern.toString();
}


/**
* Provides {@link #getSessionAttributeValueClassNameFilter()} as a
* pre-compiled regular expression pattern.
*
* @return The pre-compiled pattern used to filter session attributes based
* on the implementation class name of the value. {@code null} means
* no filter is applied.
*/
protected Pattern getSessionAttributeValueClassNamePattern() {
return sessionAttributeValueClassNamePattern;
}


/**
* Set the regular expression to use to filter classes used for session
* attributes. The regular expression is anchored and must match the fully
* qualified class name.
*
* @param sessionAttributeValueClassNameFilter The regular expression to use
* to filter session attributes based on class name. Use {@code
* null} if no filtering is required. If an empty string is
* specified then no names will match the filter and all
* attributes will be blocked.
*
* @throws PatternSyntaxException If the expression is not valid
*/
public void setSessionAttributeValueClassNameFilter(String sessionAttributeValueClassNameFilter)
throws PatternSyntaxException {
if (sessionAttributeValueClassNameFilter == null ||
sessionAttributeValueClassNameFilter.length() == 0) {
sessionAttributeValueClassNamePattern = null;
} else {
sessionAttributeValueClassNamePattern =
Pattern.compile(sessionAttributeValueClassNameFilter);
}
}


/**
* Should a warn level log message be generated if a session attribute is
* not persisted / replicated / restored.
*
* @return {@code true} if a warn level log message should be generated
*/
public boolean getWarnOnSessionAttributeFilterFailure() {
return warnOnSessionAttributeFilterFailure;
}


/**
* Configure whether or not a warn level log message should be generated if
* a session attribute is not persisted / replicated / restored.
*
* @param warnOnSessionAttributeFilterFailure {@code true} if the
* warn level message should be generated
*
*/
public void setWarnOnSessionAttributeFilterFailure(
boolean warnOnSessionAttributeFilterFailure) {
this.warnOnSessionAttributeFilterFailure = warnOnSessionAttributeFilterFailure;
}


@Override
public Container getContainer() {
return this.container;
Expand Down Expand Up @@ -767,10 +850,39 @@ public void changeSessionId(Session session) {
@Override
public boolean willAttributeDistribute(String name, Object value) {
Pattern sessionAttributeNamePattern = getSessionAttributeNamePattern();
if (sessionAttributeNamePattern == null) {
return true;
if (sessionAttributeNamePattern != null) {
if (!sessionAttributeNamePattern.matcher(name).matches()) {
if (getWarnOnSessionAttributeFilterFailure() || log.isDebugEnabled()) {
String msg = sm.getString("managerBase.sessionAttributeNameFilter",
name, sessionAttributeNamePattern);
if (getWarnOnSessionAttributeFilterFailure()) {
log.warn(msg);
} else {
log.debug(msg);
}
}
return false;
}
}
return sessionAttributeNamePattern.matcher(name).matches();

Pattern sessionAttributeValueClassNamePattern = getSessionAttributeValueClassNamePattern();
if (value != null && sessionAttributeValueClassNamePattern != null) {
if (!sessionAttributeValueClassNamePattern.matcher(
value.getClass().getName()).matches()) {
if (getWarnOnSessionAttributeFilterFailure() || log.isDebugEnabled()) {
String msg = sm.getString("managerBase.sessionAttributeValueClassNameFilter",
name, value.getClass().getName(), sessionAttributeNamePattern);
if (getWarnOnSessionAttributeFilterFailure()) {
log.warn(msg);
} else {
log.debug(msg);
}
}
return false;
}
}

return true;
}


Expand Down
16 changes: 16 additions & 0 deletions java/org/apache/catalina/session/mbeans-descriptors.xml
Expand Up @@ -137,6 +137,14 @@
descritpion="The string pattern used for including session attributes in distribution. Null means all attributes are included."
type="java.lang.String"/>

<attribute name="sessionAttributeValueClassNameFilter"
description="The regular expression used to filter session attributes based on the implementation class of the value. The regular expression is anchored and must match the fully qualified class name."
type="java.lang.String"/>

<attribute name="warnOnSessionAttributeFilterFailure"
description="Should a WARN level log message be generated if a session attribute fails to match sessionAttributeNameFilter or sessionAttributeClassNameFilter?"
type="boolean"/>

<operation name="backgroundProcess"
description="Invalidate all sessions that have expired."
impact="ACTION"
Expand Down Expand Up @@ -329,6 +337,14 @@
descritpion="The string pattern used for including session attributes in distribution. Null means all attributes are included."
type="java.lang.String"/>

<attribute name="sessionAttributeValueClassNameFilter"
description="The regular expression used to filter session attributes based on the implementation class of the value. The regular expression is anchored and must match the fully qualified class name."
type="java.lang.String"/>

<attribute name="warnOnSessionAttributeFilterFailure"
description="Should a WARN level log message be generated if a session attribute fails to match sessionAttributeNameFilter or sessionAttributeClassNameFilter?"
type="boolean"/>

<operation name="backgroundProcess"
description="Invalidate all sessions that have expired."
impact="ACTION"
Expand Down
7 changes: 7 additions & 0 deletions webapps/docs/changelog.xml
Expand Up @@ -172,6 +172,13 @@
well as unload to ensure that configuration changes made while the web
application is stopped are applied to any persisted data. (markt)
</add>
<add>
Extend the session attribute filtering options to include filtering
based on the implementation class of the value and optional
<code>WARN</code> level logging if an attribute is filtered. These
options are avaialble for all of the Manager implementations that ship
with Tomcat. (markt)
</add>
</changelog>
</subsection>
<subsection name="Jasper">
Expand Down
67 changes: 56 additions & 11 deletions webapps/docs/config/cluster-manager.xml
Expand Up @@ -83,17 +83,6 @@
sessions to expire on all nodes when a shutdown occurs on one node, set
this value to <code>true</code>. Default value is <code>false</code>.
</attribute>
<attribute name="sessionAttributeNameFilter" required="false">
A regular expression used to filter which session attributes will be
replicated. An attribute will only be replicated if its name matches
this pattern. If the pattern is zero length or <code>null</code>, all
attributes are eligible for replication. The pattern is anchored so the
session attribute name must fully match the pattern. As an example, the
value <code>(userName|sessionHistory)</code> will only replicate the
two session attributes named <code>userName</code> and
<code>sessionHistory</code>. If not specified, the default value of
<code>null</code> will be used.
</attribute>
<attribute name="maxInactiveInterval" required="false">
<p>The initial maximum time interval, in seconds,
between client requests before a session is invalidated. A negative value
Expand Down Expand Up @@ -196,6 +185,26 @@
effective only when <code>sendAllSessions</code> is <code>false</code>.
Default is <code>2000</code> milliseconds.
</attribute>
<attribute name="sessionAttributeNameFilter" required="false">
<p>A regular expression used to filter which session attributes will be
replicated. An attribute will only be replicated if its name matches
this pattern. If the pattern is zero length or <code>null</code>, all
attributes are eligible for replication. The pattern is anchored so the
session attribute name must fully match the pattern. As an example, the
value <code>(userName|sessionHistory)</code> will only replicate the
two session attributes named <code>userName</code> and
<code>sessionHistory</code>. If not specified, the default value of
<code>null</code> will be used.</p>
</attribute>
<attribute name="sessionAttributeValueClassNameFilter" required="false">
<p>A regular expression used to filter which session attributes will be
replicated. An attribute will only be replicated if the implementation
class name of the value matches this pattern. If the pattern is zero
length or <code>null</code>, all attributes are eligible for
replication. The pattern is anchored so the fully qualified class name
must fully match the pattern. If not specified, the default value of
<code>null</code> will be used.</p>
</attribute>
<attribute name="stateTimestampDrop" required="false">
When this node sends a <code>GET_ALL_SESSIONS</code> message to other
node, all session messages that are received as a response are queued.
Expand All @@ -207,6 +216,14 @@
If set to <code>false</code>, all queued session messages are handled.
Default is <code>true</code>.
</attribute>
<attribute name="warnOnSessionAttributeFilterFailure" required="false">
<p>If <strong>sessionAttributeNameFilter</strong> or
<strong>sessionAttributeValueClassNameFilter</strong> blocks an
attribute, should this be logged at <code>WARN</code> level? If
<code>WARN</code> level logging is disabled then it will be logged at
<code>DEBUG</code>. The default value of this attribute is
<code>false</code>.</p>
</attribute>
</attributes>
</subsection>
<subsection name="org.apache.catalina.ha.session.BackupManager Attributes">
Expand All @@ -230,13 +247,41 @@
another map.
Default value is <code>15000</code> milliseconds.
</attribute>
<attribute name="sessionAttributeNameFilter" required="false">
<p>A regular expression used to filter which session attributes will be
replicated. An attribute will only be replicated if its name matches
this pattern. If the pattern is zero length or <code>null</code>, all
attributes are eligible for replication. The pattern is anchored so the
session attribute name must fully match the pattern. As an example, the
value <code>(userName|sessionHistory)</code> will only replicate the
two session attributes named <code>userName</code> and
<code>sessionHistory</code>. If not specified, the default value of
<code>null</code> will be used.</p>
</attribute>
<attribute name="sessionAttributeValueClassNameFilter" required="false">
<p>A regular expression used to filter which session attributes will be
replicated. An attribute will only be replicated if the implementation
class name of the value matches this pattern. If the pattern is zero
length or <code>null</code>, all attributes are eligible for
replication. The pattern is anchored so the fully qualified class name
must fully match the pattern. If not specified, the default value of
<code>null</code> will be used.</p>
</attribute>
<attribute name="terminateOnStartFailure" required="false">
Set to true if you wish to terminate replication map when replication
map fails to start. If replication map is terminated, associated context
will fail to start. If you set this attribute to false, replication map
does not end. It will try to join the map membership in the heartbeat.
Default value is <code>false</code> .
</attribute>
<attribute name="warnOnSessionAttributeFilterFailure" required="false">
<p>If <strong>sessionAttributeNameFilter</strong> or
<strong>sessionAttributeValueClassNameFilter</strong> blocks an
attribute, should this be logged at <code>WARN</code> level? If
<code>WARN</code> level logging is disabled then it will be logged at
<code>DEBUG</code>. The default value of this attribute is
<code>false</code>.</p>
</attribute>
</attributes>
</subsection>
</section>
Expand Down

0 comments on commit 79e8ad0

Please sign in to comment.