Basic 认证是一种较为简单的 HTTP 认证方式,客户端通过明文(Base64 编码格式)传输用户名和密码到服务端进行认证,通常需要配合 HTTPS 来保证信息传输的安全。界面如下。
下面基于 Servlet 标准 Filter 实现一个 HTTP Basic 登录机制,可以用作测试时的临时发布用。部分函数利用了 AJAXJS 库。
package com.ajaxjs.web;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.ajaxjs.util.Encode;
import com.ajaxjs.util.CommonUtil;
import com.ajaxjs.util.logger.LogHelper;
/**
* 简单的 HTTP Basic 登录
*
* @author sp42 frank@ajaxjs.com
*/
public class HttpBasicAuthFilter implements Filter {
private static final LogHelper LOGGER = LogHelper.getLog(HttpBasicAuthFilter.class);
/**
* 登录名,写死只有一个用户 admin
*/
private static final String userid = "admin";
/**
* 登录密码
*/
private static String pwd = "123123";
/**
* 报告是否启动的状态,让外界知晓
*/
public static boolean isEnadble = false;
@Override
public void init(FilterConfig config) throws ServletException {
LOGGER.info("启动 HTTP BasicAuth 后台管理");
if (config.getInitParameter("adminPassword") != null)
pwd = config.getInitParameter("adminPassword");// 读取 web.xml 配置里的密码
isEnadble = true;
}
@Override
@SuppressWarnings("deprecation")
public void doFilter(ServletRequest _request, ServletResponse _response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) _request;
HttpServletResponse response = (HttpServletResponse) _response;
if (!checkAuth(request)) {
String msg = "\"Please input your account\""; // 如果认证失败,则要求认证 ,不能输入中文
response.setCharacterEncoding("utf-8");
response.setStatus(401, "Authentication Required");// 发送状态码 401, 不能使用 sendError,坑
response.setHeader("WWW-Authenticate", "Basic realm=" + msg);// 发送要求输入认证信息,则浏览器会弹出输入框
response.setCharacterEncoding("utf-8");
response.getWriter().append("<meta charset=\"utf-8\" />Please login! 请登录系统!");
LOGGER.info("HTTP BasicAuth 登录失败!");
} else {
// request.setAttribute("userName", userid);
chain.doFilter(request, response);
}
}
@Override
public void destroy() {
}
/**
* 检查是否合法登录
*
* @param request 请求对象
* @return 是否合法登录
*/
private static boolean checkAuth(HttpServletRequest request) {
return checkAuth(request.getHeader("Authorization"), userid, pwd);
}
/**
* 是否不合法的数组
*
* @param arr
* @return 是否不合法的数组
*/
private static boolean isBadArray(String[] arr) {
return arr == null || arr.length != 2;
}
/**
* 检查是否合法登录
*
* @param authorization 认证后每次HTTP请求都会附带上 Authorization 头信息
* @param username 用户名
* @param password 密码
* @return true = 认证成功/ false = 需要认证
*/
private static boolean checkAuth(String authorization, String username, String password) {
if (CommonUtil.isEmptyString(authorization))
return false;
String[] basicArray = authorization.split("\\s+");
if (isBadArray(basicArray))
return false;
String idpass = Encode.base64Decode(basicArray[1]);
if (CommonUtil.isEmptyString(idpass))
return false;
String[] idpassArray = idpass.split(":");
if (isBadArray(idpassArray))
return false;
return username.equalsIgnoreCase(idpassArray[0]) && password.equalsIgnoreCase(idpassArray[1]);
}
}
HTTP Basic 安全性还是太弱,所以可以考虑加强版: 摘要认证——HTTP Digest。