001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied. See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019 package org.tynamo.security.shiro.authc;
020
021 import javax.servlet.ServletRequest;
022 import javax.servlet.ServletResponse;
023
024 import org.apache.shiro.authc.AuthenticationException;
025 import org.apache.shiro.authc.AuthenticationToken;
026 import org.apache.shiro.authc.UsernamePasswordToken;
027 import org.apache.shiro.subject.Subject;
028
029 /**
030 * An <code>AuthenticationFilter</code> that is capable of automatically performing an authentication attempt
031 * based on the incoming request.
032 *
033 * @since 0.4.0
034 */
035 public abstract class AuthenticatingFilter extends AuthenticationFilter {
036
037 //TODO - complete JavaDoc
038
039 protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {
040 AuthenticationToken token = createToken(request, response);
041 if (token == null) {
042 String msg = "createToken method implementation returned null. A valid non-null AuthenticationToken " +
043 "must be created in order to execute a login attempt.";
044 throw new IllegalStateException(msg);
045 }
046 try {
047 Subject subject = getSubject(request, response);
048 subject.login(token);
049 return onLoginSuccess(token, subject, request, response);
050 } catch (AuthenticationException e) {
051 return onLoginFailure(token, e, request, response);
052 }
053 }
054
055 protected abstract AuthenticationToken createToken(ServletRequest request, ServletResponse response) throws Exception;
056
057 protected AuthenticationToken createToken(String username, String password,
058 ServletRequest request, ServletResponse response) {
059 boolean rememberMe = isRememberMe(request);
060 String host = getHost(request);
061 return createToken(username, password, rememberMe, host);
062 }
063
064 protected AuthenticationToken createToken(String username, String password,
065 boolean rememberMe, String host) {
066 return new UsernamePasswordToken(username, password, rememberMe, host);
067 }
068
069 protected boolean onLoginSuccess(AuthenticationToken token, Subject subject,
070 ServletRequest request, ServletResponse response) throws Exception {
071 return true;
072 }
073
074 protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e,
075 ServletRequest request, ServletResponse response) {
076 return false;
077 }
078
079 /**
080 * Returns the host name or IP associated with the current subject. This method is primarily provided for use
081 * during construction of an <code>AuthenticationToken</code>.
082 * <p/>
083 * The default implementation merely returns {@link ServletRequest#getRemoteHost()}.
084 *
085 * @param request the incoming ServletRequest
086 * @return the <code>InetAddress</code> to associate with the login attempt.
087 */
088 protected String getHost(ServletRequest request) {
089 return request.getRemoteHost();
090 }
091
092 /**
093 * Returns <code>true</code> if "rememberMe" should be enabled for the login attempt associated with the
094 * current <code>request</code>, <code>false</code> otherwise.
095 * <p/>
096 * This implementation always returns <code>false</code> and is provided as a template hook to subclasses that
097 * support <code>rememberMe</code> logins and wish to determine <code>rememberMe</code> in a custom mannner
098 * based on the current <code>request</code>.
099 *
100 * @param request the incoming ServletRequest
101 * @return <code>true</code> if "rememberMe" should be enabled for the login attempt associated with the
102 * current <code>request</code>, <code>false</code> otherwise.
103 */
104 protected boolean isRememberMe(ServletRequest request) {
105 return false;
106 }
107 }