📄 authenticationmanager.java
字号:
* this method fires event {@link com.ecyrd.jspwiki.event.WikiSecurityEvent#LOGIN_ASSERTED} * with two parameters: <code>WikiPrincipal(<em>cookievalue</em>)</code>, and * the current WikiSession.</li> * <li>If, after checking for authenticated and asserted status, the WikiSession is * <em>still</em> anonymous, this method fires event * {@link com.ecyrd.jspwiki.event.WikiSecurityEvent#LOGIN_ANONYMOUS} with * two parameters: <code>WikiPrincipal(<em>remoteAddress</em>)</code>, * and the current WikiSession </li> * </ul> * @param request servlet request for this user * @return always returns <code>true</code> (because anonymous login, at least, will always succeed) * @throws com.ecyrd.jspwiki.auth.WikiSecurityException if the user cannot be logged in for any reason * @since 2.3 */ public final boolean login( HttpServletRequest request ) throws WikiSecurityException { HttpSession httpSession = request.getSession(); WikiSession session = SessionMonitor.getInstance(m_engine).find( httpSession ); AuthenticationManager authenticationMgr = m_engine.getAuthenticationManager(); AuthorizationManager authorizationMgr = m_engine.getAuthorizationManager(); CallbackHandler handler = null; Map<String,String> options = EMPTY_MAP; // If user not authenticated, check if container logged them in, or if // there's an authentication cookie if ( !session.isAuthenticated() ) { // Create a callback handler handler = new WebContainerCallbackHandler( m_engine, request ); // Execute the container login module, then (if that fails) the cookie auth module Set<Principal> principals = authenticationMgr.doJAASLogin( WebContainerLoginModule.class, handler, options ); if ( principals.size() == 0 && authenticationMgr.allowsCookieAuthentication() ) { principals = authenticationMgr.doJAASLogin( CookieAuthenticationLoginModule.class, handler, options ); } // If the container logged the user in successfully, tell the WikiSession (and add all of the Principals) if ( principals.size() > 0 ) { fireEvent( WikiSecurityEvent.LOGIN_AUTHENTICATED, getLoginPrincipal( principals ), session ); for ( Principal principal : principals ) { fireEvent( WikiSecurityEvent.PRINCIPAL_ADD, principal, session ); } // Add all appropriate Authorizer roles injectAuthorizerRoles( session, authorizationMgr.getAuthorizer(), request ); } } // If user still not authenticated, check if assertion cookie was supplied if ( !session.isAuthenticated() && authenticationMgr.allowsCookieAssertions() ) { // Execute the cookie assertion login module Set<Principal> principals = authenticationMgr.doJAASLogin( CookieAssertionLoginModule.class, handler, options ); if ( principals.size() > 0 ) { fireEvent( WikiSecurityEvent.LOGIN_ASSERTED, getLoginPrincipal( principals ), session); } } // If user still anonymous, use the remote address if (session.isAnonymous() ) { Set<Principal> principals = authenticationMgr.doJAASLogin( AnonymousLoginModule.class, handler, options ); if ( principals.size() > 0 ) { fireEvent( WikiSecurityEvent.LOGIN_ANONYMOUS, getLoginPrincipal( principals ), session ); return true; } } // If by some unusual turn of events the Anonymous login module doesn't work, login failed! return false; } /** * Attempts to perform a WikiSession login for the given username/password * combination using JSPWiki's custom authentication mode. In order to log in, * the JAAS LoginModule supplied by the WikiEngine property {@link #PROP_LOGIN_MODULE} * will be instantiated, and its * {@link javax.security.auth.spi.LoginModule#initialize(Subject, CallbackHandler, Map, Map)} * method will be invoked. By default, the {@link com.ecyrd.jspwiki.auth.login.UserDatabaseLoginModule} * class will be used. When the LoginModule's <code>initialize</code> method is invoked, * an options Map populated by properties keys prefixed by {@link #PREFIX_LOGIN_MODULE_OPTIONS} * will be passed as a parameter. * @param session the current wiki session; may not be null. * @param username The user name. This is a login name, not a WikiName. In * most cases they are the same, but in some cases, they might * not be. * @param password the password * @return true, if the username/password is valid * @throws com.ecyrd.jspwiki.auth.WikiSecurityException if the Authorizer or UserManager cannot be obtained */ public final boolean login( WikiSession session, String username, String password ) throws WikiSecurityException { if ( session == null ) { log.error( "No wiki session provided, cannot log in." ); return false; } // Protect against brute-force password guessing if configured to do so if ( m_throttleLogins ) { delayLogin(username); } UserManager userMgr = m_engine.getUserManager(); CallbackHandler handler = new WikiCallbackHandler( userMgr.getUserDatabase(), username, password ); // Execute the user's specified login module Set<Principal> principals = doJAASLogin( m_loginModuleClass, handler, m_loginModuleOptions ); if (principals.size() > 0) { fireEvent(WikiSecurityEvent.LOGIN_AUTHENTICATED, getLoginPrincipal( principals ), session ); for ( Principal principal : principals ) { fireEvent( WikiSecurityEvent.PRINCIPAL_ADD, principal, session ); } // Add all appropriate Authorizer roles injectAuthorizerRoles( session, m_engine.getAuthorizationManager().getAuthorizer(), null ); return true; } return false; } /** * This method builds a database of login names that are being attempted, and will try to * delay if there are too many requests coming in for the same username. * <p> * The current algorithm uses 2^loginattempts as the delay in milliseconds, i.e. * at 10 login attempts it'll add 1.024 seconds to the login. * * @param username The username that is being logged in */ private void delayLogin( String username ) { try { m_lastLoginAttempts.cleanup( LASTLOGINS_CLEANUP_TIME ); int count = m_lastLoginAttempts.count( username ); long delay = Math.min( 1<<count, MAX_LOGIN_DELAY ); log.debug( "Sleeping for "+delay+" ms to allow login." ); Thread.sleep( delay ); m_lastLoginAttempts.add( username ); } catch( InterruptedException e ) { // FALLTHROUGH is fine } } /** * Logs the user out by retrieving the WikiSession associated with the * HttpServletRequest and unbinding all of the Subject's Principals, * except for {@link Role#ALL}, {@link Role#ANONYMOUS}. * is a cheap-and-cheerful way to do it without invoking JAAS LoginModules. * The logout operation will also flush the JSESSIONID cookie from * the user's browser session, if it was set. * @param request the current HTTP request */ public final void logout( HttpServletRequest request ) { if( request == null ) { log.error( "No HTTP reqest provided; cannot log out." ); return; } HttpSession session = request.getSession(); String sid = ( session == null ) ? "(null)" : session.getId(); if( log.isDebugEnabled() ) { log.debug( "Invalidating WikiSession for session ID=" + sid ); } // Retrieve the associated WikiSession and clear the Principal set WikiSession wikiSession = WikiSession.getWikiSession( m_engine, request ); Principal originalPrincipal = wikiSession.getLoginPrincipal(); wikiSession.invalidate(); // Remove the wikiSession from the WikiSession cache WikiSession.removeWikiSession( m_engine, request ); // We need to flush the HTTP session too if ( session != null ) { session.invalidate(); } // Log the event fireEvent( WikiSecurityEvent.LOGOUT, originalPrincipal, null ); } /** * Determines whether this WikiEngine allows users to assert identities using * cookies instead of passwords. This is determined by inspecting * the WikiEngine property {@link #PROP_ALLOW_COOKIE_ASSERTIONS}. * @return <code>true</code> if cookies are allowed */ public final boolean allowsCookieAssertions() { return m_allowsCookieAssertions; } /** * Determines whether this WikiEngine allows users to authenticate using * cookies instead of passwords. This is determined by inspecting * the WikiEngine property {@link #PROP_ALLOW_COOKIE_AUTH}. * @return <code>true</code> if cookies are allowed for authentication * @since 2.5.62 */ public final boolean allowsCookieAuthentication() { return m_allowsCookieAuthentication; } /** * Determines whether the supplied Principal is a "role principal". * @param principal the principal to test * @return <code>true</code> if the Principal is of type * {@link GroupPrincipal} or * {@link com.ecyrd.jspwiki.auth.authorize.Role}, * <code>false</code> otherwise */ public static final boolean isRolePrincipal( Principal principal ) { return principal instanceof Role || principal instanceof GroupPrincipal; } /** * Determines whether the supplied Principal is a "user principal". * @param principal the principal to test * @return <code>false</code> if the Principal is of type * {@link GroupPrincipal} or * {@link com.ecyrd.jspwiki.auth.authorize.Role}, * <code>true</code> otherwise */ public static final boolean isUserPrincipal( Principal principal ) { return !isRolePrincipal( principal ); } /** * Instantiates and executes a single JAAS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -