Java Web 实现 HTTP Basic 认证

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。

可以与普通 Web 登录叠加使用,指定相同的过滤器路径,这样安全性更高。

<!-- 指定一种登录验证方式。当前为 HTTP Basic Auth -->
<filter>
	<filter-name>HttpBasicAuthFilter</filter-name>
	<filter-class>com.ajaxjs.web.HttpBasicAuthFilter</filter-class>

	<init-param>
		<param-name>adminPassword</param-name>
		<param-value>a123123a</param-value> <!-- adminPassword 指定登录密码;如不指定,则默认为 123123 -->
	</init-param>
</filter>
<filter-mapping>
	<filter-name>HttpBasicAuthFilter</filter-name>
	<url-pattern>/admin/*</url-pattern><!-- 可指定路径,应使用 * 泛指该目录下所有路径 -->
</filter-mapping>

 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sp42a

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值