📄 authenticatorbase.java
字号:
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);
}
// ------------------------------------------------------ Protected Methods
/**
* Associate the specified single sign on identifier with the
* specified Session.
*
* @param ssoId Single sign on identifier
* @param session Session to be associated
*/
protected void associate(String ssoId, Session session) {
if (sso == null)
return;
sso.associate(ssoId, session);
}
/**
* Authenticate the user making this request, based on the specified
* login configuration. Return <code>true</code> if any specified
* constraint has been satisfied, or <code>false</code> if we have
* created a response challenge already.
*
* @param request Request we are processing
* @param response Response we are creating
* @param config Login configuration describing how authentication
* should be performed
*
* @exception IOException if an input/output error occurs
*/
protected abstract boolean authenticate(Request request,
Response response,
LoginConfig config)
throws IOException;
/**
* Generate and return a new session identifier for the cookie that
* identifies an SSO principal.
*/
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());
}
/**
* 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.
*/
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 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.
*/
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);
}
/**
* Attempts reauthentication to the <code>Realm</code> using
* the credentials included in argument <code>entry</code>.
*
* @param ssoId identifier of SingleSignOn session with which the
* caller is associated
* @param request the request that needs to be authenticated
*/
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;
}
/**
* 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.
*
* @param request The servlet request we are processing
* @param response The servlet response we are generating
* @param principal The authenticated Principal to be registered
* @param authType The authentication type to be registered
* @param username Username used to authenticate (if any)
* @param password Password used to authenticate (if any)
*/
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);
// 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);
}
// ------------------------------------------------------ Lifecycle Methods
/**
* Add a lifecycle event listener to this component.
*
* @param listener The listener to add
*/
public void addLifecycleListener(LifecycleListener listener) {
lifecycle.addLifecycleListener(listener);
}
/**
* Get the lifecycle listeners associated with this lifecycle. If this
* Lifecycle has no listeners registered, a zero-length array is returned.
*/
public LifecycleListener[] findLifecycleListeners() {
return lifecycle.findLifecycleListeners();
}
/**
* Remove a lifecycle event listener from this component.
*
* @param listener The listener to remove
*/
public void removeLifecycleListener(LifecycleListener listener) {
lifecycle.removeLifecycleListener(listener);
}
/**
* Prepare for the beginning of active use of the public methods of this
* component. This method should be called after <code>configure()</code>,
* and before any of the public methods of the component are utilized.
*
* @exception LifecycleException if this component detects a fatal error
* that prevents this component from being used
*/
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");
}
}
/**
* 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.
*
* @exception LifecycleException if this component detects a fatal error
* that needs to be reported
*/
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;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -