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);
}
}