您的位置:首页 > 理论基础 > 计算机网络

检查HTTP 的 Digest 认证代码示例-JSP

2015-06-18 21:50 543 查看
检查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>
代码如上所述,.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: