qq空间百度分享summary 怎么动态赋值summary的值

asp.net mvc 如何调用微信jssdk接口:分享到微信朋友(圈)| 分享到qq空间
时间: 06:53:45
&&&& 阅读:805
&&&& 评论:
&&&& 收藏:0
标签:&&&&&&如何在asp.net mvc 项目里, 调用微信jssdk接口,现实功能: 分享到微信朋友(圈)| 分享到qq空间1 创建一个Action,准备一些数据,初始化数据(签名):/// &summary&& & & & /// 分享的内容& & & & /// 必须写在html的head里面才可以生效& & & & /// &/summary&& & & & /// &param name="fxUrl"&&/param&& & & & /// &returns&&/returns&& & & & public ActionResult SharePartial(string fxUrl="")& & & & {& & & & & & BLL.SiteConfigBLL SiteBLL = new BLL.SiteConfigBLL();& & & & & & Model.siteconfig siteConfig = SiteBLL.getConfig();& & & & & & ShareModel fxModel = new ShareModel();& & & & & & fxModel.appid = siteConfig.& & & & & & fxModel.timestamp = JSSDKHelper.GetTimestamp();& & & & & & fxModel.nonce = JSSDKHelper.GetNoncestr();& & & & & & fxModel.thisUrl = Request.Url.ToString();//MyCommFun.getTotalUrl();& & & & & & if (fxUrl == null || fxUrl.Trim() == "")& & & & & & {& & & & & & & & fxModel.fxUrl = fxModel.thisU& & & & & & }& & & & & & else& & & & & & {& & & & & & & & fxModel.fxUrl = fxU& & & & & & }& & & & & & string ticket = AccessTokenContainer.TryGetJsApiTicket(siteConfig.appid, siteConfig.appsecret);& & & & & & JSSDKHelper jsHelper = new JSSDKHelper();& & & & & & //最后一个参数url,必须为当前的网址& & & & & & var signature = JSSDKHelper.GetSignature(ticket, fxModel.nonce, fxModel.timestamp, fxModel.thisUrl);& & & & & & fxModel.signature =& & & & & & return PartialView("SharePartial", fxModel);& & & & }2 创建一个局部视图,对应上面的Action。@model &Model.ShareModel && & & &&!--分享--&&script src="http://res./open/js/jweixin-1.0.0.js" type="text/javascript"&&/script&&script type="text/javascript"&& & //本活动被分享次数& & var dataForWeixin = {& & & & appId: "@Model.appid",& & & & MsgImg: "@Model.fxImg",& & & & TLImg: "@Model.fxImg",& & & & url: "@Model.thisUrl",& & & & fxUrl: "@Model.fxUrl",& & & & title: "@Model.fxTitle",& & & & desc: "@Model.fxContent",& & & & timestamp: "@Model.timestamp",& & & & nonceStr: "@Model.nonce",& & & & signature: "@Model.signature",& & & & jsApiList: [‘onMenuShareTimeline‘, ‘onMenuShareAppMessage‘, ‘onMenuShareQQ‘, ‘onMenuShareQZone‘, ‘onMenuShareWeibo‘, ‘showOptionMenu‘, ‘closeWindow‘],& & & & fakeid: "",& & & & callback: function () { }& & };& & wx.config({& & & & debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。& & & & appId: dataForWeixin.appId, // 必填,公众号的唯一标识& & & & timestamp: dataForWeixin.timestamp, // 必填,生成签名的时间戳& & & & nonceStr: dataForWeixin.nonceStr, // 必填,生成签名的随机串& & & & signature: dataForWeixin.signature,// 必填,签名,见附录1& & & & jsApiList: dataForWeixin.jsApiList &// 必填,需要使用的JS接口列表,所有JS接口列表见附录2& & });& & wx.ready(function () {& & & & //在此输入各种API& & & & wx.showOptionMenu();& & & & //分享到朋友圈& & & & wx.onMenuShareTimeline({& & & & & & title: dataForWeixin.title, // 分享标题& & & & & & link: dataForWeixin.fxUrl, // 分享链接& & & & & & imgUrl: dataForWeixin.MsgImg, // 分享图标& & & & & & success: function () {& & & & & & & & // 用户确认分享后执行的回调函数& & & & & & & & fxJia();//分享+1& & & & & & },& & & & & & cancel: function () {& & & & & & & & // 用户取消分享后执行的回调函数& & & & & & }& & & & });& & & & //分享给朋友& & & & wx.onMenuShareAppMessage({& & & & & & title: dataForWeixin.title, // 分享标题& & & & & & desc: dataForWeixin.desc, // 分享描述& & & & & & link: dataForWeixin.fxUrl, // 分享链接& & & & & & imgUrl: dataForWeixin.TLImg, // 分享图标& & & & & & type: ‘‘, // 分享类型,music、video或link,不填默认为link& & & & & & dataUrl: ‘‘, // 如果type是music或video,则要提供数据链接,默认为空& & & & & & success: function () {& & & & & & & & // 用户确认分享后执行的回调函数& & & & & & & & fxJia();//分享+1& & & & & & },& & & & & & cancel: function () {& & & & & & & & // 用户取消分享后执行的回调函数& & & & & & }& & & & });& & & & //QQ& & & & wx.onMenuShareQQ({& & & & & & title: dataForWeixin.title, // 分享标题& & & & & & desc: dataForWeixin.desc, // 分享描述& & & & & & link: dataForWeixin.fxUrl, // 分享链接& & & & & & imgUrl: dataForWeixin.MsgImg,// 分享图标& & & & & & success: function () {& & & & & & & & // 用户确认分享后执行的回调函数& & & & & & },& & & & & & cancel: function () {& & & & & & & & // 用户取消分享后执行的回调函数& & & & & & }& & & & });& & & & //QQ微博& & & & wx.onMenuShareWeibo({& & & & & & title: dataForWeixin.title, // 分享标题& & & & & & desc: dataForWeixin.desc, // 分享描述& & & & & & link: dataForWeixin.fxUrl, // 分享链接& & & & & & imgUrl: dataForWeixin.TLImg, // 分享图标& & & & & & success: function () {& & & & & & & & // 用户确认分享后执行的回调函数& & & & & & },& & & & & & cancel: function () {& & & & & & & & // 用户取消分享后执行的回调函数& & & & & & }& & & & });& & & & //QQ空间& & & & wx.onMenuShareQZone({& & & & & & title: dataForWeixin.title, // 分享标题& & & & & & desc: dataForWeixin.desc, // 分享描述& & & & & & link: dataForWeixin.fxUrl, // 分享链接& & & & & & imgUrl: dataForWeixin.TLImg, // 分享图标& & & & & & success: function () {& & & & & & & & // 用户确认分享后执行的回调函数& & & & & & },& & & & & & cancel: function () {& & & & & & & & // 用户取消分享后执行的回调函数& & & & & & }& & & & });& & & & // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,& & & & //所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。& & });& & wx.error(function (res) {& & & & //alert(res);& & & & // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。& & });&/script&&!--end分享--&之所以使用局部视图,是方便其他的页面(视图)调用,哪个页面(视图)需要,就直接调用局部视图;也就不需要在每个页面都写了。在写项目之前,需要引用2个dll:Senparc.Weixin.dllSenparc.Weixin.MP.dll&注意事项:1 签名时,传的参数,必须是当前页面的地址,必须一模一样;2 js最好放在&head&内。3 在微信公众号官方后台,公众号设置---功能设置---业务域名 和&JS接口安全域名,填写你网页的域名(需备案)。650) this.width=650;" src="/blog//-.png"
style="margin:0padding:0border:0" />&本文出自 “” 博客,请务必保留此出处标签:&&&&&&
&&国之画&&&& &&
版权所有 京ICP备号-2
迷上了代码!QQ JS_SDk相关功能接口 - 人生梦想起飞 - 博客园
posts - 189, comments - 8, trackbacks - 0, articles - 0
一、实现QQ登录功能
&!DOCTYPE html&&html lang="zh-cn"&&& &head& &&&& &meta http-equiv="Content-Type" content="text/ charset=utf-8" /&&&&& &title&QQ登录功能 - JSSDK&/title&&& &/head& && &body& &&&& &a href="javascript:void(0)" id="qq_login_btn" _origText="get_user_info 加载昵称中..." title="nickname"&QQ登录&/span&&&&& &a href="javascript:void(0)" id="login_btn" _origText="get_user_info 加载昵称中..." title="nickname"&QQ登录申请回调地址&/span&&&&& &a href="javascript:void(0)" id="qq_logout_btn" &退出&/span&&& &/body&&/html&&script type="text/javascript" src="/qzone/openapi/qc_loader.js" charset="utf-8" data-appid="" data-redirecturi=""&&/script&&!--appid和redirecturi可以放在加载js中--&&script type="text/javascript"&& //检测是否已经登录& function getInfo() {&&& if(QC.Login.check()){&&&&& QC.api("get_user_info")&&&&&&& .success(function(s){//成功回调&&&&&&&&& alert("获取用户信息成功!当前用户昵称为:"+s.data.nickname);&&&&&&& })&&&&&&& .error(function(f){//失败回调&&&&&&&&& alert("获取用户信息失败!");&&&&&&& })&&&&&&& .complete(function(c){//完成请求回调&&&&&&&&& alert("获取用户信息完成!");&&&&&&& });&&& }else{&&&&& alert("请登录后体验");&&& }& }& getInfo();& //方法一& //加入QQ登录按钮,这种方法打开的是一个小窗口的网页页面& /* QC.Login({&&& btnId:"qq_login_btn"& });*///方法二document.getElementById('qq_login_btn').onclick = function(){&&& QC.Login.showPopup({&&&&&&& appId:"",&&&&&&& redirectURI:""//回调地址必须以http或https开头。回调地址为空时登录成功后直接返回当前登录页面&&&& });}document.getElementById('login_btn').onclick = function(){&&& QC.Login.showPopup({&&&&& appId:"",//申请appId 可以返回会跳地址,其中要填写回调地址和名称&&&&& redirectURI:"/connect/success?t=qq&state=e1228eadfdb270bf1e07c726&scope=get_user_info"//回调地址必须以http或https开头。&&& });}//检测当前登录状态返回值说明:true:说明登录成功。false:说明登录失败。if(QC.Login.check()){&& document.getElementById('qq_logout_btn').onclick = function(){&&&&&& QC.Login.signOut()&&&&&& alert("退出")&& }}&/script&
二、实现分享到QQ好友功能
&&!DOCTYPE html&&html lang="zh-cn"&&& &head& &&&& &meta http-equiv="Content-Type" content="text/ charset=utf-8" /&&&&& &title&分享到QQ好友功能 - JSSDK&/title&&& &/head& && &body& &&& &a title="分享到QQ后面链接使用的是encodeURIComponent" hidefocus="true" target="_blank" href="/widget/shareqq/index.html?url=http%3A%2F%2Fwiki.%2Fjs_sdk%25e4%25bd%25bf%25e7%%25e8%25af%25b4%25e6%Fsource%3Dshareqq&desc=%E8%AF%B7%E5%8F%82%E8%80%83QQ%E4%BA%92%E8%81%94%E6%96%87%E6%A1%A3%E5%BA%93%E4%B8%AD%E7%9A%84%E3%80%8AJS_SDK%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E%E3%80%8B%EF%BC%8C%E5%B8%8C%E6%9C%9B%E5%AF%B9%E4%BD%A0%E6%9C%89%E5%B8%AE%E5%8A%A9%E3%80%82&title=JS_SDK%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E-QQ%E4%BA%92%E8%81%94%E6%96%87%E6%A1%A3%E5%BA%93&summary=&pics=&flash=&site=QQ%E4%BA%92%E8%81%94%E6%96%87%E6%A1%A3%E5%BA%93&callback=http%3A%2F%2Fcgi.%2Freport%2Freport_vm%3Ftag%3D0%26log%3Djs~sdk%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E_t%3D6" class="qcShareQQDiv"&分享到QQ&/a&&!--分享到QQ可以把链接直接放到a标签的href中,里面的参数要用encodeURIComponent编码--&&&& &a class="bt_icon" href="###" id="qcShareQQDiv" title="发送到QQ好友和群"&发送到QQ好友和群&/a&&& &/body&&&/html&&script&document.getElementById('qcShareQQDiv').onclick = function(e){&&& var& p = {&& &&& &&&& url: '/widget/shareqq/test_iframe_shareqq.html',/*获取URL,可加上来自分享到QQ标识,方便统计*/&& &&& &&&& desc: 'QQ分享', /*分享理由(风格应模拟用户对话),支持多分享语随机展现(使用|分隔)*/&& &&& &&&& title : 'QQ分享',/*分享标题(可选)*/&& &&& &&&& summary : 'QQ分享',/*分享描述(可选)*/&& &&& &&&& pics : '',/*分享图片(可选)*/&& &&& &&&& flash : '', /*视频地址(可选)*/&& &&& &&&& //commonClient : true, /*客户端嵌入标志*/&& &&& &&&& site: 'QQ分享'/*分享来源 (可选) ,如:QQ分享*/&&&&&&& };&&&&&&& var s = [];&&&&&&& for (var i in p) {&&&&&&&&&&& s.push(i + '=' + encodeURIComponent(p[i] || ''));&&&&&&& }&&&&&&& //使用/widget/shareqq/iframe_index.html链接,iframe_index.html是弹出层效果,index.html是新打开页面效果&&&&&&& var _src = "/widget/shareqq/index.html?" + s.join('&') ;&&&&&&& window.open(_src);&&& };& &&/script&
三、实现分享内容到QQ空间功能
&&&&& 实现分享内容到QQ空间功能和二中实现分享到QQ好友功能的配置使用方法完全一样,只是将前面的链接/widget/shareqq/index.html改成http:
&&&&&& //sns./cgi-bin/qzshare/cgi_qzshare_onekey即可,?后面的完全一样
以上内容参考网址来源于1 &!DOCTYPE HTML&
&title&QQ空间分享&/title&
&meta http-equiv="Content-Type" content="text/ charset=utf-8" /&
&input type="button" onclick="shareQQzone();" value="分享"&&/input&
<span style="color: # &script src="/qzone/app/qzlike/qzopensl.js#jsdate=" charset="utf-8"&&/script&
<span style="color: # &script&
<span style="color: #
//QQ空间分享方法:这样写可以对分享事件进行绑定
<span style="color: #
function shareQQzone(){
<span style="color: #
var _url = '';
<span style="color: #
var _showcount = '<span style="background-color: #f5f5f5; color: #'
<span style="color: #
var _desc = '我正在我的相册网冲洗照片';
<span style="color: #
var _summary = '大家都来看看吧';
<span style="color: #
var _title = '真不错';
<span style="color: #
var _site = '我的相册网';
<span style="color: #
var _pic = '';
<span style="color: #
var _width= '<span style="background-color: #f5f5f5; color: #0px';
<span style="color: #
var _height= '<span style="background-color: #f5f5f5; color: #0px';
<span style="color: #
<span style="color: #
var _shareUrl = 'http://sns./cgi-bin/qzshare/cgi_qzshare_onekey?';
<span style="color: #
_shareUrl += 'url=' + encodeURIComponent(_url||document.location);
//参数url设置分享的内容链接|默认当前页location
<span style="color: #
_shareUrl += '&showcount=' + _showcount||<span style="background-color: #f5f5f5; color: #;
//参数showcount是否显示分享总数,显示:'1',不显示:'0',默认不显示
<span style="color: #
_shareUrl += '&desc=' + encodeURIComponent(_desc||'分享的描述');
//参数desc设置分享的描述,可选参数
<span style="color: #
_shareUrl += '&summary=' + encodeURIComponent(_summary||'分享摘要');
//参数summary设置分享摘要,可选参数
<span style="color: #
_shareUrl += '&title=' + encodeURIComponent(_title||document.title);
//参数title设置分享标题,可选参数
<span style="color: #
_shareUrl += '&site=' + encodeURIComponent(_site||'');
//参数site设置分享来源,可选参数
<span style="color: #
_shareUrl += '&pics=' + encodeURIComponent(_pic||'');
//参数pics设置分享图片的路径,多张图片以"|"隔开,可选参数
<span style="color: #
window.open(_shareUrl,'_blank','width='+_width+',height='+_height+',top='+(screen.height-_height)/<span style="background-color: #f5f5f5; color: #+',left='+(screen.width-_width)/<span style="background-color: #f5f5f5; color: #+',toolbar=no,menubar=no,scrollbars=no,resizable=1,location=no,status=0');
<span style="color: #
<span style="color: # &/script&
<span style="color: # &/html&
阅读(...) 评论()将qq空间的说说同步至博客园系列之通过Cookie和qq空间g_tk参数取得空间数据(2) - 推酷
将qq空间的说说同步至博客园系列之通过Cookie和qq空间g_tk参数取得空间数据(2)
刚开始博主的思路是写一个Chrome扩展,然后每次当我打开空间的时候自动记录数据到本地。后来感觉javascript操作数据很不方便,便决定还是使用C#来取数据。
另外先透漏一下,从qq空间取数据到博客园后博主的思路。博主打算使用Knockout组件的形式在博客园渲染页面。所以现在把qq空间同步至博客园这个工程大概有以下三步。一是本地服务端取数据存储到数据库。二是通过javascript调用wcf将数据传输到博客园,最后是使用KnockOut将数据渲染至页面。
另:博主本打算模拟qq空间登录的方式来取数据。不过qq空间登录的模块是使用插件的形式登录的。了解其机制代价太大。所以决定通过下面这种方式取数据。
另:现在页面上还看不到效果。最后一步使用KnockOut将数据渲染至页面博主还没开始准备。现在我们开始到qq空间取数据。
确定qq空间异步无刷新填充数据的报文必要参数
我们仔细观察下qq空间首页,会发现qq空间全部动态那儿有个刷新的按钮
点击此处会异步去qq服务器取数据。如下图
我们将该链接访问以下。
http://user./p/ic2.s51/cgi-bin/feeds/feeds3_html_more?uin=&scope=0&view=1&daylist=&uinlist=&gid=&flag=1&filter=all&applist=all&refresh=0&aisortEndTime=0&aisortOffset=0&getAisort=0&aisortBeginTime=0&pagenum=2&externparam=basetime%3D%26pagenum%3D2%26dayvalue%3D0&firstGetGroup=0&icServerTime=0&mixnocache=0&scene=0&begintime=&count=10&dayspac=0&sidomain=cm.&useutf8=1&outputhtmlfeed=1&rd=0.5886&g_tk=
如上所示,可以通过这样取到我们需要的json数据。
那么问题来了。我们如果要使用System.Net该类库提供的服务来模拟http请求报文,都需要什么条件么。毫无疑问,在这儿需要的是,一个是get请求的url,包括该get请求传递过去的参数。以及报文发送时随报文发送的cookie.
需求已经明了。我们需要得到get参数,以及发送的cookie.
破解g_tk=参数的秘密
观察上面我发布get链接。首先最想说的是,这参数也太**多了。不过没问题。我们多对比几次就会发现,上面的大部分参数都是不怎么变化的。其中一个begintime参数,博主试了下并没有多大的影响。几经确认,发现该get请求最重要的参数只有一个,那就是g_tk参数。该参数和cookie几乎决定了我们请求数据的成败。那么该参数到底是在哪儿来的呢。
要想知道该参数怎么来的,我们就要知道当我们点击刷新的时候,javascript函数到底做了什么。怎样生成的ajax请求呢。那么我们就需要知道当我们点击该刷新按钮的时候执行的是什么函数,也就是该按钮到底和哪个javascript函数绑定。那么问题来了----如何找到dom元素绑定的函数呢。我们首先在chrome浏览器下f12调试。
博主在这儿找了半天,也没找到有用的信息,不过幸好博主找到了一个神器
该插件可以提供让我们看dom元素绑定函数的功能,虽说有些限制,不过在这儿确实发挥了作用。
既然找到了该函数调用的函数,那么顺藤摸瓜。博主找到了下面这个函数。
pingCgi: function () {
&http://& + g_R_Domain + &/cgi-bin/user/qzone_cgi_msg_getcnt2&; setInterval(function () { QZFL.pingSender(a + &?uin=& + g_iLoginUin + &&bm=& + g_LoginBitmap + &&v=& + c.getCGISeed(&_QZN_TodoMsgCnt&) + &&g_tk=& + QZONE.FrontPage.getACSRFToken() + &&g=& + Math.random(), 0) }, 6E5)
显然g_tk是通过QZONE.FrontPage.getACSRFToken()这个函数生成的。我们继续找到该函数。
QZONE.FrontPage.getACSRFToken = function (a) {
a = QZFL.util.URI(a);
a && (a.host && 0 & a.host.indexOf(&&) ? b = QZFL.cookie.get(&p_skey&) : a.host && 0 & a.host.indexOf(&&) && (b = QZFL.cookie.get(&skey&)));
b || (b = QZFL.cookie.get(&skey&) || QZFL.cookie.get(&rv2&));
for (var c = 0, d = b. c & ++c)
a += (a && 5) + b.charAt(c).charCodeAt();
return a &
找到了个函数那么问题就清楚了。该函数调用了cookie里面的P_skey参数来生成了该g_tk. 我们可以使用C#来重写该javascript函数。
public string getg_tk(string str)
var a = 5381;
for (int c = 0, d = b.L c & ++c)
//这儿是javascript代码的c#实现。b[c]取到字符串在c索引处的字符。强转为int既是将char转为Unicode
a += (a && 5) + (int)b[c];
return (a & ).ToString();
之后我们传入cookie里面的p_skey=rK6xJHZPMWUxBj6ehdS5CoILGC8aMt7EPEgNYVRBbRU_;会发现生成的g_tk和我们用来调用的g_tk=相等。如下图。
现在解决了get参数的问题,我们再来解决我们的cookie问题。
使用sqllite数据库获取chrome cookie数据表
我们找到chrome cookie所在的文件夹。
使用notepad打开,会发现是乱码。这是因为chrome后来版本的cookie都是通过加密后存储到了sqlite数据库里面。
为我们的项目添加如下引用。同时在我们项目的bin问价夹下添加SQLite.Interop.dll类库。
我们添加一个sqllitehelper帮助类。
//添加一个静态帮助类 public static class SqlLiteHelper
public static DataTable ExecuteSql(System.Data.IDbConnection connection, string sql)
var cmd = connection.CreateCommand();
mandText =
using (var reader = cmd.ExecuteReader())
var dataTable = new DataTable();
dataTable.Load(reader);
return dataT
//这是sqllite数据库的连接字符串
string connectionString = @&Data Source=C:\Documents and Settings\wfm\Local Settings\Application Data\Google\Chrome\User Data\Default\Cookies&;
//使用using用来释放非托管资源,垃圾回收。
using (var conn = new System.Data.SQLite.SQLiteConnection(connectionString))
conn.Open();
DataTable db = SqlLiteHelper.ExecuteSql(conn, &select host_key,name,value,encrypted_&);
使用上面的代码我们就可取到sqllite数据库的数据。
使用crypt32.dll下的CryptUnprotectData函数解密chrome cookie
如上图取到cookie的数据后我们会发现取到的value值是空的,同时有一个encrypted_value的byte数组.随便google一下我们就知道这是chrome新版本里面存储的cookie数据。不过被chrome加密了。那么现在我们就需要解密cookie.如何解密,博主其实一点也不会。不过幸好有大神会。搜索相关资源,我们知道需要用到
crypt32.dll下的CryptUnprotectData函数来解密。我们寻找资源会发现相关的资料都是使用Python实现的。并没有c#下面的代码可以拿来直接用。相关连接如下
,还有一些其它类似的资料。这里就不列出了。
我们新建一个类DPAPI相关代码如下。
///////////////////////////////////////////////////////////////////////////////
// SAMPLE: Encryption and decryption using DPAPI functions.
// To run this sample, create a new Visual C# project using the Console
// Application template and replace the contents of the Class1.cs file
// with the code below.
// THIS CODE AND INFORMATION IS PROVIDED &AS IS& WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
// PURPOSE.
// Copyright (C) 2003 Obviex(TM). All rights reserved.
using System.T
using System.Runtime.InteropS
/// &summary&
/// Encrypts and decrypts data using DPAPI functions.
/// &/summary&
public class DPAPI
// Wrapper for DPAPI CryptProtectData function.
[DllImport(&crypt32.dll&,
SetLastError = true,
CharSet = System.Runtime.InteropServices.CharSet.Auto)]
private static extern
bool CryptProtectData(ref DATA_BLOB pPlainText,
string szDescription,
ref DATA_BLOB pEntropy,
IntPtr pReserved,
ref CRYPTPROTECT_PROMPTSTRUCT pPrompt,
int dwFlags,
ref DATA_BLOB pCipherText);
// Wrapper for DPAPI CryptUnprotectData function.
[DllImport(&crypt32.dll&,
SetLastError = true,
CharSet = System.Runtime.InteropServices.CharSet.Auto)]
private static extern
bool CryptUnprotectData(ref DATA_BLOB pCipherText,
ref string pszDescription,
ref DATA_BLOB pEntropy,
IntPtr pReserved,
ref CRYPTPROTECT_PROMPTSTRUCT pPrompt,
int dwFlags,
ref DATA_BLOB pPlainText);
// BLOB structure used to pass data to DPAPI functions.
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal struct DATA_BLOB
public int cbD
public IntPtr pbD
// Prompt structure to be used for required parameters.
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal struct CRYPTPROTECT_PROMPTSTRUCT
public int cbS
public int dwPromptF
public IntPtr hwndA
public string szP
// Wrapper for the NULL handle or pointer.
static private IntPtr NullPtr = ((IntPtr)((int)(0)));
// DPAPI key initialization flags.
private const int CRYPTPROTECT_UI_FORBIDDEN = 0x1;
private const int CRYPTPROTECT_LOCAL_MACHINE = 0x4;
/// &summary&
/// Initializes empty prompt structure.
/// &/summary&
/// &param name=&ps&&
/// Prompt parameter (which we do not actually need).
/// &/param&
private static void InitPrompt(ref CRYPTPROTECT_PROMPTSTRUCT ps)
ps.cbSize = Marshal.SizeOf(
typeof(CRYPTPROTECT_PROMPTSTRUCT));
ps.dwPromptFlags = 0;
ps.hwndApp = NullP
ps.szPrompt =
/// &summary&
/// Initializes a BLOB structure from a byte array.
/// &/summary&
/// &param name=&data&&
/// Original data in a byte array format.
/// &/param&
/// &param name=&blob&&
/// Returned blob structure.
/// &/param&
private static void InitBLOB(byte[] data, ref DATA_BLOB blob)
// Use empty array for null parameter.
if (data == null)
data = new byte[0];
// Allocate memory for the BLOB data.
blob.pbData = Marshal.AllocHGlobal(data.Length);
// Make sure that memory allocation was successful.
if (blob.pbData == IntPtr.Zero)
throw new Exception(
&Unable to allocate data buffer for BLOB structure.&);
// Specify number of bytes in the BLOB.
blob.cbData = data.L
// Copy data from original source to the BLOB structure.
Marshal.Copy(data, 0, blob.pbData, data.Length);
// Flag indicating the type of key. DPAPI terminology refers to
// key types as user store or machine store.
public enum KeyType { UserKey = 1, MachineKey };
// It is reasonable to set default key type to user key.
private static KeyType defaultKeyType = KeyType.UserK
/// &summary&
/// Calls DPAPI CryptProtectData function to encrypt a plaintext
/// string value with a user-specific key. This function does not
/// specify data description and additional entropy.
/// &/summary&
/// &param name=&plainText&&
/// Plaintext data to be encrypted.
/// &/param&
/// &returns&
/// Encrypted value in a base64-encoded format.
/// &/returns&
public static string Encrypt(string plainText)
return Encrypt(defaultKeyType, plainText, String.Empty,
String.Empty);
/// &summary&
/// Calls DPAPI CryptProtectData function to encrypt a plaintext
/// string value. This function does not specify data description
/// and additional entropy.
/// &/summary&
/// &param name=&keyType&&
/// Defines type of encryption key to use. When user key is
/// specified, any application running under the same user account
/// as the one making this call, will be able to decrypt data.
/// Machine key will allow any application running on the same
/// computer where data were encrypted to perform decryption.
/// Note: If optional entropy is specifed, it will be required
/// for decryption.
/// &/param&
/// &param name=&plainText&&
/// Plaintext data to be encrypted.
/// &/param&
/// &returns&
/// Encrypted value in a base64-encoded format.
/// &/returns&
public static string Encrypt(KeyType keyType, string plainText)
return Encrypt(keyType, plainText, String.Empty,
String.Empty);
/// &summary&
/// Calls DPAPI CryptProtectData function to encrypt a plaintext
/// string value. This function does not specify data description.
/// &/summary&
/// &param name=&keyType&&
/// Defines type of encryption key to use. When user key is
/// specified, any application running under the same user account
/// as the one making this call, will be able to decrypt data.
/// Machine key will allow any application running on the same
/// computer where data were encrypted to perform decryption.
/// Note: If optional entropy is specifed, it will be required
/// for decryption.
/// &/param&
/// &param name=&plainText&&
/// Plaintext data to be encrypted.
/// &/param&
/// &param name=&entropy&&
/// Optional entropy which - if specified - will be required to
/// perform decryption.
/// &/param&
/// &returns&
/// Encrypted value in a base64-encoded format.
/// &/returns&
public static string Encrypt(KeyType keyType,
string plainText,
string entropy)
return Encrypt(keyType, plainText, entropy, String.Empty);
/// &summary&
/// Calls DPAPI CryptProtectData function to encrypt a plaintext
/// string value.
/// &/summary&
/// &param name=&keyType&&
/// Defines type of encryption key to use. When user key is
/// specified, any application running under the same user account
/// as the one making this call, will be able to decrypt data.
/// Machine key will allow any application running on the same
/// computer where data were encrypted to perform decryption.
/// Note: If optional entropy is specifed, it will be required
/// for decryption.
/// &/param&
/// &param name=&plainText&&
/// Plaintext data to be encrypted.
/// &/param&
/// &param name=&entropy&&
/// Optional entropy which - if specified - will be required to
/// perform decryption.
/// &/param&
/// &param name=&description&&
/// Optional description of data to be encrypted. If this value is
/// specified, it will be stored along with encrypted data and
/// returned as a separate value during decryption.
/// &/param&
/// &returns&
/// Encrypted value in a base64-encoded format.
/// &/returns&
public static string Encrypt(KeyType keyType,
string plainText,
string entropy,
string description)
// Make sure that parameters are valid.
if (plainText == null) plainText = String.E
if (entropy == null) entropy = String.E
// Call encryption routine and convert returned bytes into
// a base64-encoded value.
return Convert.ToBase64String(
Encrypt(keyType,
Encoding.UTF8.GetBytes(plainText),
Encoding.UTF8.GetBytes(entropy),
description));
/// &summary&
/// Calls DPAPI CryptProtectData function to encrypt an array of
/// plaintext bytes.
/// &/summary&
/// &param name=&keyType&&
/// Defines type of encryption key to use. When user key is
/// specified, any application running under the same user account
/// as the one making this call, will be able to decrypt data.
/// Machine key will allow any application running on the same
/// computer where data were encrypted to perform decryption.
/// Note: If optional entropy is specifed, it will be required
/// for decryption.
/// &/param&
/// &param name=&plainTextBytes&&
/// Plaintext data to be encrypted.
/// &/param&
/// &param name=&entropyBytes&&
/// Optional entropy which - if specified - will be required to
/// perform decryption.
/// &/param&
/// &param name=&description&&
/// Optional description of data to be encrypted. If this value is
/// specified, it will be stored along with encrypted data and
/// returned as a separate value during decryption.
/// &/param&
/// &returns&
/// Encrypted value.
/// &/returns&
public static byte[] Encrypt(KeyType keyType,
byte[] plainTextBytes,
byte[] entropyBytes,
string description)
// Make sure that parameters are valid.
if (plainTextBytes == null) plainTextBytes = new byte[0];
if (entropyBytes == null) entropyBytes = new byte[0];
if (description == null) description = String.E
// Create BLOBs to hold data.
DATA_BLOB plainTextBlob = new DATA_BLOB();
DATA_BLOB cipherTextBlob = new DATA_BLOB();
DATA_BLOB entropyBlob = new DATA_BLOB();
// We only need prompt structure because it is a required
// parameter.
CRYPTPROTECT_PROMPTSTRUCT prompt =
new CRYPTPROTECT_PROMPTSTRUCT();
InitPrompt(ref prompt);
// Convert plaintext bytes into a BLOB structure.
InitBLOB(plainTextBytes, ref plainTextBlob);
catch (Exception ex)
throw new Exception(
&Cannot initialize plaintext BLOB.&, ex);
// Convert entropy bytes into a BLOB structure.
InitBLOB(entropyBytes, ref entropyBlob);
catch (Exception ex)
throw new Exception(
&Cannot initialize entropy BLOB.&, ex);
// Disable any types of UI.
int flags = CRYPTPROTECT_UI_FORBIDDEN;
// When using machine-specific key, set up machine flag.
if (keyType == KeyType.MachineKey)
flags |= CRYPTPROTECT_LOCAL_MACHINE;
// Call DPAPI to encrypt data.
bool success = CryptProtectData(ref plainTextBlob,
description,
ref entropyBlob,
IntPtr.Zero,
ref prompt,
ref cipherTextBlob);
// Check the result.
if (!success)
// If operation failed, retrieve last Win32 error.
int errCode = Marshal.GetLastWin32Error();
// Win32Exception will contain error message corresponding
// to the Windows error code.
throw new Exception(
&CryptProtectData failed.&, new Win32Exception(errCode));
// Allocate memory to hold ciphertext.
byte[] cipherTextBytes = new byte[cipherTextBlob.cbData];
// Copy ciphertext from the BLOB to a byte array.
Marshal.Copy(cipherTextBlob.pbData,
cipherTextBytes,
cipherTextBlob.cbData);
// Return the result.
return cipherTextB
catch (Exception ex)
throw new Exception(&DPAPI was unable to encrypt data.&, ex);
// Free all memory allocated for BLOBs.
if (plainTextBlob.pbData != IntPtr.Zero)
Marshal.FreeHGlobal(plainTextBlob.pbData);
if (cipherTextBlob.pbData != IntPtr.Zero)
Marshal.FreeHGlobal(cipherTextBlob.pbData);
if (entropyBlob.pbData != IntPtr.Zero)
Marshal.FreeHGlobal(entropyBlob.pbData);
/// &summary&
/// Calls DPAPI CryptUnprotectData to decrypt ciphertext bytes.
/// This function does not use additional entropy and does not
/// return data description.
/// &/summary&
/// &param name=&cipherText&&
/// Encrypted data formatted as a base64-encoded string.
/// &/param&
/// &returns&
/// Decrypted data returned as a UTF-8 string.
/// &/returns&
/// &remarks&
/// When decrypting data, it is not necessary to specify which
/// type of encryption key to use: user-specific or
/// machine- DPAPI will figure it out by looking at
/// the signature of encrypted data.
/// &/remarks&
public static string Decrypt(string cipherText)
return Decrypt(cipherText, String.Empty, out description);
/// &summary&
/// Calls DPAPI CryptUnprotectData to decrypt ciphertext bytes.
/// This function does not use additional entropy.
/// &/summary&
/// &param name=&cipherText&&
/// Encrypted data formatted as a base64-encoded string.
/// &/param&
/// &param name=&description&&
/// Returned description of data specified during encryption.
/// &/param&
/// &returns&
/// Decrypted data returned as a UTF-8 string.
/// &/returns&
/// &remarks&
/// When decrypting data, it is not necessary to specify which
/// type of encryption key to use: user-specific or
/// machine- DPAPI will figure it out by looking at
/// the signature of encrypted data.
/// &/remarks&
public static string Decrypt(string cipherText,
out string description)
return Decrypt(cipherText, String.Empty, out description);
/// &summary&
/// Calls DPAPI CryptUnprotectData to decrypt ciphertext bytes.
/// &/summary&
/// &param name=&cipherText&&
/// Encrypted data formatted as a base64-encoded string.
/// &/param&
/// &param name=&entropy&&
/// Optional entropy, which is required if it was specified during
/// encryption.
/// &/param&
/// &param name=&description&&
/// Returned description of data specified during encryption.
/// &/param&
/// &returns&
/// Decrypted data returned as a UTF-8 string.
/// &/returns&
/// &remarks&
/// When decrypting data, it is not necessary to specify which
/// type of encryption key to use: user-specific or
/// machine- DPAPI will figure it out by looking at
/// the signature of encrypted data.
/// &/remarks&
public static string Decrypt(string cipherText,
string entropy,
out string description)
// Make sure that parameters are valid.
if (entropy == null) entropy = String.E
return Encoding.UTF8.GetString(
Decrypt(Convert.FromBase64String(cipherText),
Encoding.UTF8.GetBytes(entropy),
out description));
/// &summary&
/// Calls DPAPI CryptUnprotectData to decrypt ciphertext bytes.
/// &/summary&
/// &param name=&cipherTextBytes&&
/// Encrypted data.
/// &/param&
/// &param name=&entropyBytes&&
/// Optional entropy, which is required if it was specified during
/// encryption.
/// &/param&
/// &param name=&description&&
/// Returned description of data specified during encryption.
/// &/param&
/// &returns&
/// Decrypted data bytes.
/// &/returns&
/// &remarks&
/// When decrypting data, it is not necessary to specify which
/// type of encryption key to use: user-specific or
/// machine- DPAPI will figure it out by looking at
/// the signature of encrypted data.
/// &/remarks&
public static byte[] Decrypt(byte[] cipherTextBytes,
byte[] entropyBytes,
out string description)
// Create BLOBs to hold data.
DATA_BLOB plainTextBlob = new DATA_BLOB();
DATA_BLOB cipherTextBlob = new DATA_BLOB();
DATA_BLOB entropyBlob = new DATA_BLOB();
// We only need prompt structure because it is a required
// parameter.
CRYPTPROTECT_PROMPTSTRUCT prompt =
new CRYPTPROTECT_PROMPTSTRUCT();
InitPrompt(ref prompt);
// Initialize description string.
description = String.E
// Convert ciphertext bytes into a BLOB structure.
InitBLOB(cipherTextBytes, ref cipherTextBlob);
catch (Exception ex)
throw new Exception(
&Cannot initialize ciphertext BLOB.&, ex);
// Convert entropy bytes into a BLOB structure.
InitBLOB(entropyBytes, ref entropyBlob);
catch (Exception ex)
throw new Exception(
&Cannot initialize entropy BLOB.&, ex);
// Disable any types of UI. CryptUnprotectData does not
// mention CRYPTPROTECT_LOCAL_MACHINE flag in the list of
// supported flags so we will not set it up.
int flags = CRYPTPROTECT_UI_FORBIDDEN;
// Call DPAPI to decrypt data.
bool success = CryptUnprotectData(ref cipherTextBlob,
ref description,
ref entropyBlob,
IntPtr.Zero,
ref prompt,
ref plainTextBlob);
// Check the result.
if (!success)
// If operation failed, retrieve last Win32 error.
int errCode = Marshal.GetLastWin32Error();
// Win32Exception will contain error message corresponding
// to the Windows error code.
throw new Exception(
&CryptUnprotectData failed.&, new Win32Exception(errCode));
// Allocate memory to hold plaintext.
byte[] plainTextBytes = new byte[plainTextBlob.cbData];
// Copy ciphertext from the BLOB to a byte array.
Marshal.Copy(plainTextBlob.pbData,
plainTextBytes,
plainTextBlob.cbData);
// Return the result.
return plainTextB
catch (Exception ex)
throw new Exception(&DPAPI was unable to decrypt data.&, ex);
// Free all memory allocated for BLOBs.
if (plainTextBlob.pbData != IntPtr.Zero)
Marshal.FreeHGlobal(plainTextBlob.pbData);
if (cipherTextBlob.pbData != IntPtr.Zero)
Marshal.FreeHGlobal(cipherTextBlob.pbData);
if (entropyBlob.pbData != IntPtr.Zero)
Marshal.FreeHGlobal(entropyBlob.pbData);
我们可以通过如下调用解密cookie:
Encrypted_value = DPAPI.Decrypt(Convert.ToBase64String(cookieContent))
现在关于模拟http报文请求的条件已经都准备好了。
使用System.net类库模拟http请求报文
HttpResponseParameter responseParameter1 = httpProvider.Excute(new HttpRequestParameter
Url = &http://user./p/ic2.s51/cgi-bin/feeds/feeds3_html_more?uin=&scope=0&view=1&daylist=&uinlist=&gid=&flag=1&filter=all&applist=all&refresh=0&aisortEndTime=0&aisortOffset=0&getAisort=0&aisortBeginTime=0&pagenum=2&externparam=basetime%3D%26pagenum%3D2%26dayvalue%3D0&firstGetGroup=0&icServerTime=0&mixnocache=0&scene=0&begintime=&count=10&dayspac=0&sidomain=cm.&useutf8=1&outputhtmlfeed=1&rd=0.0671&g_tk=& + getg_tk(GetCookieStr(&p_skey&).Split('=')[1].Replace(&;&, &&)),
IsPost = false,
Encoding = Encoding.UTF8,
Cookie = new HttpCookieType() { CookieCollection = addCookieToContainer(cookieSend) }
注意上面我使用了一个类库,也是园子里的一位大神写的,大家可以自己去下载。
现在,所有的难点我们都一一解决了。现在我们运行代码
OK,我们需要的数据都取到了。但是注意一个问题,取数据的时候只有我们登陆qq空间也就是qq空间的cookie有效的时候才可以取到数据。
现在我们可以将数据存储到数据。等待javascript调用wcf来读取数据
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致

我要回帖

更多关于 qq空间分享动态不显示 的文章

 

随机推荐