-
-
Save neolitec/8953607 to your computer and use it in GitHub Desktop.
package com.neolitec.examples; | |
import org.apache.commons.codec.binary.Base64; | |
import org.apache.commons.lang.StringUtils; | |
import org.slf4j.Logger; | |
import org.slf4j.LoggerFactory; | |
import javax.servlet.*; | |
import javax.servlet.http.HttpServletRequest; | |
import javax.servlet.http.HttpServletResponse; | |
import java.io.IOException; | |
import java.io.UnsupportedEncodingException; | |
import java.util.StringTokenizer; | |
/** | |
* Created by kemanson on 12/02/14. | |
*/ | |
public class BasicAuthenticationFilter implements Filter { | |
/** Logger */ | |
private static final Logger LOG = LoggerFactory.getLogger(BasicAuthenticationFilter.class); | |
private String username = ""; | |
private String password = ""; | |
private String realm = "Protected"; | |
@Override | |
public void init(FilterConfig filterConfig) throws ServletException { | |
username = filterConfig.getInitParameter("username"); | |
password = filterConfig.getInitParameter("password"); | |
String paramRealm = filterConfig.getInitParameter("realm"); | |
if (StringUtils.isNotBlank(paramRealm)) { | |
realm = paramRealm; | |
} | |
} | |
@Override | |
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) | |
throws IOException, ServletException { | |
HttpServletRequest request = (HttpServletRequest) servletRequest; | |
HttpServletResponse response = (HttpServletResponse) servletResponse; | |
String authHeader = request.getHeader("Authorization"); | |
if (authHeader != null) { | |
StringTokenizer st = new StringTokenizer(authHeader); | |
if (st.hasMoreTokens()) { | |
String basic = st.nextToken(); | |
if (basic.equalsIgnoreCase("Basic")) { | |
try { | |
String credentials = new String(Base64.decodeBase64(st.nextToken()), "UTF-8"); | |
LOG.debug("Credentials: " + credentials); | |
int p = credentials.indexOf(":"); | |
if (p != -1) { | |
String _username = credentials.substring(0, p).trim(); | |
String _password = credentials.substring(p + 1).trim(); | |
if (!username.equals(_username) || !password.equals(_password)) { | |
unauthorized(response, "Bad credentials"); | |
} | |
filterChain.doFilter(servletRequest, servletResponse); | |
} else { | |
unauthorized(response, "Invalid authentication token"); | |
} | |
} catch (UnsupportedEncodingException e) { | |
throw new Error("Couldn't retrieve authentication", e); | |
} | |
} | |
} | |
} else { | |
unauthorized(response); | |
} | |
} | |
@Override | |
public void destroy() { | |
} | |
private void unauthorized(HttpServletResponse response, String message) throws IOException { | |
response.setHeader("WWW-Authenticate", "Basic realm=\"" + realm + "\""); | |
response.sendError(401, message); | |
} | |
private void unauthorized(HttpServletResponse response) throws IOException { | |
unauthorized(response, "Unauthorized"); | |
} | |
} |
<?xml version="1.0" encoding="UTF-8"?> | |
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> | |
<filter> | |
<filter-name>basicAuthenticationFilter</filter-name> | |
<filter-class>com.neolitec.examples.BasicAuthenticationFilter</filter-class> | |
<init-param> | |
<param-name>username</param-name> | |
<param-value>admin</param-value> | |
</init-param> | |
<init-param> | |
<param-name>password</param-name> | |
<param-value>motdepasse</param-value> | |
</init-param> | |
</filter> | |
<filter-mapping> | |
<filter-name>basicAuthenticationFilter</filter-name> | |
<url-pattern>/admin.jsp</url-pattern> | |
</filter-mapping> | |
</web-app> |
Thanks for the code. To avoid any timing attacks, you should compare username and password with MessageDigest.isEqual() which is good enough since Java 6u17.
Good job!
But Eclipse does not accept the line
throw new Error("Couldn't retrieve authentication", e);
with reason "No exception of type Error can be thrown; an exception type must be a subclass of Throwable"
Recently I have a job to add a simple filter to internal Restful API, things get very simple with your excellent work. Thank Author a lot! and, thank @storysj for his notification.
Awesome @neolitec,
This is the exactly filter I was looking for. Thanks a load and you save my week. cheers !
if (!username.equals(_username) || !password.equals(_password)) { unauthorized(response, "Bad credentials"); } else { filterChain.doFilter(servletRequest, servletResponse); }
It does however not set up a login context (request.login(name, pass)
). This is a (somewhat limited) hook into the server security. See also Oracle tutorial on that matter.
want to create two groups user and admin but kill function will work only for admin any one help me for this
the line with
filterChain.doFilter(servletRequest, servletResponse);
needs to be in anelse
block, otherwise requests with bad credentials will still pass through the filter.