提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
记录摘要认证的实现,用于海康录像机获取抓拍图片。
一、代码
1.引入包
代码如下(示例):
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.io.IOUtils;
import cn.hutool.http.Method;
2.代码
代码如下:
String m_sUsername = "用户名";// 用户名
String m_sPassword = "密码";// 密码
//通过url从设备获取图片
private byte[] getStreamFromUrl(String picUrl,String uri) {
URL url = null;
byte[] data = null;
InputStream inStream = null;
try {
// 第一次请求
url = new URL(picUrl);
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
//超时响应时间为3秒
conn.setConnectTimeout(3 * 1000);
if(conn.getResponseCode()==401) {
System.out.println("返回401,设备已开启摘要认证");
// 摘要认证
Map<String, List<String>> headerFields = conn.getHeaderFields();
List<String> au = headerFields.get("WWW-Authenticate");
conn.disconnect();
String auth = au.get(0);
HashMap<String, String> authFields = splitAuthFields(auth.substring(7));
String A1 = null;
String A2 = null;
String response = null;
MessageDigest md5 = null;
// 第一次摘要认证请求
String nc = "00000001";
// 可以修改
String cnonce = "0123abcd";
try {
md5 = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
// 拼接字符串A1
try {
md5.reset();
String A1Str = m_sUsername+":"+authFields.get("realm")+":"+m_sPassword;
md5.update(A1Str.getBytes());
System.out.println("A1Str:"+A1Str);
A1 = bytesToHexString(md5.digest());
} catch (Exception e) {
e.printStackTrace();
}
// 拼接字符串A2
try {
md5.reset();
String A2Str = Method.GET.toString()+":"+ uri;
md5.update(A2Str.getBytes());
A2 = bytesToHexString(md5.digest());
} catch (Exception e) {
e.printStackTrace();
}
// 拼接最终字符串
try {
md5.reset();
StringBuilder s0 = new StringBuilder(A1);
s0.append(":").append(authFields.get("nonce")).append(":");
s0.append(nc).append(":");
s0.append(cnonce).append(":");
s0.append(authFields.get("qop")).append(":");
s0.append(A2);
String reStr = s0.toString();
md5.update(reStr.getBytes());
response = bytesToHexString(md5.digest());
} catch (Exception e) {
e.printStackTrace();
}
// 拼接 Authorization Header
StringBuilder sb = new StringBuilder();
sb.append("Digest ");
sb.append("username").append("=\"").append(m_sUsername).append("\",");
sb.append("realm").append("=\"").append(authFields.get("realm")).append("\",");
sb.append("qop").append("=\"").append(authFields.get("qop")).append("\",");
sb.append("nonce").append("=\"").append(authFields.get("nonce")).append("\",");
sb.append("uri").append("=\"").append(uri).append("\",");
sb.append("algorithm").append("=\"").append("MD5").append("\",");
sb.append("nc").append("=\"").append(nc).append("\",");
sb.append("cnonce").append("=\"").append(cnonce).append("\",");
sb.append("response").append("=\"").append(response).append("\"");
// 再次请求
HttpURLConnection conn1 = null;
try {
URL url1 = new URL(picUrl);
conn1 = (HttpURLConnection)url1.openConnection();
conn1.setRequestProperty("Authorization", sb.toString());
//超时响应时间为3秒
conn1.setConnectTimeout(3 * 1000);
conn1.connect();
// 获取输入流
inStream = conn1.getInputStream();
data = readInputStream(inStream);
//关闭输入流
inStream.close();
// 关闭连接
conn1.disconnect();
} catch (Exception e) {
System.out.println(e);
System.out.println(conn1.getResponseCode());
InputStream errorStream = conn1.getErrorStream();
System.out.println(IOUtils.toString(errorStream, "UTF-8"));
}
}else if(conn.getResponseCode()==200){
System.out.println("设备未开启摘要认证");
inStream = conn.getInputStream();
data = readInputStream(inStream);
//关闭输入流
inStream.close();
// 关闭连接
conn.disconnect();
}
} catch (Exception e) {
e.printStackTrace();
}
return data;
}
// 读取输入流,转为byte数组
private static byte[] readInputStream(InputStream inStream) throws Exception {
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
byte[] buffer = new byte[4096];
//每次读取的字符串长度,如果为-1,代表全部读取完毕
int len = 0;
//使用一个输入流从buffer里把数据读取出来
while ((len = inStream.read(buffer)) != -1) {
//用输出流往buffer里写入数据,中间参数代表从哪个位置开始读,len代表读取的长度
outStream.write(buffer, 0, len);
}
byte[] byteArray = outStream.toByteArray();
outStream.close();
//把outStream里的数据写入内存
return byteArray;
}
private static final String HEX_LOOKUP = "0123456789abcdef";
private static String bytesToHexString(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < bytes.length; i++) {
sb.append(HEX_LOOKUP.charAt((bytes[i] & 0xF0) >> 4));
sb.append(HEX_LOOKUP.charAt((bytes[i] & 0x0F) >> 0));
}
return sb.toString();
}
// 将AuthFields(字符串)中的数据转化为Map
private static HashMap<String, String> splitAuthFields(String raw) {
final HashMap<String, String> fields = new HashMap<String, String>();
String[] str = raw.trim().split(",");
for (String s : str) {
String[] item = s.trim().split("=");
fields.put(item[0], item[1].replaceAll("\"", ""));
}
return fields;
}
---
1518

被折叠的 条评论
为什么被折叠?



