接口为什么加微信 noncestr

微信JS接口 - 为程序员服务
微信JS接口
17785 阅读
微信JS接口 分享到朋友圈 分享给朋友 分享到QQ 拍照或从手机相册中选图 识别音频并返回识别结果 使用微信内置地图查看位置来源:&
1.引入JS文件
在需要调用JS接口的页面引入如下JS文件,(支持https):
备注:支持使用 AMD/CMD 标准模块加载方法加载
2.注入配置config接口
所有需要使用JSSDK的页面必须先注入配置信息,否则将无法调用(同一个url仅需调用一次,对于变化url的SPA的web app可在每次url变化时进行调用)。
wx.config({
debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: '', // 必填,公众号的唯一标识
timestamp: , // 必填,生成签名的时间戳
nonceStr: '', // 必填,生成签名的随机串
signature: '',// 必填,签名,见附录1
jsApiList: [] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
3.验证通过ready接口
wx.ready(function(){
// config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
4.验证失败error接口
wx.error(function(res){
// config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
接口调用说明
所有接口通过wx对象(也可使用jWeixin对象)来调用,参数是一个对象,除了每个接口本身需要传的参数之外,还有以下通用参数:
success:接口调用成功时执行的回调函数。
fail:接口调用失败时执行的回调函数。
complete:接口调用完成时执行的回调函数,无论成功或失败都会执行。
cancel:用户点击取消时的回调函数,仅部分有用户取消操作的api才会用到。
trigger: 监听Menu中的按钮点击时触发的方法,该方法仅支持Menu中的相关接口。
以上几个函数都带有一个参数,类型为对象,其中除了每个接口本身返回的数据之外,还有一个通用属性errMsg,其值格式如下:
调用成功时:”xxx:ok” ,其中xxx为调用的接口名
用户取消时:”xxx:cancel”,其中xxx为调用的接口名
调用失败时:其值为具体错误信息
判断当前客户端版本是否支持指定JS接口
wx.checkJsApi({
jsApiList: ['chooseImage'] // 需要检测的JS接口列表,所有JS接口列表见附录2,
success: function(res) {
// 以键值对的形式返回,可用的api值true,不可用为false
// 如:{"checkResult":{"chooseImage":true},"errMsg":"checkJsApi:ok"}
获取&分享到朋友圈&按钮点击状态及自定义分享内容接口
wx.onMenuShareTimeline({
title: '', // 分享标题
link: '', // 分享链接
imgUrl: '', // 分享图标
success: function () {
// 用户确认分享后执行的回调函数
cancel: function () {
// 用户取消分享后执行的回调函数
获取&分享给朋友&按钮点击状态及自定义分享内容接口
wx.onMenuShareAppMessage({
title: '', // 分享标题
desc: '', // 分享描述
link: '', // 分享链接
imgUrl: '', // 分享图标
type: '', // 分享类型,music、video或link,不填默认为link
dataUrl: '', // 如果type是music或video,则要提供数据链接,默认为空
success: function () {
// 用户确认分享后执行的回调函数
cancel: function () {
// 用户取消分享后执行的回调函数
获取&分享到QQ&按钮点击状态及自定义分享内容接口
wx.onMenuShareQQ({
title: '', // 分享标题
desc: '', // 分享描述
link: '', // 分享链接
imgUrl: '' // 分享图标
success: function () {
// 用户确认分享后执行的回调函数
cancel: function () {
// 用户取消分享后执行的回调函数
获取&分享到腾讯微博&按钮点击状态及自定义分享内容接口
wx.onMenuShareWeibo({
title: '', // 分享标题
desc: '', // 分享描述
link: '', // 分享链接
imgUrl: '' // 分享图标
success: function () {
// 用户确认分享后执行的回调函数
cancel: function () {
// 用户取消分享后执行的回调函数
拍照或从手机相册中选图接口
wx.chooseImage({
success: function (res) {
var localIds = res.localI // 返回选定照片的本地ID列表,localId可以作为img标签的src属性显示图片
预览图片接口
wx.previewImage({
current: '', // 当前显示的图片链接
urls: [] // 需要预览的图片链接列表
上传图片接口
wx.uploadImage({
localId: '', // 需要上传的图片的本地ID,由chooseImage接口获得
isShowProgressTips: 1// 默认为1,显示进度提示
success: function (res) {
var serverId = res.serverId; // 返回图片的服务器端ID
备注:可用微信下载多媒体文件接口下载上传的图片,此处获得的 serverId 即 media_id,参考文档
下载图片接口
wx.downloadImage({
serverId: '', // 需要下载的图片的服务器端ID,由uploadImage接口获得
isShowProgressTips: 1// 默认为1,显示进度提示
success: function (res) {
var localId = res.localId; // 返回图片下载后的本地ID
开始录音接口
wx.startRecord();
停止录音接口
wx.stopRecord({
success: function (res) {
var localId = res.localId;
监听录音自动停止接口
wx.onVoiceRecordEnd({
// 录音时间超过一分钟没有停止的时候会执行 complete 回调
complete: function (res) {
var localId = res.localId;
播放语音接口
wx.playVoice({
localId: '' // 需要播放的音频的本地ID,由stopRecord接口获得
暂停播放接口
wx.pauseVoice({
localId: '' // 需要暂停的音频的本地ID,由stopRecord接口获得
停止播放接口
wx.stopVoice({
localId: '' // 需要停止的音频的本地ID,由stopRecord接口获得
监听语音播放完毕接口
wx.onVoicePlayEnd({
serverId: '', // 需要下载的音频的服务器端ID,由uploadVoice接口获得
success: function (res) {
var localId = res.localId; // 返回音频的本地ID
上传语音接口
wx.uploadVoice({
localId: '', // 需要上传的音频的本地ID,由stopRecord接口获得
isShowProgressTips: 1// 默认为1,显示进度提示
success: function (res) {
var serverId = res.serverId; // 返回音频的服务器端ID
备注:可用微信下载多媒体文件接口下载上传的语音,此处获得的 serverId 即 media_id,参考文档
下载语音接口
wx.downloadVoice({
serverId: '', // 需要下载的音频的服务器端ID,由uploadVoice接口获得
isShowProgressTips: 1// 默认为1,显示进度提示
success: function (res) {
var localId = res.localId; // 返回音频的本地ID
识别音频并返回识别结果接口
wx.translateVoice({
localId: '', // 需要识别的音频的本地Id,由录音相关接口获得
isShowProgressTips: 1, // 默认为1,显示进度提示
success: function (res) {
alert(res.translateResult); // 语音识别的结果
获取网络状态接口
wx.getNetworkType({
success: function (res) {
var networkType = res.networkT // 返回网络类型2g,3g,4g,wifi
使用微信内置地图查看位置接口
wx.openLocation({
latitude: 0, // 纬度,浮点数,范围为90 ~ -90
longitude: 0, // 经度,浮点数,范围为180 ~ -180。
name: '', // 位置名
address: '', // 地址详情说明
scale: 1, // 地图缩放级别,整形值,范围从1~28。默认为最大
infoUrl: '' // 在查看位置界面底部显示的超链接,可点击跳转
获取地理位置接口
wx.getLocation({
timestamp: 0, // 位置签名时间戳,仅当需要兼容6.0.2版本之前时提供
nonceStr: '', // 位置签名随机串,仅当需要兼容6.0.2版本之前时提供
addrSign: '', // 位置签名,仅当需要兼容6.0.2版本之前时提供,详见附录4
success: function (res) {
var longitude = res. // 纬度,浮点数,范围为90 ~ -90
var latitude = res. // 经度,浮点数,范围为180 ~ -180。
var speed = res. // 速度,以米/每秒计
var accuracy = res. // 位置精度
隐藏右上角菜单接口
wx.hideOptionMenu();
显示右上角菜单接口
wx.showOptionMenu();
关闭当前网页窗口接口
wx.closeWindow();
批量隐藏功能按钮接口
wx.hideMenuItems({
menuList: [] // 要隐藏的菜单项,所有menu项见附录3
批量显示功能按钮接口
wx.showMenuItems({
menuList: [] // 要显示的菜单项,所有menu项见附录3
隐藏所有非基础按钮接口
wx.hideAllNonBaseMenuItem();
显示所有功能按钮接口
wx.showAllNonBaseMenuItem();
微信扫一扫
调起微信扫一扫接口
wx.scanQRCode({
desc: 'scanQRCode desc',
needResult: 0, // 默认为0,扫描结果由微信处理,1则直接返回扫描结果,
scanType: ["qrCode","barCode"], // 可以指定扫二维码还是一维码,默认二者都有
success: function () {
var result = res.resultS // 当needResult 为 1 时,扫码返回的结果
编辑收货地址接口
wx.editAddress(
timestamp: 0, // 位置签名时间戳,仅当需要兼容6.0.2版本之前时提供
nonceStr: '', // 位置签名随机串,仅当需要兼容6.0.2版本之前时提供
addrSign: '', // 位置签名,仅当需要兼容6.0.2版本之前时提供,详见附录4
success: function (res) {
var userName = res.userN // 收货人姓名
var telNumber = res.telN // 收货人电话
var postalCode = res.postalC // 邮编
var provinceName = res.provinceN // 国标收货地址第一级地址
var cityName = res.cityN // 国标收货地址第二级地址
var countryName = res.countryN // 国标收货地址第三级地址
var address = res. // 详细收货地址信息
var nationalCode = res.nationalC // 收货地址国家码
获取最近的收货地址接口
wx.getLatestAddress({
timestamp: 0, // 位置签名时间戳,仅当需要兼容6.0.2版本之前时提供
nonceStr: '', // 位置签名随机串,仅当需要兼容6.0.2版本之前时提供
addrSign: '', // 位置签名,仅当需要兼容6.0.2版本之前时提供,详见附录4
success: function (res) {
var userName = res.userN // 收货人姓名
var telNumber = res.telN // 收货人电话
var postalCode = res.postalC // 邮编
var provinceName = res.provinceN // 国标收货地址第一级地址
var cityName = res.cityN // 国标收货地址第二级地址
var countryName = res.countryN // 国标收货地址第三级地址
var address = res. // 详细收货地址信息
var nationalCode = res.nationalC // 收货地址国家码
跳转微信商品页接口
wx.openProductSpecificView({
productId: '', // 商品id
viewType: '' // 0.默认值,普通商品详情页1.扫一扫商品详情页2.小店商品详情页
调起适用于门店的卡券列表并获取用户选择列表
wx.chooseCard({
shopId: '', // 门店Id
cardType: '', // 卡券类型
cardId: '', // 卡券Id
timeStamp: 0, // 卡券签名时间戳
nonceStr: '', // 卡券签名随机串
cardSign: '', // 卡券签名,详见附录6
success: function (res) {
var cardList= res.cardL // 用户选中的卡券列表信息
批量添加卡券接口
wx.addCard({
cardList: [{
cardId: '',
cardExt: ''
}], // 需要添加的卡券列表
success: function (res) {
var cardList = res.cardL // 添加的卡券列表信息
查看微信卡包中的卡券接口
wx.openCard({
cardList: [{
cardId: '',
}]// 需要打开的卡券列表
发起一个微信支付请求
wx.chooseWXPay({
timestamp: 0, // 支付签名时间戳
noncestr: '', // 支付签名随机串
package: '', // 订单详情扩展字符串,详见附录5
paySign: '', // 支付签名,详见附录5
附录1-JSSDK使用权限签名算法
jsapi_ticket
生成签名之前必须先了解一下jsapi_ticket,jsapi_ticket是公众号用于调用微信JS接口的临时票据。正常情况下,jsapi_ticket的有效期为7200秒,通过access_token来获取。由于获取jsapi_ticket的api调用次数非常有限,频繁刷新jsapi_ticket会导致api调用受限,影响自身业务,开发者必须在自己的服务全局缓存jsapi_ticket&。
参考以下文档获取access_token(有效期7200秒,开发者必须在自己的服务全局缓存access_token):
用第一步拿到的access_token 采用http GET方式请求获得jsapi_ticket(有效期7200秒,开发者必须在自己的服务全局缓存jsapi_ticket):
成功返回如下JSON:
"errcode":0,
"errmsg":"ok",
"ticket":"bxLdikRXVbTPdHSM05e5u5sUoXNKd8-41ZO3MhKoyN5OfkWITDGgnr2fwJ0m9E8NYzWKVZvdVtaUgWvsdshFKA",
"expires_in":7200
获得jsapi_ticket之后,就可以生成JSSDK权限验证的签名了。
签名生成规则如下:参与签名的字段包括noncestr(随机字符串), 有效的jsapi_ticket, timestamp(时间戳), url(当前网页的URL,不包含#及其后面部分) 。对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2&)拼接成字符串string1。这里需要注意的是所有参数名均为小写字符。对string1作sha1加密,字段名和字段值都采用原始值,不进行URL 转义。
即signature=sha1(string1)。 示例:
noncestr=Wm3WZYTPz0wzccnW
jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg
timestamp=
步骤1. 对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2&)拼接成字符串string1:
jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg&noncestr=Wm3WZYTPz0wzccnW&timestamp=&url=http://mp.
步骤2. 对string1进行sha1签名,得到signature:
f4d90daf4b3bca175ba34c443a7b
签名用的noncestr和timestamp必须与wx.config中的nonceStr和timestamp相同。
签名用的url必须是调用JS接口页面的完整URL。
出于安全考虑,开发者必须在服务器端实现签名的逻辑。
附录2-所有JS接口列表
onMenuShareTimeline
onMenuShareAppMessage
onMenuShareQQ
onMenuShareWeibo
startRecord
stopRecord
onVoiceRecordEnd
pauseVoice
onVoicePlayEnd
uploadVoice
downloadVoice
chooseImage
previewImage
uploadImage
downloadImage
translateVoice
getNetworkType
openLocation
getLocation
hideOptionMenu
showOptionMenu
hideMenuItems
showMenuItems
hideAllNonBaseMenuItem
showAllNonBaseMenuItem
closeWindow
scanQRCode
chooseWXPay
getLatestAddress
editAddress
openProductSpecificView
chooseCard
附录3-所有按钮列表
举报: “menuItem:exposeArticle”
调整字体: “menuItem:setFont”
日间模式: “menuItem:dayMode”
夜间模式: “menuItem:nightMode”
刷新: “menuItem:refresh”
查看公众号(已添加): “menuItem:profile”
查看公众号(未添加): “menuItem:addContact”
发送给朋友: “menuItem:share:appMessage”
分享到朋友圈: “menuItem:share:timeline”
分享到QQ: “menuItem:share:qq”
分享到Weibo: “menuItem:share:weiboApp”
收藏: “menuItem:favorite”
分享到FB: “menuItem:share:facebook”
调试: “menuItem:jsDebug”
编辑标签: “menuItem:editTag”
删除: “menuItem:delete”
复制链接: “menuItem:copyUrl”
原网页: “menuItem:originPage”
阅读模式: “menuItem:readMode”
在QQ浏览器中打开: “menuItem:openWithQQBrowser”
在Safari中打开: “menuItem:openWithSafari”
邮件: “menuItem:share:email”
一些特殊公众号: “menuItem:share:brand”
附录4-位置与地址签名生成算法
addrSign的生成规则与JSSDK权限验证的签名生成规则相同(参考附录1),只是参与签名参数有所不同。参与addrSign的签名参数有:appId、url(当前网页url)、timestamp、noncestr、accesstoken(用户授权凭证,请参照oauth2.0 协议获取)。
附录5-支付扩展字段及签名生成算法
订单详情(package)扩展字符串定义
在商户调起JS API 时,商户需要此时确定该笔订单详情,并将该订单详情通过一定的方式进行组合放入package。JS API 调用后,微信将通过package 的内容生成预支付单。下 面将定义package 的所需字段列表以及签名方法。 接口需要注意:所有传入参数都是字符串类型!
附录6-卡券扩展字段及签名生成算法
附录7-常见错误解决方法
附录8-DEMO页面和示例代码
又一个码农站点
原文地址:, 感谢原作者分享。
您可能感兴趣的代码博客分类:
&&&&&& 摘要访问认证是一种协议规定的Web服务器用来同网页浏览器进行认证信息协商的方法。它在密码发出前,先对其应用哈希函数,这相对于HTTP基本认证发送明文而言,更安全。从技术上讲,摘要认证是使用随机数来阻止进行密码分析的MD5加密哈希函数应用。它使用HTTP协议。
一、摘要认证基本流程:
1.客户端请求 (无认证)
Html代码 &
GET&/dir/index.html&HTTP/1.0&&Host:&localhost&&
2.服务器响应
服务端返回401未验证的状态,并且返回WWW-Authenticate信息,包含了验证方式Digest,realm,qop,nonce,opaque的值。其中:
Digest:认证方式;
realm:领域,领域参数是强制的,在所有的盘问中都必须有,它的目的是鉴别SIP消息中的机密,在SIP实际应用中,它通常设置为SIP代理服务器所负责的域名;
qop:保护的质量,这个参数规定服务器支持哪种保护方案,客户端可以从列表中选择一个。值 “auth”表示只进行身份查验, “auth-int”表示进行查验外,还有一些完整性保护。需要看更详细的描述,请参阅RFC2617;
nonce:为一串随机值,在下面的请求中会一直使用到,当过了存活期后服务端将刷新生成一个新的nonce值;
opaque:一个不透明的(不让外人知道其意义)数据字符串,在盘问中发送给用户。
Html代码 &
HTTP/1.0&401&Unauthorized&&Server:&HTTPd/0.9&&Date:&Sun,&10&Apr&:47&GMT&&WWW-Authenticate:&Digest&realm=&&,&&&&&&&&&&&&&&&&&&&&&&&&&&qop=&auth,auth-int&,&&&&&&&&&&&&&&&&&&&&&&&&&&nonce=&dcd98be8b11d0f600bfb0c093&,&&&&&&&&&&&&&&&&&&&&&&&&&&opaque=&5ccc069c403ebaf9fe41&&&
3.客户端请求& (用户名 &Mufasa&, 密码 &Circle Of Life&)
客户端接受到请求返回后,进行HASH运算,返回Authorization参数
其中:realm,nonce,qop由服务器产生;
uri:客户端想要访问的URI;
nc:“现时”计数器,这是一个16进制的数值,即客户端发送出请求的数量(包括当前这个请求),这些请求都使用了当前请求中这个“现时”值。例如,对一个给定的“现时”值,在响应的第一个请求中,客户端将发送“nc=”。这个指示值的目的,是让服务器保持这个计数器的一个副本,以便检测重复的请求。如果这个相同的值看到了两次,则这个请求是重复的;
cnonce:这是一个不透明的字符串值,由客户端提供,并且客户端和服务器都会使用,以避免用明文文本。这使得双方都可以查验对方的身份,并对消息的完整性提供一些保护;
response:这是由用户代理软件计算出的一个字符串,以证明用户知道口令。
Html代码 &
response计算过程:&&HA1=MD5(A1)=MD5(username:realm:password)&&如果&qop&值为“auth”或未指定,那么&HA2&为&&HA2=MD5(A2)=MD5(method:digestURI)&&如果&qop&值为“auth-int”,那么&HA2&为&&HA2=MD5(A2)=MD5(method:digestURI:MD5(entityBody))&&如果&qop&值为“auth”或“auth-int”,那么如下计算&response:&&response=MD5(HA1:nonce:nonceCount:clientNonce:qop:HA2)&&如果&qop&未指定,那么如下计算&response:&&response=MD5(HA1:nonce:HA2)&&
Html代码 &
GET&/dir/index.html&HTTP/1.0&&Host:&localhost&&Authorization:&Digest&username=&Mufasa&,&&&&&&&&&&&&&&&&&&&&&&&realm=&&,&&&&&&&&&&&&&&&&&&&&&&&nonce=&dcd98be8b11d0f600bfb0c093&,&&&&&&&&&&&&&&&&&&&&&&&uri=&/dir/index.html&,&&&&&&&&&&&&&&&&&&&&&&&qop=auth,&&&&&&&&&&&&&&&&&&&&&&&nc=,&&&&&&&&&&&&&&&&&&&&&&&cnonce=&0a4f113b&,&&&&&&&&&&&&&&&&&&&&&&&response=&6629faeef1&,&&&&&&&&&&&&&&&&&&&&&&&opaque=&5ccc069c403ebaf9fe41&&&
4.服务器响应
当服务器接收到摘要响应,也要重新计算响应中各参数的值,并利用客户端提供的参数值,和服务器上存储的口令,进行比对。如果计算结果与收到的客户响应值是相同的,则客户已证明它知道口令,因而客户的身份验证通过。
Html代码 &
HTTP/1.0&200&OK&&
二、服务端验证
编写一个自定义消息处理器,需要通过System.Net.Http.DelegatingHandler进行派生,并重写SendAsync方法。
public&class&AuthenticationHandler&:&DelegatingHandler&&{&&&&&&protected&async&override&Task&HttpResponseMessage&&SendAsync(HttpRequestMessage&request,&CancellationToken&cancellationToken)&&&&&&{&&&&&&&&&&try&&&&&&&&&&{&&&&&&&&&&&&&&HttpRequestHeaders&headers&=&request.H&&&&&&&&&&&&&&if&(headers.Authorization&!=&null)&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&Header&header&=&new&Header(request.Headers.Authorization.Parameter,&request.Method.Method);&&&&&&&&&&&&&&&&&&&&if&(Nonce.IsValid(header.Nonce,&header.NounceCounter))&&&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&string&password&=&header.UserN&&&&&&&&&&&&&&&&&&&&&&&&string&ha1&=&String.Format(&{0}:{1}:{2}&,&header.UserName,&header.Realm,&password).ToMD5Hash();&&&&&&&&&&&&&&&&&&&&&&&&string&ha2&=&String.Format(&{0}:{1}&,&header.Method,&header.Uri).ToMD5Hash();&&&&&&&&&&&&&&&&&&&&&&&&string&computedResponse&=&String.Format(&{0}:{1}:{2}:{3}:{4}:{5}&,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ha1,&header.Nonce,&header.once,&&auth&,&ha2).ToMD5Hash();&&&&&&&&&&&&&&&&&&&&&&&&if&(pareOrdinal(header.Response,&computedResponse)&==&0)&&&&&&&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&var&claims&=&new&List&Claim&&&&&&&&&&&&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&new&Claim(ClaimTypes.Name,&header.UserName),&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&new&Claim(ClaimTypes.AuthenticationMethod,&AuthenticationMethods.Password)&&&&&&&&&&&&&&&&&&&&&&&&&&};&&&&&&&&&&&&&&&&&&&&&&&&&&&&ClaimsPrincipal&principal&=&new&ClaimsPrincipal(new[]&{&new&ClaimsIdentity(claims,&&Digest&)&});&&&&&&&&&&&&&&&&&&&&&&&&&&&&Thread.CurrentPrincipal&=&&&&&&&&&&&&&&&&&&&&&&&&&&&&&if&(HttpContext.Current&!=&null)&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&HttpContext.Current.User&=&&&&&&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&HttpResponseMessage&response&=&await&base.SendAsync(request,&cancellationToken);&&&&&&&&&&&&&&&&if&(response.StatusCode&==&HttpStatusCode.Unauthorized)&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&response.Headers.WwwAuthenticate.Add(new&AuthenticationHeaderValue(&Digest&,Header.UnauthorizedResponseHeader.ToString()));&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&return&&&&&&&&&&&}&&&&&&&&&&catch&(Exception)&&&&&&&&&&{&&&&&&&&&&&&&&var&response&=&request.CreateResponse(HttpStatusCode.Unauthorized);&&&&&&&&&&&&&&response.Headers.WwwAuthenticate.Add(new&AuthenticationHeaderValue(&Digest&,Header.UnauthorizedResponseHeader.ToString()));&&&&&&&&&&&&&&&&return&&&&&&&&&&&}&&&&&&}&&}&&
public&class&Header&&{&&&&&&public&Header()&{&}&&&&&&&&public&Header(string&header,&string&method)&&&&&&{&&&&&&&&&&string&keyValuePairs&=&header.Replace(&\&&,&String.Empty);&&&&&&&&&&&&foreach&(string&keyValuePair&in&keyValuePairs.Split(','))&&&&&&&&&&{&&&&&&&&&&&&&&int&index&=&keyValuePair.IndexOf(&=&,&System.StringComparison.Ordinal);&&&&&&&&&&&&&&string&key&=&keyValuePair.Substring(0,&index);&&&&&&&&&&&&&&string&value&=&keyValuePair.Substring(index&+&1);&&&&&&&&&&&&&&&&switch&(key)&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&case&&username&:&this.UserName&=&&break;&&&&&&&&&&&&&&&&&&case&&realm&:&this.Realm&=&&break;&&&&&&&&&&&&&&&&&&case&&nonce&:&this.Nonce&=&&break;&&&&&&&&&&&&&&&&&&case&&uri&:&this.Uri&=&&break;&&&&&&&&&&&&&&&&&&case&&nc&:&this.NounceCounter&=&&break;&&&&&&&&&&&&&&&&&&case&&cnonce&:&this.Cnonce&=&&break;&&&&&&&&&&&&&&&&&&case&&response&:&this.Response&=&&break;&&&&&&&&&&&&&&&&&&case&&method&:&this.Method&=&&break;&&&&&&&&&&&&&&}&&&&&&&&&&}&&&&&&&&&&&&if&(String.IsNullOrEmpty(this.Method))&&&&&&&&&&&&&&this.Method&=&&&&&&&}&&&&&&&&public&string&Cnonce&{&get;&private&set;&}&&&&&&public&string&Nonce&{&get;&private&set;&}&&&&&&public&string&Realm&{&get;&private&set;&}&&&&&&public&string&UserName&{&get;&private&set;&}&&&&&&public&string&Uri&{&get;&private&set;&}&&&&&&public&string&Response&{&get;&private&set;&}&&&&&&public&string&Method&{&get;&private&set;&}&&&&&&public&string&NounceCounter&{&get;&private&set;&}&&&&&&&&&&&&&&&&&&&&&&&&&&public&static&Header&UnauthorizedResponseHeader&&&&&&{&&&&&&&&&&get&&&&&&&&&&{&&&&&&&&&&&&&&return&new&Header()&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&Realm&=&&MyRealm&,&&&&&&&&&&&&&&&&&&Nonce&=&WebApiDemo.Nonce.Generate()&&&&&&&&&&&&&&};&&&&&&&&&&}&&&&&&}&&&&&&&&public&override&string&ToString()&&&&&&{&&&&&&&&&&StringBuilder&header&=&new&StringBuilder();&&&&&&&&&&header.AppendFormat(&realm=\&{0}\&&,&Realm);&&&&&&&&&&header.AppendFormat(&,nonce=\&{0}\&&,&Nonce);&&&&&&&&&&header.AppendFormat(&,qop=\&{0}\&&,&&auth&);&&&&&&&&&&return&header.ToString();&&&&&&}&&}&&
public&class&Nonce&&{&&&&&&private&static&ConcurrentDictionary&string,&Tuple&int,&DateTime&&&&&&&&nonces&=&new&ConcurrentDictionary&string,&Tuple&int,&DateTime&&();&&&&&&&&public&static&string&Generate()&&&&&&{&&&&&&&&&&byte[]&bytes&=&new&byte[16];&&&&&&&&&&&&using&(var&rngProvider&=&new&RNGCryptoServiceProvider())&&&&&&&&&&{&&&&&&&&&&&&&&rngProvider.GetBytes(bytes);&&&&&&&&&&}&&&&&&&&&&&&string&nonce&=&bytes.ToMD5Hash();&&&&&&&&&&&&nonces.TryAdd(nonce,&new&Tuple&int,&DateTime&(0,&DateTime.Now.AddMinutes(10)));&&&&&&&&&&&&return&&&&&&&}&&&&&&&&public&static&bool&IsValid(string&nonce,&string&nonceCount)&&&&&&{&&&&&&&&&&Tuple&int,&DateTime&&cachedNonce&=&null;&&&&&&&&&&&&&&&&&&&&nonces.TryRemove(nonce,&out&cachedNonce);&&&&&&&&&&&&if&(cachedNonce&!=&null)&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&&&&&&if&(Int32.Parse(nonceCount)&&&cachedNonce.Item1)&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&if&(cachedNonce.Item2&&&DateTime.Now)&&&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&return&true;&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&}&&&&&&&&&&}&&&&&&&&&&&&return&false;&&&&&&}&&}&&
&需要使用摘要验证可在代码里添加Attribute [Authorize],如:
[Authorize]&&public&class&ProductsController&:&ApiController&&
&最后Global.asax里需注册下
GlobalConfiguration.Configuration.MessageHandlers.Add(&&new&AuthenticationHandler());&&
三、客户端的调用
这里主要说明使用WebClient调用
public&static&string&Request(string&sUrl,&string&sMethod,&string&sEntity,&string&sContentType,&&&&&&out&string&sMessage)&&{&&&&&&try&&&&&&{&&&&&&&&&&sMessage&=&&&;&&&&&&&&&&using&(System.Net.WebClient&client&=&new&System.Net.WebClient())&&&&&&&&&&{&&&&&&&&&&&&&&client.Credentials&=&CreateAuthenticateValue(sUrl);&&&&&&&&&&&&&&client.Headers&=&CreateHeader(sContentType);&&&&&&&&&&&&&&&&Uri&url&=&new&Uri(sUrl);&&&&&&&&&&&&&&byte[]&bytes&=&Encoding.UTF8.GetBytes(sEntity);&&&&&&&&&&&&&&byte[]&&&&&&&&&&&&&&&switch&(sMethod.ToUpper())&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&case&&GET&:&&&&&&&&&&&&&&&&&&&&&&buffer&=&client.DownloadData(url);&&&&&&&&&&&&&&&&&&&&&&break;&&&&&&&&&&&&&&&&&&case&&POST&:&&&&&&&&&&&&&&&&&&&&&&buffer&=&client.UploadData(url,&&POST&,&bytes);&&&&&&&&&&&&&&&&&&&&&&break;&&&&&&&&&&&&&&&&&&default:&&&&&&&&&&&&&&&&&&&&&&buffer&=&client.UploadData(url,&&POST&,&bytes);&&&&&&&&&&&&&&&&&&&&&&break;&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&return&Encoding.UTF8.GetString(buffer);&&&&&&&&&&}&&&&&&}&&&&&&catch&(WebException&ex)&&&&&&{&&&&&&&&&&sMessage&=&ex.M&&&&&&&&&&var&rsp&=&ex.Response&as&HttpWebR&&&&&&&&&&var&httpStatusCode&=&rsp.StatusC&&&&&&&&&&var&authenticate&=&rsp.Headers.Get(&WWW-Authenticate&);&&&&&&&&&&&&return&&&;&&&&&&}&&&&&&catch&(Exception&ex)&&&&&&{&&&&&&&&&&sMessage&=&ex.M&&&&&&&&&&return&&&;&&&&&&}&&}&&
&关键代码,在这里添加用户认证,使用NetworkCredential
private&static&CredentialCache&CreateAuthenticateValue(string&sUrl)&&{&&&&&&CredentialCache&credentialCache&=&new&CredentialCache();&&&&&&credentialCache.Add(new&Uri(sUrl),&&Digest&,&new&NetworkCredential(&Lime&,&&Lime&));&&&&&&&&return&credentialC&&}&&
&至此整个认证就ok了。
http://zrj-/blog/2163487
本文已收录于以下专栏:
相关文章推荐
using System.L
using System.W
using System.Web.H
using System.Web.S...
前言:Web 用户的身份验证,及页面操作权限验证是B/S系统的基础功能,一个功能复杂的业务应用系统,通过角色授权来控制用户访问,本文通过Form认证,Mvc的Controller基类及Action的权...
Linux老难题解决了!
Linux工程师很多,甚至有很多有多年工作经验,但是对一些关键概念的理解非常模糊,比如不理解CPU、内存资源等的真正分布,具体的工作机制,这使得他们对很多问题的分析都摸不到方向。比如进程的调度延时是多少?linux能否硬实时?多核下多线程如何执行?
» 增加模型验证
» 自定义过滤器,输出模型验证信息
» FromUri和FromBody用途
下面一步一个脚印的来分享:
» 增加模型验证
首先,我们测试用例使用上一篇的 MoStu...
分布式通讯框架--&一个系统要访问另外一个系统中的数据,有一下三种方法,第一种分为2种
1.0 ,MVC Webapi  (严格的讲它其实仅仅是一个设计方案,而不是一个设计框架,Webapi流行的...
Web用户的身份验证及WebApi权限验证流程的设计和实现
14:42 32033人阅读 评论(4) 收藏 举报
 分类:
MVC技术(29) 
对于一般的开发人员来说,很少需要对安全领域内的基础技术进行深入的研究,但是鉴于日常系统开发中遇到的各种安全相关的问题,熟悉和了解这些安全技术的基本原理和使用场景还是非常必要的。本文将对非对称加密、数字...
身份验证(Authentication):确定用户是谁。
授权(Authorization):确定用户能做什么,不能做什么。
WebApi 假定身份验证发生在宿主程序称中。...
Web API入门指南
有些朋友回复问了些安全方面的问题,安全方面可以写的东西实在太多了,这里尽量围绕着Web API的安全性来展开,介绍一些安全的基本概念,常见安全隐患、相关的防御技巧以及Web A...
PHP的api接口
在实际工作中,使用PHP写api接口是经常做的,PHP写好接口后,前台就可以通过链接获取接口提供的数据,而返回的数据一般分为两种情况,xml和json,在这个过程中,服务器并不知...
       在app开放接口api的设计中,避免不了的就是安全性问题,因为大多数接口涉及到用户的个人信息以及一些敏感的数据,所以对这些接口需要进行身份的认证,那么这就需要用户提供一些信息,比如...
他的最新文章
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)

我要回帖

更多关于 noncestr如何获取 的文章

 

随机推荐