| Method from org.apache.catalina.authenticator.AuthenticatorBase Detail: |
public void addLifecycleListener(LifecycleListener listener) {
lifecycle.addLifecycleListener(listener);
}
Add a lifecycle event listener to this component. |
protected void associate(String ssoId,
Session session) {
if (sso == null)
return;
sso.associate(ssoId, session);
}
Associate the specified single sign on identifier with the
specified Session. |
abstract protected boolean authenticate(Request request,
Response response,
LoginConfig config) throws IOException
Authenticate the user making this request, based on the specified
login configuration. Return true if any specified
constraint has been satisfied, or false if we have
created a response challenge already. |
public LifecycleListener[] findLifecycleListeners() {
return lifecycle.findLifecycleListeners();
}
Get the lifecycle listeners associated with this lifecycle. If this
Lifecycle has no listeners registered, a zero-length array is returned. |
protected synchronized String generateSessionId() {
// Generate a byte array containing a session identifier
byte bytes[] = new byte[SESSION_ID_BYTES];
getRandom().nextBytes(bytes);
bytes = getDigest().digest(bytes);
// Render the result as a String of hexadecimal digits
StringBuffer result = new StringBuffer();
for (int i = 0; i < bytes.length; i++) {
byte b1 = (byte) ((bytes[i] & 0xf0) > > 4);
byte b2 = (byte) (bytes[i] & 0x0f);
if (b1 < 10)
result.append((char) ('0' + b1));
else
result.append((char) ('A' + (b1 - 10)));
if (b2 < 10)
result.append((char) ('0' + b2));
else
result.append((char) ('A' + (b2 - 10)));
}
return (result.toString());
}
Generate and return a new session identifier for the cookie that
identifies an SSO principal. |
public String getAlgorithm() {
return (this.algorithm);
}
Return the message digest algorithm for this Manager. |
public boolean getCache() {
return (this.cache);
}
Return the cache authenticated Principals flag. |
public boolean getChangeSessionIdOnAuthentication() {
return changeSessionIdOnAuthentication;
}
Return the flag that states if we should change the session ID of an
existing session upon successful authentication. |
public Container getContainer() {
return (this.context);
}
Return the Container to which this Valve is attached. |
protected synchronized MessageDigest getDigest() {
if (this.digest == null) {
try {
this.digest = MessageDigest.getInstance(algorithm);
} catch (NoSuchAlgorithmException e) {
try {
this.digest = MessageDigest.getInstance(DEFAULT_ALGORITHM);
} catch (NoSuchAlgorithmException f) {
this.digest = null;
}
}
}
return (this.digest);
}
Return the MessageDigest object to be used for calculating
session identifiers. If none has been created yet, initialize
one the first time this method is called. |
public boolean getDisableProxyCaching() {
return disableProxyCaching;
}
Return the flag that states if we add headers to disable caching by
proxies. |
public String getEntropy() {
// Calculate a semi-useful value if this has not been set
if (this.entropy == null)
setEntropy(this.toString());
return (this.entropy);
}
Return the entropy increaser value, or compute a semi-useful value
if this String has not yet been set. |
public String getInfo() {
return (info);
}
Return descriptive information about this Valve implementation. |
protected synchronized Random getRandom() {
if (this.random == null) {
try {
Class clazz = Class.forName(randomClass);
this.random = (Random) clazz.newInstance();
long seed = System.currentTimeMillis();
char entropy[] = getEntropy().toCharArray();
for (int i = 0; i < entropy.length; i++) {
long update = ((byte) entropy[i]) < < ((i % 8) * 8);
seed ^= update;
}
this.random.setSeed(seed);
} catch (Exception e) {
this.random = new java.util.Random();
}
}
return (this.random);
}
Return the random number generator instance we should use for
generating session identifiers. If there is no such generator
currently defined, construct and seed a new one. |
public String getRandomClass() {
return (this.randomClass);
}
Return the random number generator class name. |
public boolean getSecurePagesWithPragma() {
return securePagesWithPragma;
}
Return the flag that states, if proxy caching is disabled, what headers
we add to disable the caching. |
public void invoke(Request request,
Response response) throws IOException, ServletException {
if (log.isDebugEnabled())
log.debug("Security checking request " +
request.getMethod() + " " + request.getRequestURI());
LoginConfig config = this.context.getLoginConfig();
// Have we got a cached authenticated Principal to record?
if (cache) {
Principal principal = request.getUserPrincipal();
if (principal == null) {
Session session = request.getSessionInternal(false);
if (session != null) {
principal = session.getPrincipal();
if (principal != null) {
if (log.isDebugEnabled())
log.debug("We have cached auth type " +
session.getAuthType() +
" for principal " +
session.getPrincipal());
request.setAuthType(session.getAuthType());
request.setUserPrincipal(principal);
}
}
}
}
// Special handling for form-based logins to deal with the case
// where the login form (and therefore the "j_security_check" URI
// to which it submits) might be outside the secured area
String contextPath = this.context.getPath();
String requestURI = request.getDecodedRequestURI();
if (requestURI.startsWith(contextPath) &&
requestURI.endsWith(Constants.FORM_ACTION)) {
if (!authenticate(request, response, config)) {
if (log.isDebugEnabled())
log.debug(" Failed authenticate() test ??" + requestURI );
return;
}
}
Realm realm = this.context.getRealm();
// Is this request URI subject to a security constraint?
SecurityConstraint [] constraints
= realm.findSecurityConstraints(request, this.context);
if ((constraints == null) /* &&
(!Constants.FORM_METHOD.equals(config.getAuthMethod())) */ ) {
if (log.isDebugEnabled())
log.debug(" Not subject to any constraint");
getNext().invoke(request, response);
return;
}
// Make sure that constrained resources are not cached by web proxies
// or browsers as caching can provide a security hole
if (disableProxyCaching &&
// FIXME: Disabled for Mozilla FORM support over SSL
// (improper caching issue)
//!request.isSecure() &&
!"POST".equalsIgnoreCase(request.getMethod())) {
if (securePagesWithPragma) {
// FIXME: These cause problems with downloading office docs
// from IE under SSL and may not be needed for newer Mozilla
// clients.
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
} else {
response.setHeader("Cache-Control", "private");
}
response.setHeader("Expires", DATE_ONE);
}
int i;
// Enforce any user data constraint for this security constraint
if (log.isDebugEnabled()) {
log.debug(" Calling hasUserDataPermission()");
}
if (!realm.hasUserDataPermission(request, response,
constraints)) {
if (log.isDebugEnabled()) {
log.debug(" Failed hasUserDataPermission() test");
}
/*
* ASSERT: Authenticator already set the appropriate
* HTTP status code, so we do not have to do anything special
*/
return;
}
// Since authenticate modifies the response on failure,
// we have to check for allow-from-all first.
boolean authRequired = true;
for(i=0; i < constraints.length && authRequired; i++) {
if(!constraints[i].getAuthConstraint()) {
authRequired = false;
} else if(!constraints[i].getAllRoles()) {
String [] roles = constraints[i].findAuthRoles();
if(roles == null || roles.length == 0) {
authRequired = false;
}
}
}
if(authRequired) {
if (log.isDebugEnabled()) {
log.debug(" Calling authenticate()");
}
if (!authenticate(request, response, config)) {
if (log.isDebugEnabled()) {
log.debug(" Failed authenticate() test");
}
/*
* ASSERT: Authenticator already set the appropriate
* HTTP status code, so we do not have to do anything
* special
*/
return;
}
}
if (log.isDebugEnabled()) {
log.debug(" Calling accessControl()");
}
if (!realm.hasResourcePermission(request, response,
constraints,
this.context)) {
if (log.isDebugEnabled()) {
log.debug(" Failed accessControl() test");
}
/*
* ASSERT: AccessControl method has already set the
* appropriate HTTP status code, so we do not have to do
* anything special
*/
return;
}
// Any and all specified constraints have been satisfied
if (log.isDebugEnabled()) {
log.debug(" Successfully passed all security constraints");
}
getNext().invoke(request, response);
}
Enforce the security restrictions in the web application deployment
descriptor of our associated Context. |
protected boolean reauthenticateFromSSO(String ssoId,
Request request) {
if (sso == null || ssoId == null)
return false;
boolean reauthenticated = false;
Container parent = getContainer();
if (parent != null) {
Realm realm = parent.getRealm();
if (realm != null) {
reauthenticated = sso.reauthenticate(ssoId, realm, request);
}
}
if (reauthenticated) {
associate(ssoId, request.getSessionInternal(true));
if (log.isDebugEnabled()) {
log.debug(" Reauthenticated cached principal '" +
request.getUserPrincipal().getName() +
"' with auth type '" + request.getAuthType() + "'");
}
}
return reauthenticated;
}
Attempts reauthentication to the Realm using
the credentials included in argument entry. |
protected void register(Request request,
Response response,
Principal principal,
String authType,
String username,
String password) {
if (log.isDebugEnabled())
log.debug("Authenticated '" + principal.getName() + "' with type '"
+ authType + "'");
// Cache the authentication information in our request
request.setAuthType(authType);
request.setUserPrincipal(principal);
Session session = request.getSessionInternal(false);
if (session != null && changeSessionIdOnAuthentication) {
Manager manager = request.getContext().getManager();
manager.changeSessionId(session);
request.changeSessionId(session.getId());
}
// Cache the authentication information in our session, if any
if (cache) {
if (session != null) {
session.setAuthType(authType);
session.setPrincipal(principal);
if (username != null)
session.setNote(Constants.SESS_USERNAME_NOTE, username);
else
session.removeNote(Constants.SESS_USERNAME_NOTE);
if (password != null)
session.setNote(Constants.SESS_PASSWORD_NOTE, password);
else
session.removeNote(Constants.SESS_PASSWORD_NOTE);
}
}
// Construct a cookie to be returned to the client
if (sso == null)
return;
// Only create a new SSO entry if the SSO did not already set a note
// for an existing entry (as it would do with subsequent requests
// for DIGEST and SSL authenticated contexts)
String ssoId = (String) request.getNote(Constants.REQ_SSOID_NOTE);
if (ssoId == null) {
// Construct a cookie to be returned to the client
ssoId = generateSessionId();
Cookie cookie = new Cookie(Constants.SINGLE_SIGN_ON_COOKIE, ssoId);
cookie.setMaxAge(-1);
cookie.setPath("/");
// Bugzilla 41217
cookie.setSecure(request.isSecure());
// Bugzilla 34724
String ssoDomain = sso.getCookieDomain();
if(ssoDomain != null) {
cookie.setDomain(ssoDomain);
}
response.addCookie(cookie);
// Register this principal with our SSO valve
sso.register(ssoId, principal, authType, username, password);
request.setNote(Constants.REQ_SSOID_NOTE, ssoId);
} else {
// Update the SSO session with the latest authentication data
sso.update(ssoId, principal, authType, username, password);
}
// Fix for Bug 10040
// Always associate a session with a new SSO reqistration.
// SSO entries are only removed from the SSO registry map when
// associated sessions are destroyed; if a new SSO entry is created
// above for this request and the user never revisits the context, the
// SSO entry will never be cleared if we don't associate the session
if (session == null)
session = request.getSessionInternal(true);
sso.associate(ssoId, session);
}
Register an authenticated Principal and authentication type in our
request, in the current session (if there is one), and with our
SingleSignOn valve, if there is one. Set the appropriate cookie
to be returned. |
public void removeLifecycleListener(LifecycleListener listener) {
lifecycle.removeLifecycleListener(listener);
}
Remove a lifecycle event listener from this component. |
public void setAlgorithm(String algorithm) {
this.algorithm = algorithm;
}
Set the message digest algorithm for this Manager. |
public void setCache(boolean cache) {
this.cache = cache;
}
Set the cache authenticated Principals flag. |
public void setChangeSessionIdOnAuthentication(boolean changeSessionIdOnAuthentication) {
this.changeSessionIdOnAuthentication = changeSessionIdOnAuthentication;
}
Set the value of the flag that states if we should change the session ID
of an existing session upon successful authentication. |
public void setContainer(Container container) {
if (!(container instanceof Context))
throw new IllegalArgumentException
(sm.getString("authenticator.notContext"));
super.setContainer(container);
this.context = (Context) container;
}
Set the Container to which this Valve is attached. |
public void setDisableProxyCaching(boolean nocache) {
disableProxyCaching = nocache;
}
Set the value of the flag that states if we add headers to disable
caching by proxies. |
public void setEntropy(String entropy) {
this.entropy = entropy;
}
Set the entropy increaser value. |
public void setRandomClass(String randomClass) {
this.randomClass = randomClass;
}
Set the random number generator class name. |
public void setSecurePagesWithPragma(boolean securePagesWithPragma) {
this.securePagesWithPragma = securePagesWithPragma;
}
Set the value of the flag that states what headers we add to disable
proxy caching. |
public void start() throws LifecycleException {
// Validate and update our current component state
if (started)
throw new LifecycleException
(sm.getString("authenticator.alreadyStarted"));
lifecycle.fireLifecycleEvent(START_EVENT, null);
started = true;
// Look up the SingleSignOn implementation in our request processing
// path, if there is one
Container parent = context.getParent();
while ((sso == null) && (parent != null)) {
if (!(parent instanceof Pipeline)) {
parent = parent.getParent();
continue;
}
Valve valves[] = ((Pipeline) parent).getValves();
for (int i = 0; i < valves.length; i++) {
if (valves[i] instanceof SingleSignOn) {
sso = (SingleSignOn) valves[i];
break;
}
}
if (sso == null)
parent = parent.getParent();
}
if (log.isDebugEnabled()) {
if (sso != null)
log.debug("Found SingleSignOn Valve at " + sso);
else
log.debug("No SingleSignOn Valve is present");
}
}
Prepare for the beginning of active use of the public methods of this
component. This method should be called after configure(),
and before any of the public methods of the component are utilized. |
public void stop() throws LifecycleException {
// Validate and update our current component state
if (!started)
throw new LifecycleException
(sm.getString("authenticator.notStarted"));
lifecycle.fireLifecycleEvent(STOP_EVENT, null);
started = false;
sso = null;
}
Gracefully terminate the active use of the public methods of this
component. This method should be the last one called on a given
instance of this component. |