1 17 18 19 package org.apache.catalina.authenticator; 20 21 22 import java.io.IOException ; 23 import java.security.Principal ; 24 import java.util.HashMap ; 25 import java.util.Map ; 26 27 import javax.servlet.ServletException ; 28 import javax.servlet.http.Cookie ; 29 30 import org.apache.catalina.Lifecycle; 31 import org.apache.catalina.LifecycleException; 32 import org.apache.catalina.LifecycleListener; 33 import org.apache.catalina.Realm; 34 import org.apache.catalina.Session; 35 import org.apache.catalina.SessionEvent; 36 import org.apache.catalina.SessionListener; 37 import org.apache.catalina.connector.Request; 38 import org.apache.catalina.connector.Response; 39 import org.apache.catalina.util.LifecycleSupport; 40 import org.apache.catalina.util.StringManager; 41 import org.apache.catalina.valves.ValveBase; 42 43 44 64 65 public class SingleSignOn 66 extends ValveBase 67 implements Lifecycle, SessionListener { 68 69 70 72 73 77 protected Map cache = new HashMap (); 78 79 80 83 protected static String info = 84 "org.apache.catalina.authenticator.SingleSignOn"; 85 86 87 90 protected LifecycleSupport lifecycle = new LifecycleSupport(this); 91 92 97 private boolean requireReauthentication = false; 98 99 103 protected Map reverse = new HashMap (); 104 105 106 109 protected final static StringManager sm = 110 StringManager.getManager(Constants.Package); 111 112 113 116 protected boolean started = false; 117 118 121 private String cookieDomain; 122 123 125 131 public String getCookieDomain() { 132 return cookieDomain; 133 } 134 139 public void setCookieDomain(String cookieDomain) { 140 if (cookieDomain != null && cookieDomain.trim().length() == 0) { 141 cookieDomain = null; 142 } 143 this.cookieDomain = cookieDomain; 144 } 145 146 163 public boolean getRequireReauthentication() 164 { 165 return requireReauthentication; 166 } 167 168 169 209 public void setRequireReauthentication(boolean required) 210 { 211 this.requireReauthentication = required; 212 } 213 214 215 217 218 223 public void addLifecycleListener(LifecycleListener listener) { 224 225 lifecycle.addLifecycleListener(listener); 226 227 } 228 229 230 234 public LifecycleListener[] findLifecycleListeners() { 235 236 return lifecycle.findLifecycleListeners(); 237 238 } 239 240 241 246 public void removeLifecycleListener(LifecycleListener listener) { 247 248 lifecycle.removeLifecycleListener(listener); 249 250 } 251 252 253 261 public void start() throws LifecycleException { 262 263 if (started) 265 throw new LifecycleException 266 (sm.getString("authenticator.alreadyStarted")); 267 lifecycle.fireLifecycleEvent(START_EVENT, null); 268 started = true; 269 270 } 271 272 273 281 public void stop() throws LifecycleException { 282 283 if (!started) 285 throw new LifecycleException 286 (sm.getString("authenticator.notStarted")); 287 lifecycle.fireLifecycleEvent(STOP_EVENT, null); 288 started = false; 289 290 } 291 292 293 295 296 301 public void sessionEvent(SessionEvent event) { 302 303 if (!Session.SESSION_DESTROYED_EVENT.equals(event.getType()) 305 && (!Session.SESSION_PASSIVATED_EVENT.equals(event.getType()))) 306 return; 307 308 Session session = event.getSession(); 310 if (containerLog.isDebugEnabled()) 311 containerLog.debug("Process session destroyed on " + session); 312 313 String ssoId = null; 314 synchronized (reverse) { 315 ssoId = (String ) reverse.get(session); 316 } 317 if (ssoId == null) 318 return; 319 320 if (((session.getMaxInactiveInterval() > 0) 325 && (System.currentTimeMillis() - session.getLastAccessedTimeInternal() >= 326 session.getMaxInactiveInterval() * 1000)) 327 || (Session.SESSION_PASSIVATED_EVENT.equals(event.getType()))) { 328 removeSession(ssoId, session); 329 } else { 330 deregister(ssoId); 334 } 335 336 } 337 338 339 341 342 345 public String getInfo() { 346 347 return (info); 348 349 } 350 351 352 361 public void invoke(Request request, Response response) 362 throws IOException , ServletException { 363 364 request.removeNote(Constants.REQ_SSOID_NOTE); 365 366 if (containerLog.isDebugEnabled()) 368 containerLog.debug("Process request for '" + request.getRequestURI() + "'"); 369 if (request.getUserPrincipal() != null) { 370 if (containerLog.isDebugEnabled()) 371 containerLog.debug(" Principal '" + request.getUserPrincipal().getName() + 372 "' has already been authenticated"); 373 getNext().invoke(request, response); 374 return; 375 } 376 377 if (containerLog.isDebugEnabled()) 379 containerLog.debug(" Checking for SSO cookie"); 380 Cookie cookie = null; 381 Cookie cookies[] = request.getCookies(); 382 if (cookies == null) 383 cookies = new Cookie [0]; 384 for (int i = 0; i < cookies.length; i++) { 385 if (Constants.SINGLE_SIGN_ON_COOKIE.equals(cookies[i].getName())) { 386 cookie = cookies[i]; 387 break; 388 } 389 } 390 if (cookie == null) { 391 if (containerLog.isDebugEnabled()) 392 containerLog.debug(" SSO cookie is not present"); 393 getNext().invoke(request, response); 394 return; 395 } 396 397 if (containerLog.isDebugEnabled()) 399 containerLog.debug(" Checking for cached principal for " + cookie.getValue()); 400 SingleSignOnEntry entry = lookup(cookie.getValue()); 401 if (entry != null) { 402 if (containerLog.isDebugEnabled()) 403 containerLog.debug(" Found cached principal '" + 404 entry.getPrincipal().getName() + "' with auth type '" + 405 entry.getAuthType() + "'"); 406 request.setNote(Constants.REQ_SSOID_NOTE, cookie.getValue()); 407 if (!getRequireReauthentication()) { 409 request.setAuthType(entry.getAuthType()); 410 request.setUserPrincipal(entry.getPrincipal()); 411 } 412 } else { 413 if (containerLog.isDebugEnabled()) 414 containerLog.debug(" No cached principal found, erasing SSO cookie"); 415 cookie.setMaxAge(0); 416 response.addCookie(cookie); 417 } 418 419 getNext().invoke(request, response); 421 422 } 423 424 425 427 428 431 public String toString() { 432 433 StringBuffer sb = new StringBuffer ("SingleSignOn["); 434 if (container == null ) 435 sb.append("Container is null"); 436 else 437 sb.append(container.getName()); 438 sb.append("]"); 439 return (sb.toString()); 440 441 } 442 443 444 446 447 454 protected void associate(String ssoId, Session session) { 455 456 if (containerLog.isDebugEnabled()) 457 containerLog.debug("Associate sso id " + ssoId + " with session " + session); 458 459 SingleSignOnEntry sso = lookup(ssoId); 460 if (sso != null) 461 sso.addSession(this, session); 462 synchronized (reverse) { 463 reverse.put(session, ssoId); 464 } 465 466 } 467 468 475 protected void deregister(String ssoId, Session session) { 476 477 synchronized (reverse) { 478 reverse.remove(session); 479 } 480 481 SingleSignOnEntry sso = lookup(ssoId); 482 if ( sso == null ) 483 return; 484 485 sso.removeSession( session ); 486 487 Session sessions[] = sso.findSessions(); 489 if ( sessions == null || sessions.length == 0 ) { 490 synchronized (cache) { 491 sso = (SingleSignOnEntry) cache.remove(ssoId); 492 } 493 } 494 495 } 496 497 498 504 protected void deregister(String ssoId) { 505 506 if (containerLog.isDebugEnabled()) 507 containerLog.debug("Deregistering sso id '" + ssoId + "'"); 508 509 SingleSignOnEntry sso = null; 511 synchronized (cache) { 512 sso = (SingleSignOnEntry) cache.remove(ssoId); 513 } 514 515 if (sso == null) 516 return; 517 518 Session sessions[] = sso.findSessions(); 520 for (int i = 0; i < sessions.length; i++) { 521 if (containerLog.isTraceEnabled()) 522 containerLog.trace(" Invalidating session " + sessions[i]); 523 synchronized (reverse) { 525 reverse.remove(sessions[i]); 526 } 527 sessions[i].expire(); 529 } 530 531 535 } 536 537 538 559 protected boolean reauthenticate(String ssoId, Realm realm, 560 Request request) { 561 562 if (ssoId == null || realm == null) 563 return false; 564 565 boolean reauthenticated = false; 566 567 SingleSignOnEntry entry = lookup(ssoId); 568 if (entry != null && entry.getCanReauthenticate()) { 569 570 String username = entry.getUsername(); 571 if (username != null) { 572 Principal reauthPrincipal = 573 realm.authenticate(username, entry.getPassword()); 574 if (reauthPrincipal != null) { 575 reauthenticated = true; 576 request.setAuthType(entry.getAuthType()); 578 request.setUserPrincipal(reauthPrincipal); 579 } 580 } 581 } 582 583 return reauthenticated; 584 } 585 586 587 598 protected void register(String ssoId, Principal principal, String authType, 599 String username, String password) { 600 601 if (containerLog.isDebugEnabled()) 602 containerLog.debug("Registering sso id '" + ssoId + "' for user '" + 603 principal.getName() + "' with auth type '" + authType + "'"); 604 605 synchronized (cache) { 606 cache.put(ssoId, new SingleSignOnEntry(principal, authType, 607 username, password)); 608 } 609 610 } 611 612 613 638 protected void update(String ssoId, Principal principal, String authType, 639 String username, String password) { 640 641 SingleSignOnEntry sso = lookup(ssoId); 642 if (sso != null && !sso.getCanReauthenticate()) { 643 if (containerLog.isDebugEnabled()) 644 containerLog.debug("Update sso id " + ssoId + " to auth type " + authType); 645 646 synchronized(sso) { 647 sso.updateCredentials(principal, authType, username, password); 648 } 649 650 } 651 } 652 653 654 660 protected SingleSignOnEntry lookup(String ssoId) { 661 662 synchronized (cache) { 663 return ((SingleSignOnEntry) cache.get(ssoId)); 664 } 665 666 } 667 668 669 676 protected void removeSession(String ssoId, Session session) { 677 678 if (containerLog.isDebugEnabled()) 679 containerLog.debug("Removing session " + session.toString() + " from sso id " + 680 ssoId ); 681 682 SingleSignOnEntry entry = lookup(ssoId); 684 if (entry == null) 685 return; 686 687 entry.removeSession(session); 689 690 synchronized(reverse) { 692 reverse.remove(session); 693 } 694 695 if (entry.findSessions().length == 0) { 698 deregister(ssoId); 699 } 700 } 701 702 } 703 | Popular Tags |