This is an automated email from the ASF dual-hosted git repository.
michaelo pushed a commit to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/9.0.x by this push:
new 024a495 Add support for additional user attributes in TomcatPrincipal
024a495 is described below
commit 024a4956f0053569beb3f842dc1154c9b7979977
Author: Carsten Klein <[email protected]>
AuthorDate: Tue Feb 8 16:53:22 2022 +0100
Add support for additional user attributes in TomcatPrincipal
This closes #472
---
java/org/apache/catalina/TomcatPrincipal.java | 32 ++++++++++++++++
.../apache/catalina/realm/GenericPrincipal.java | 42 ++++++++++++++++++---
java/org/apache/catalina/realm/JNDIRealm.java | 2 +-
webapps/docs/changelog.xml | 5 +++
webapps/examples/jsp/security/protected/index.jsp | 44 ++++++++++++++++++++++
5 files changed, 119 insertions(+), 6 deletions(-)
diff --git a/java/org/apache/catalina/TomcatPrincipal.java
b/java/org/apache/catalina/TomcatPrincipal.java
index 83f9035..b74f187 100644
--- a/java/org/apache/catalina/TomcatPrincipal.java
+++ b/java/org/apache/catalina/TomcatPrincipal.java
@@ -17,6 +17,8 @@
package org.apache.catalina;
import java.security.Principal;
+import java.util.Collections;
+import java.util.Enumeration;
import org.ietf.jgss.GSSCredential;
@@ -47,4 +49,34 @@ public interface TomcatPrincipal extends Principal {
* exception to LoginContext
*/
void logout() throws Exception;
+
+ /**
+ * Returns the value of the named attribute as an <code>Object</code>, or
+ * <code>null</code> if no attribute of the given name exists, or if
+ * <code>null</code> has been specified as the attribute's name.
+ * <p>
+ * Only the servlet container may set attributes to make available custom
+ * information about a Principal or the user it represents.
+ *
+ * @param name a <code>String</code> specifying the name of the attribute
+ * @return an <code>Object</code> containing the value of the attribute, or
+ * <code>null</code> if the attribute does not exist, or if
+ * <code>null</code> has been specified as the attribute's name
+ */
+ default Object getAttribute(String name) {
+ return null;
+ }
+
+ /**
+ * Returns an <code>Enumeration</code> containing the names of the
+ * attributes available to this Principal. This method returns an empty
+ * <code>Enumeration</code> if the Principal has no attributes available to
+ * it.
+ *
+ * @return an <code>Enumeration</code> of strings containing the names of
+ * the Principal's attributes
+ */
+ default Enumeration<String> getAttributeNames() {
+ return Collections.emptyEnumeration();
+ }
}
diff --git a/java/org/apache/catalina/realm/GenericPrincipal.java
b/java/org/apache/catalina/realm/GenericPrincipal.java
index d8a8167..52a039b 100644
--- a/java/org/apache/catalina/realm/GenericPrincipal.java
+++ b/java/org/apache/catalina/realm/GenericPrincipal.java
@@ -19,7 +19,10 @@ package org.apache.catalina.realm;
import java.io.Serializable;
import java.security.Principal;
import java.util.Arrays;
+import java.util.Collections;
+import java.util.Enumeration;
import java.util.List;
+import java.util.Map;
import javax.security.auth.login.LoginContext;
@@ -83,7 +86,7 @@ public class GenericPrincipal implements TomcatPrincipal,
Serializable {
*/
public GenericPrincipal(String name, String password, List<String> roles,
Principal userPrincipal, LoginContext loginContext) {
- this(name, password, roles, userPrincipal, loginContext, null);
+ this(name, password, roles, userPrincipal, loginContext, null, null);
}
/**
@@ -99,10 +102,12 @@ public class GenericPrincipal implements TomcatPrincipal,
Serializable {
* @param loginContext - If provided, this will be used to log out the
user
* at the appropriate time
* @param gssCredential - If provided, the user's delegated credentials
+ * @param attributes - If provided, additional attributes associated with
+ * this Principal
*/
public GenericPrincipal(String name, String password, List<String> roles,
Principal userPrincipal, LoginContext loginContext,
- GSSCredential gssCredential) {
+ GSSCredential gssCredential, Map<String, Object> attributes) {
super();
this.name = name;
this.password = password;
@@ -117,6 +122,7 @@ public class GenericPrincipal implements TomcatPrincipal,
Serializable {
}
this.loginContext = loginContext;
this.gssCredential = gssCredential;
+ this.attributes = attributes != null ?
Collections.unmodifiableMap(attributes) : null;
}
@@ -189,6 +195,11 @@ public class GenericPrincipal implements TomcatPrincipal,
Serializable {
this.gssCredential = gssCredential;
}
+ /**
+ * The additional attributes associated with this Principal.
+ */
+ protected final Map<String, Object> attributes;
+
// ---------------------------------------------------------- Public
Methods
@@ -239,10 +250,28 @@ public class GenericPrincipal implements TomcatPrincipal,
Serializable {
}
+ @Override
+ public Object getAttribute(String name) {
+ if (attributes == null || name == null) {
+ return null;
+ }
+ return attributes.get(name);
+ }
+
+
+ @Override
+ public Enumeration<String> getAttributeNames() {
+ if (attributes == null) {
+ return Collections.emptyEnumeration();
+ }
+ return Collections.enumeration(attributes.keySet());
+ }
+
+
// -----------------------------------------------------------
Serialization
private Object writeReplace() {
- return new SerializablePrincipal(name, password, roles, userPrincipal);
+ return new SerializablePrincipal(name, password, roles, userPrincipal,
attributes);
}
private static class SerializablePrincipal implements Serializable {
@@ -252,9 +281,10 @@ public class GenericPrincipal implements TomcatPrincipal,
Serializable {
private final String password;
private final String[] roles;
private final Principal principal;
+ private final Map<String, Object> attributes;
public SerializablePrincipal(String name, String password, String[]
roles,
- Principal principal) {
+ Principal principal, Map<String, Object> attributes) {
this.name = name;
this.password = password;
this.roles = roles;
@@ -263,10 +293,12 @@ public class GenericPrincipal implements TomcatPrincipal,
Serializable {
} else {
this.principal = null;
}
+ this.attributes = attributes;
}
private Object readResolve() {
- return new GenericPrincipal(name, password, Arrays.asList(roles),
principal);
+ return new GenericPrincipal(name, password, Arrays.asList(roles),
principal, null, null,
+ attributes);
}
}
}
diff --git a/java/org/apache/catalina/realm/JNDIRealm.java
b/java/org/apache/catalina/realm/JNDIRealm.java
index 80c829f..672ecf5 100644
--- a/java/org/apache/catalina/realm/JNDIRealm.java
+++ b/java/org/apache/catalina/realm/JNDIRealm.java
@@ -2517,7 +2517,7 @@ public class JNDIRealm extends RealmBase {
}
if (user != null) {
- return new GenericPrincipal(user.getUserName(),
user.getPassword(), roles, null, null, gssCredential);
+ return new GenericPrincipal(user.getUserName(),
user.getPassword(), roles, null, null, gssCredential, null);
}
return null;
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 939630a..785c4ad 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -128,6 +128,11 @@
Tomcat will not load from web applications. Pull request provided by
ppkarwasz. (markt)
</fix>
+ <add>
+ <pr>472</pr>: Add support for additional user attributes to
+ <code>TomcatPrincipal</code> and <code>GenericPrincipal</code>.
+ Patch provided by Carsten Klein. (michaelo)
+ </add>
</changelog>
</subsection>
<subsection name="Coyote">
diff --git a/webapps/examples/jsp/security/protected/index.jsp
b/webapps/examples/jsp/security/protected/index.jsp
index 31122eb..75ac4bc 100644
--- a/webapps/examples/jsp/security/protected/index.jsp
+++ b/webapps/examples/jsp/security/protected/index.jsp
@@ -15,6 +15,8 @@
limitations under the License.
--%>
<%@ page import="java.util.Enumeration" %>
+<%@ page import="java.security.Principal" %>
+<%@ page import="org.apache.catalina.TomcatPrincipal" %>
<%
if (request.getParameter("logoff") != null) {
session.invalidate();
@@ -73,6 +75,48 @@ enter it here:
</form>
<br><br>
+<%
+ Principal p = request.getUserPrincipal();
+ if (!(p instanceof TomcatPrincipal)) {
+%>
+<p>The principal does not support attributes.</p>
+<%
+ } else {
+ TomcatPrincipal principal = (TomcatPrincipal) p;
+%>
+<p>The principal contains the following attributes:</p>
+<table>
+<tr><th>Name</th><th>Value</th><th>Type</th></tr>
+<%
+ Enumeration<String> names = principal.getAttributeNames();
+ while (names.hasMoreElements()) {
+ String name = names.nextElement();
+ Object value = principal.getAttribute(name);
+ String type = value != null ? value.getClass().getName() : "unknown";
+ if (value instanceof Object[]) {
+ Object[] values = (Object[]) value;
+ value = "";
+ for (int i = 0; i < values.length; i++) {
+ value += values[i] + "<br/>";
+ }
+ if (values.length > 0) {
+ type = values[0].getClass().getName() + "[]";
+ } else {
+ type = "unknown";
+ }
+ }
+ type = type.replaceFirst("^java\\.lang\\.", "");
+%>
+<tr><td><%= name %></td><td><%= value %></td><td><%= type %></td>
+<%
+ }
+%>
+</table>
+<%
+ }
+%>
+<br><br>
+
To add some data to the authenticated session, enter it here:
<form method="GET" action='<%= response.encodeURL("index.jsp") %>'>
<input type="text" name="dataName">
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]