检查HTTP 的 Digest 认证. since http1.1
代码如下所示:(此代码还不完善, RFC2617算法未实现).
<%@ page pageEncoding="UTF-8" contentType="text/html;charset=UTF-8" %>
<%@ page import="sun.misc.BASE64Decoder" %>
<%@ page import="java.io.IOException" %>
<%@ page import="java.util.UUID" %>
<%@ page import="java.util.HashMap" %>
<%@ page import="java.util.Map" %>
<%!
// 检查HTTP 的 Basic认证. since http1.0
public static boolean checkAuth(HttpServletRequest request, String _username, String _password){
boolean authOK = false;
// 认证后每次HTTP请求都会附带上 Authorization 头信息
String Authorization = request.getHeader("Authorization");
if(null == Authorization || Authorization.trim().isEmpty()){
// 需要认证
return authOK;
}
// 示例数据, 没有换行,有逗号,也有空格
// Digest username="admin", realm="DIGEST tiemao",
// nonce="227c89449fd644a3b9df12e7cb8b0e33", uri="/digest.jsp",
// algorithm=MD5, response="a8bc07c1d6dc38802ce538247e22f773",
// qop=auth, nc=00000001, cnonce="f337ac5d88670ef5"
String[] digestArray = Authorization.split("\\s+");
if(null == digestArray || digestArray.length < 2){
return authOK;
}
//
Map<String,String> authMap = new HashMap<String,String>();
for(int i = 0; i < digestArray.length; i++){
String paraAndValue = digestArray[i];
//
String[] pvArray = paraAndValue.split("=");
if(null == pvArray || 2 != pvArray.length){
continue; // 不处理0
}
String key = pvArray[0];
String value = pvArray[1];
//
if(null==key || null == value){
}
//
value = value.replace("'","");
value = value.replace(",","");
value = value.replace("\"","");
value = value.trim();
authMap.put(key, value);
}
//
String username = authMap.get("username");
String nonce = authMap.get("nonce");
String response = authMap.get("response");
// 这里应该有个 RFC2617 算法,与客户端一致,即计算用户密码
if(_username.equalsIgnoreCase(username) && checkAuth_RFC2617(_username, _password, response)){
authOK = true;// 认证成功,
}
//
return authOK;
}
// RFC2617 运算,这算法比较复杂,暂时未实现
// 参考地址: http://www.faqs.org/rfcs/rfc2617.html
public static boolean checkAuth_RFC2617(String _username,String _password, String response){
boolean authOK = false;
if(null != _username || null !=_password || response.equalsIgnoreCase(response)){
authOK = true;// 认证成功,
}
return true;
}
// 不依赖 this 状态的方法,其实都应该设置为 static
public static void requireDigestAuth(HttpServletResponse response, String nonce){
// 发送状态码 401, 不能使用 sendError,坑
response.setStatus(401,"Authentication Required");
//
String authHeader = "Digest realm=\"DIGEST tiemao\"";
authHeader += ",nonce=\""+ nonce +"\"";
authHeader += ",algorithm=MD5";
authHeader += ",qop=\""+ "auth" +"\"";
// 发送要求输入认证信息,则浏览器会弹出输入框
response.addHeader("WWW-Authenticate", authHeader);
return;
}
%>
<%
//
String Authorization = request.getHeader("Authorization");
//
String _username = "admin";
String pwd = "11111111";
boolean authOK = checkAuth(request, _username, pwd);
//
if (!authOK) {
//
String nonce = UUID.randomUUID().toString().replace("-","");
// 如果认证失败,则要求认证
requireDigestAuth(response, nonce);
return;
}
%>
<html>
<head>
<title>DIGEST认证示例</title>
</head>
<body>
R U OK? <%=_username %>. Your Password is <%="********"%>
</body>
</html>
代码如上所述,.