package com.hwlcn.security.web.filter.authc; import com.hwlcn.security.authc.AuthenticationToken; import com.hwlcn.security.codec.Base64; import com.hwlcn.security.web.util.WebUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.Locale; public class BasicHttpAuthenticationFilter extends AuthenticatingFilter { private static final Logger log = LoggerFactory.getLogger(BasicHttpAuthenticationFilter.class); protected static final String AUTHORIZATION_HEADER = "Authorization"; protected static final String AUTHENTICATE_HEADER = "WWW-Authenticate"; private String applicationName = "application"; private String authcScheme = HttpServletRequest.BASIC_AUTH; private String authzScheme = HttpServletRequest.BASIC_AUTH; public String getApplicationName() { return applicationName; } public void setApplicationName(String applicationName) { this.applicationName = applicationName; } public String getAuthzScheme() { return authzScheme; } public void setAuthzScheme(String authzScheme) { this.authzScheme = authzScheme; } public String getAuthcScheme() { return authcScheme; } public void setAuthcScheme(String authcScheme) { this.authcScheme = authcScheme; } protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception { boolean loggedIn = false; if (isLoginAttempt(request, response)) { loggedIn = executeLogin(request, response); } if (!loggedIn) { sendChallenge(request, response); } return loggedIn; } protected boolean isLoginAttempt(ServletRequest request, ServletResponse response) { String authzHeader = getAuthzHeader(request); return authzHeader != null && isLoginAttempt(authzHeader); } @Override protected final boolean isLoginRequest(ServletRequest request, ServletResponse response) { return this.isLoginAttempt(request, response); } protected String getAuthzHeader(ServletRequest request) { HttpServletRequest httpRequest = WebUtils.toHttp(request); return httpRequest.getHeader(AUTHORIZATION_HEADER); } protected boolean isLoginAttempt(String authzHeader) { String authzScheme = getAuthzScheme().toLowerCase(Locale.ENGLISH); return authzHeader.toLowerCase(Locale.ENGLISH).startsWith(authzScheme); } protected boolean sendChallenge(ServletRequest request, ServletResponse response) { if (log.isDebugEnabled()) { log.debug("Authentication required: sending 401 Authentication challenge response."); } HttpServletResponse httpResponse = WebUtils.toHttp(response); httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED); String authcHeader = getAuthcScheme() + " realm=\"" + getApplicationName() + "\""; httpResponse.setHeader(AUTHENTICATE_HEADER, authcHeader); return false; } protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) { String authorizationHeader = getAuthzHeader(request); if (authorizationHeader == null || authorizationHeader.length() == 0) { return createToken("", "", request, response); } if (log.isDebugEnabled()) { log.debug("Attempting to execute login with headers [" + authorizationHeader + "]"); } String[] prinCred = getPrincipalsAndCredentials(authorizationHeader, request); if (prinCred == null || prinCred.length < 2) { String username = prinCred == null || prinCred.length == 0 ? "" : prinCred[0]; return createToken(username, "", request, response); } String username = prinCred[0]; String password = prinCred[1]; return createToken(username, password, request, response); } protected String[] getPrincipalsAndCredentials(String authorizationHeader, ServletRequest request) { if (authorizationHeader == null) { return null; } String[] authTokens = authorizationHeader.split(" "); if (authTokens == null || authTokens.length < 2) { return null; } return getPrincipalsAndCredentials(authTokens[0], authTokens[1]); } protected String[] getPrincipalsAndCredentials(String scheme, String encoded) { String decoded = Base64.decodeToString(encoded); return decoded.split(":", 2); } }