本文主要是介绍HTTP Digest接入方式鉴权认证流程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
HTTP Digest接入方式鉴权认证流程
一、摘要认证原理
摘要认证与基础认证的工作原理很相似,用户先发出一个没有认证证书的请求,Web服务器回复一个带有WWW-Authenticate头的响应,指明访问所请求的资源需要证书。但是和基础认证发送以Base 64编码的用户名和密码不同,在摘要认证中服务器让客户选一个随机数(称作”nonce“),然后浏览器使用一个单向的加密函数生成一个消息摘要(message digest),该摘要是关于用户名、密码、给定的nonce值、HTTP方法,以及所请求的URL。
二、摘要认证流程
客户端首次向服务器发送HTTP请求,服务器返回401(未授权)响应进行挑战。401消息的头里带有WWW-Authenticate消息头,其中包含挑战摘要的随机参数nonce。客户端收到401后,将用户名密码和挑战信息用MD5加密形成认证鉴权头,重新发送给服务器,服务器对认证鉴权头进行验证,如果认证成功则返回200 OK,并在响应的消息中返回下次认证的随机数nextnonce,客户端下次请求时,根据nextnonce生成鉴权头进行HTTP请求。
服务器的401未授权挑战WWW-Authenticate消息头语法:
challenge =“Digest” digest-challenge
digest-challenge=1#( realm | [ domain ] | nonce |
[ opaque ] |[ stale ] | [ algorithm ] |
[ qop-options ] | [auth-param] )
domain =“domain" “=” <“> URI ( 1*SP URI ) <”>
URI =absoluteURI | abs_path
nonce =“nonce" “=” nonce-value
nonce-value =quoted-string
opaque =“opaque" “=” quoted-string
stale =“stale" “=” ( “true” | “false” )
algorithm =“algorithm" “=” ( “MD5” | “MD5-sess” |
token )
qop-options =“qop" “=” <“> 1#qop-value <”>
qop-value =“auth" | “auth-int” | token
参数说明:
- realm:用户域。由服务端告知
- qop:保护质量。auth:鉴权,不对消息体做完整性验证。auth-int:鉴权并需要对消息体做摘要,保证消息完整性。
- nonce:摘要质询参数。401响应中唯一生成的字符串数据。采用十六进制数据。
- opaque:会话标识。由服务器指定,客户端须在请求二中返回该数据。采用十六进制数据。
客户端的挑战响应消息Authorization头参数一下为String类型:
- username:用户名。必填。
- realm:用户域。由服务方告知
- nonce:摘要质询参数。返回请求一响应中的参数nonce
- uri:访问路径。请求的URI
- qop:保护质量。auth:鉴权,不对消息体做完整性验证。auth-int:鉴权并需要对消息体做摘要,保证消息完整性。注册过程使用auth
- nc:nonce计数参数。客户端请求的十六进制计数,以00000001开始,每次请求加1,目的是防止重放攻击。
- cnonce:客户端nonce值。客户端用来鉴定服务器的摘要质询参数
- response:响应值。对请求一中401响应的参数采用MD5算法做摘要计算的结果
- opaque:会话标识。返回服务器原值
response参数的算法:
response=<“> < KD ( H(A1), unq(nonce-value) “:” nc-value “:”
unq(cnonce-value) “:” unq(qop-value) “:” H(A2) ) <”>
A1=unq(username-value) “:” unq(realm-value) “:” passwd
如果qop等于auth,A2=Method “:” digest-uri-value 如果qop等于auth-int,A2=Method
“:” digest-uri-value “:” H(entity-body) 其中: H(data)=MD5(data)。
KD(secret, data)=H(concat(secret, “:”, data))。 unq(X)代表去掉X前后的引号。
Method=GET或者POST。 entity-body代表HTTP请求的消息体。 passwd=key。
三、代码实现HTTP Digest接入方式鉴权认证
以下是初次接触摘要认证时的简要请求方法。
摘要认证过程也可用Springorg.springframework.web.client.RestTemplate实现,修改配置类中的RestTemplate生成方法。具体方法自行百度。
public static String sendPostRequest(String username,String password,String uri, String jsonParams){CloseableHttpClient httpClient = null;String result =null;String requestUrl=url+uri;try {CredentialsProvider credsProvider = new BasicCredentialsProvider();httpClient = HttpClients.custom().setDefaultCredentialsProvider(credsProvider).build();//第一次请求HttpPost post = new HttpPost(requestUrl);// 构造消息头post.addHeader("Content-type","application/json; charset=utf-8");post.setHeader("Accept", "application/json");HttpResponse firstResponse = httpClient.execute(post);org.apache.http.HttpEntity firstEntity = null;firstEntity = firstResponse.getEntity();result = EntityUtils.toString(firstEntity, "UTF-8");Map<String,String> map =new HashMap<String,String>();StringEntity stringEntity = new StringEntity(jsonParams);//解析头部Header[] h=firstResponse.getHeaders("WWW-Authenticate");StringBuffer auth=new StringBuffer(h[0].toString());String realm=auth.substring(auth.indexOf("realm=")+6,auth.indexOf("qop=")-1);String qop=auth.substring(auth.indexOf("qop=")+4,auth.indexOf("nonce=")-1);String nonce=auth.substring(auth.indexOf("nonce=")+6,auth.indexOf("opaque=")-1);String opaque=auth.substring(auth.indexOf("opaque=")+7);String cnonce="00000001";String nc="00000001";String algorithm="MD5";String responseString;String params1=username+":"+realm+":"+password;String params2="POST:"+uri;String params3= SecureUtil.md5(params1)+":"+nonce+":"+nc+":"+cnonce+":"+qop+":"+SecureUtil.md5(params2);responseString=SecureUtil.md5(params3);StringBuilder sb=new StringBuilder();String Authorization ="Digest username=" + username +",realm="+ realm +",nonce=" + nonce +",uri=" + uri +",response=" + responseString + ",cnonce=" +cnonce + ",qop=" +qop+ ",nc="+nc;//第二次请求// 构造消息头post.setHeader("Authorization",Authorization);post.setEntity(stringEntity);HttpResponse secondResponse = httpClient.execute(post);org.apache.http.HttpEntity secondEntity = null;secondEntity = secondResponse.getEntity();result = EntityUtils.toString(secondEntity, "UTF-8");httpClient.close();} catch (Exception e) {log.error(e.getMessage());} finally {if (httpClient != null) {try {httpClient.close();} catch (IOException e) {log.error(e.getMessage());}}}return result;}
这篇关于HTTP Digest接入方式鉴权认证流程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!