📄 singlesignon.java
字号:
// of all session associated with the SSO.
if (System.currentTimeMillis() - session.getLastAccessedTime() >=
session.getMaxInactiveInterval() * 1000) {
removeSession(ssoId, session);
} else {
// The session was logged out.
// Deregister this single session id, invalidating
// associated sessions
deregister(ssoId);
}
}
// ---------------------------------------------------------- Valve Methods
/**
* Return descriptive information about this Valve implementation.
*/
public String getInfo() {
return (info);
}
/**
* Perform single-sign-on support processing for this request.
*
* @param request The servlet request we are processing
* @param response The servlet response we are creating
* @param context The valve context used to invoke the next valve
* in the current processing pipeline
*
* @exception IOException if an input/output error occurs
* @exception ServletException if a servlet error occurs
*/
public void invoke(Request request, Response response,
ValveContext context)
throws IOException, ServletException {
// If this is not an HTTP request and response, just pass them on
if (!(request instanceof HttpRequest) ||
!(response instanceof HttpResponse)) {
context.invokeNext(request, response);
return;
}
HttpServletRequest hreq =
(HttpServletRequest) request.getRequest();
HttpServletResponse hres =
(HttpServletResponse) response.getResponse();
request.removeNote(Constants.REQ_SSOID_NOTE);
// Has a valid user already been authenticated?
if (debug >= 1)
log("Process request for '" + hreq.getRequestURI() + "'");
if (hreq.getUserPrincipal() != null) {
if (debug >= 1)
log(" Principal '" + hreq.getUserPrincipal().getName() +
"' has already been authenticated");
context.invokeNext(request, response);
return;
}
// Check for the single sign on cookie
if (debug >= 1)
log(" Checking for SSO cookie");
Cookie cookie = null;
Cookie cookies[] = hreq.getCookies();
if (cookies == null)
cookies = new Cookie[0];
for (int i = 0; i < cookies.length; i++) {
if (Constants.SINGLE_SIGN_ON_COOKIE.equals(cookies[i].getName())) {
cookie = cookies[i];
break;
}
}
if (cookie == null) {
if (debug >= 1)
log(" SSO cookie is not present");
context.invokeNext(request, response);
return;
}
// Look up the cached Principal associated with this cookie value
if (debug >= 1)
log(" Checking for cached principal for " + cookie.getValue());
SingleSignOnEntry entry = lookup(cookie.getValue());
if (entry != null) {
if (debug >= 1)
log(" Found cached principal '" +
entry.getPrincipal().getName() + "' with auth type '" +
entry.getAuthType() + "'");
request.setNote(Constants.REQ_SSOID_NOTE, cookie.getValue());
// Only set security elements if reauthentication is not required
if (!getRequireReauthentication()) {
((HttpRequest) request).setAuthType(entry.getAuthType());
((HttpRequest) request).setUserPrincipal(entry.getPrincipal());
}
} else {
if (debug >= 1)
log(" No cached principal found, erasing SSO cookie");
cookie.setMaxAge(0);
hres.addCookie(cookie);
}
// Invoke the next Valve in our pipeline
context.invokeNext(request, response);
}
// --------------------------------------------------------- Public Methods
/**
* Return a String rendering of this object.
*/
public String toString() {
StringBuffer sb = new StringBuffer("SingleSignOn[");
if (container == null )
sb.append("Container is null");
else
sb.append(container.getName());
sb.append("]");
return (sb.toString());
}
// ------------------------------------------------------ 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 (debug >= 1)
log("Associate sso id " + ssoId + " with session " + session);
SingleSignOnEntry sso = lookup(ssoId);
if (sso != null)
sso.addSession(this, session);
synchronized (reverse) {
reverse.put(session, ssoId);
}
}
/**
* Deregister the specified session. If it is the last session,
* then also get rid of the single sign on identifier
*
* @param ssoId Single sign on identifier
* @param session Session to be deregistered
*/
protected void deregister(String ssoId, Session session) {
synchronized (reverse) {
reverse.remove(session);
}
SingleSignOnEntry sso = lookup(ssoId);
if ( sso == null )
return;
sso.removeSession( session );
// see if we are the last session, if so blow away ssoId
Session sessions[] = sso.findSessions();
if ( sessions == null || sessions.length == 0 ) {
synchronized (cache) {
sso = (SingleSignOnEntry) cache.remove(ssoId);
}
}
}
/**
* Deregister the specified single sign on identifier, and invalidate
* any associated sessions.
*
* @param ssoId Single sign on identifier to deregister
*/
protected void deregister(String ssoId) {
if (debug >= 1)
log("Deregistering sso id '" + ssoId + "'");
// Look up and remove the corresponding SingleSignOnEntry
SingleSignOnEntry sso = null;
synchronized (cache) {
sso = (SingleSignOnEntry) cache.remove(ssoId);
}
if (sso == null)
return;
// Expire any associated sessions
Session sessions[] = sso.findSessions();
for (int i = 0; i < sessions.length; i++) {
if (debug >= 2)
log(" Invalidating session " + sessions[i]);
// Remove from reverse cache first to avoid recursion
synchronized (reverse) {
reverse.remove(sessions[i]);
}
// Invalidate this session
sessions[i].expire();
}
// NOTE: Clients may still possess the old single sign on cookie,
// but it will be removed on the next request since it is no longer
// in the cache
}
/**
* Register the specified Principal as being associated with the specified
* value for the single sign on identifier.
*
* @param ssoId Single sign on identifier to register
* @param principal Associated user principal that is identified
* @param authType Authentication type used to authenticate this
* user principal
* @param username Username used to authenticate this user
* @param password Password used to authenticate this user
*/
protected void register(String ssoId, Principal principal, String authType,
String username, String password) {
if (debug >= 1)
log("Registering sso id '" + ssoId + "' for user '" +
principal.getName() + "' with auth type '" + authType + "'");
synchronized (cache) {
cache.put(ssoId, new SingleSignOnEntry(principal, authType,
username, password));
}
}
/**
* Log a message on the Logger associated with our Container (if any).
*
* @param message Message to be logged
*/
protected void log(String message) {
Logger logger = container.getLogger();
if (logger != null)
logger.log(this.toString() + ": " + message);
else
System.out.println(this.toString() + ": " + message);
}
/**
* Log a message on the Logger associated with our Container (if any).
*
* @param message Message to be logged
* @param throwable Associated exception
*/
protected void log(String message, Throwable throwable) {
Logger logger = container.getLogger();
if (logger != null)
logger.log(this.toString() + ": " + message, throwable);
else {
System.out.println(this.toString() + ": " + message);
throwable.printStackTrace(System.out);
}
}
/**
* Look up and return the cached SingleSignOn entry associated with this
* sso id value, if there is one; otherwise return <code>null</code>.
*
* @param ssoId Single sign on identifier to look up
*/
protected SingleSignOnEntry lookup(String ssoId) {
synchronized (cache) {
return ((SingleSignOnEntry) cache.get(ssoId));
}
}
//---------------------------------------------- Package-Protected Methods
/**
* Remove a single Session from a SingleSignOn. Called when
* a session is timed out and no longer active.
*
* @param ssoId Single sign on identifier from which to remove the session.
* @param session the session to be removed.
*/
void removeSession(String ssoId, Session session) {
if (debug >= 1)
log("Removing session " + session.toString() + " from sso id " +
ssoId );
// Get a reference to the SingleSignOn
SingleSignOnEntry entry = lookup(ssoId);
if (entry == null)
return;
// Remove the inactive session from SingleSignOnEntry
entry.removeSession(session);
// Remove the inactive session from the 'reverse' Map.
synchronized(reverse) {
reverse.remove(session);
}
// If there are not sessions left in the SingleSignOnEntry,
// deregister the entry.
if (entry.findSessions().length == 0) {
deregister(ssoId);
}
}
/**
* Updates any <code>SingleSignOnEntry</code> found under key
* <code>ssoId</code> with the given authentication data.
* <p>
* The purpose of this method is to allow an SSO entry that was
* established without a username/password combination (i.e. established
* following DIGEST or CLIENT-CERT authentication) to be updated with
* a username and password if one becomes available through a subsequent
* BASIC or FORM authentication. The SSO entry will then be usable for
* reauthentication.
* <p>
* <b>NOTE:</b> Only updates the SSO entry if a call to
* <code>SingleSignOnEntry.getCanReauthenticate()</code> returns
* <code>false</code>; otherwise, it is assumed that the SSO entry already
* has sufficient information to allow reauthentication and that no update
* is needed.
*
* @param ssoId identifier of Single sign to be updated
* @param principal the <code>Principal</code> returned by the latest
* call to <code>Realm.authenticate</code>.
* @param authType the type of authenticator used (BASIC, CLIENT-CERT,
* DIGEST or FORM)
* @param username the username (if any) used for the authentication
* @param password the password (if any) used for the authentication
*/
void update(String ssoId, Principal principal, String authType,
String username, String password) {
SingleSignOnEntry sso = lookup(ssoId);
if (sso != null && !sso.getCanReauthenticate()) {
if (debug >= 1)
log("Update sso id " + ssoId + " to auth type " + authType);
synchronized(sso) {
sso.updateCredentials(principal, authType, username, password);
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -