Skip to content

Commit fd5b0fb

Browse files
committed
Add support code for custom user attributes
Based on code from 473 by Carsten Klein.
1 parent 1f32463 commit fd5b0fb

File tree

2 files changed

+100
-1
lines changed

2 files changed

+100
-1
lines changed

java/org/apache/catalina/realm/RealmBase.java

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import java.security.Principal;
2727
import java.security.cert.X509Certificate;
2828
import java.util.ArrayList;
29+
import java.util.Collections;
2930
import java.util.List;
3031
import java.util.Locale;
3132

@@ -72,6 +73,21 @@ public abstract class RealmBase extends LifecycleMBeanBase implements Realm {
7273

7374
private static final Log log = LogFactory.getLog(RealmBase.class);
7475

76+
/**
77+
* The character used for delimiting user attribute names.
78+
* <p>
79+
* Applies to some of the Realm implementations only.
80+
*/
81+
protected static final String USER_ATTRIBUTES_DELIMITER = ",";
82+
83+
/**
84+
* The character used as wildcard in user attribute lists. Using it means
85+
* <i>query all available user attributes</i>.
86+
* <p>
87+
* Applies to some of the Realm implementations only.
88+
*/
89+
protected static final String USER_ATTRIBUTES_WILDCARD = "*";
90+
7591
private static final List<Class<? extends DigestCredentialHandlerBase>> credentialHandlerClasses = new ArrayList<>();
7692

7793
static {
@@ -143,6 +159,22 @@ public abstract class RealmBase extends LifecycleMBeanBase implements Realm {
143159
private int transportGuaranteeRedirectStatus = HttpServletResponse.SC_FOUND;
144160

145161

162+
/**
163+
* The comma separated names of user attributes to additionally query from the
164+
* realm. These will be provided to the user through the created
165+
* Principal's <i>attributes</i> map. Support for this feature is optional.
166+
*/
167+
protected String userAttributes = null;
168+
169+
170+
/**
171+
* The list of user attributes to additionally query from the
172+
* realm. These will be provided to the user through the created
173+
* Principal's <i>attributes</i> map. Support for this feature is optional.
174+
*/
175+
protected List<String> userAttributesList = null;
176+
177+
146178
// ------------------------------------------------------------- Properties
147179

148180
/**
@@ -264,6 +296,33 @@ public void setStripRealmForGss(boolean stripRealmForGss) {
264296
}
265297

266298

299+
/**
300+
* @return the comma separated names of user attributes to additionally query from realm
301+
*/
302+
public String getUserAttributes() {
303+
return userAttributes;
304+
}
305+
306+
/**
307+
* Set the comma separated names of user attributes to additionally query from
308+
* the realm. These will be provided to the user through the created
309+
* Principal's <i>attributes</i> map. In this map, each field value is bound to
310+
* the field's name, that is, the name of the field serves as the key of the
311+
* mapping.
312+
* <p>
313+
* If set to the wildcard character, or, if the wildcard character is part of
314+
* the comma separated list, all available attributes - except the
315+
* <i>password</i> attribute (as specified by <code>userCredCol</code>) - are
316+
* queried. The wildcard character is defined by constant
317+
* {@link RealmBase#USER_ATTRIBUTES_WILDCARD}. It defaults to the asterisk (*)
318+
* character.
319+
*
320+
* @param userAttributes the comma separated names of user attributes
321+
*/
322+
public void setUserAttributes(String userAttributes) {
323+
this.userAttributes = userAttributes;
324+
}
325+
267326
// --------------------------------------------------------- Public Methods
268327

269328
@Override
@@ -845,6 +904,40 @@ public boolean hasRole(Wrapper wrapper, Principal principal, String role) {
845904
}
846905

847906

907+
/**
908+
* Parse the specified delimiter separated attribute names and return a list of
909+
* that names or <code>null</code>, if no attributes have been specified.
910+
* <p>
911+
* If a wildcard character is found, return a list consisting of a single
912+
* wildcard character only.
913+
*
914+
* @param userAttributes comma separated names of attributes to parse
915+
* @return a list containing the parsed attribute names or <code>null</code>, if
916+
* no attributes have been specified
917+
*/
918+
protected List<String> parseUserAttributes(String userAttributes) {
919+
if (userAttributes == null) {
920+
return null;
921+
}
922+
List<String> attrs = new ArrayList<>();
923+
for (String name : userAttributes.split(USER_ATTRIBUTES_DELIMITER)) {
924+
name = name.trim();
925+
if (name.length() == 0) {
926+
continue;
927+
}
928+
if (name.equals(USER_ATTRIBUTES_WILDCARD)) {
929+
return Collections.singletonList(USER_ATTRIBUTES_WILDCARD);
930+
}
931+
if (attrs.contains(name)) {
932+
// skip duplicates
933+
continue;
934+
}
935+
attrs.add(name);
936+
}
937+
return attrs.size() > 0 ? attrs : null;
938+
}
939+
940+
848941
/**
849942
* Check if the specified Principal has the specified security role, within the context of this Realm. This method
850943
* or {@link #hasRoleInternal(Principal, String)} can be overridden by Realm implementations, but the default is
@@ -979,7 +1072,9 @@ protected void startInternal() throws LifecycleException {
9791072
if (credentialHandler == null) {
9801073
credentialHandler = new MessageDigestCredentialHandler();
9811074
}
982-
1075+
if (userAttributes != null) {
1076+
userAttributesList = parseUserAttributes(userAttributes);
1077+
}
9831078
setState(LifecycleState.STARTING);
9841079
}
9851080

webapps/docs/changelog.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,10 @@
156156
<bug>66524</bug> Correct eviction ordering in WebResource cache to
157157
by LRU as intended. (schultz)
158158
</fix>
159+
<update>
160+
Add support code for custom user attributes in <code>RealmBase</code>.
161+
Based on code from <pr>473</pr> by Carsten Klein. (remm)
162+
</update>
159163
</changelog>
160164
</subsection>
161165
<subsection name="Coyote">

0 commit comments

Comments
 (0)