Dev Guide: js | css | HTML(DOM) WEBCAST .NET4 Lib Web.config-WCF MVC3-EF4.1 T-SQL-(2012)

OAuth 2.0 - 访问新浪、腾讯的资源服务器

I:访问资源服务器需要些什么?

访问资源服务器最最重要的前提条件就是你必须要有Access Token。而关于Access Token的取得原理已经在前面两篇(第1篇第2篇)随笔当中有介绍,在这里就略过介绍Access Token的获取方法了。

首先我们还是先看看新浪、腾讯他们的API文档上提供的参考内容。

新浪资源服务器API调用规范
image
也就是说新浪目前提供两种方式去调用API.
第一种是以QueryString参数的形式去调用,例子:
https://api.weibo.com/2/{API接口}?access_token={yourAccessToken}


第二种是往header里添加Authorization:OAuth2 {yourAccessToken}的形式去调用。

 

腾讯资源服务器API调用规范
image
根据腾讯方的文档资料来看!腾讯目前提供的API调用方法跟新浪的第一种方式类似,但没有提供类似新浪第二种把Access Token放到Header里面的方式(或许有但是我未能从文档站上搜索到具体要求)。接着GRD的腾讯又搞了几个属于自己的参数如:openid, clientip, oauth_version,微微地创新了一把!关于OpenID腾讯的介绍是OpenID可以唯一标识一个用户。在同一个应用下,同一个QQ号码的OpenID是相同的;但在不同应用下,同一个QQ号码可能有不同的OpenID。另外楼主可以推断这个oauth_version参数的设计能够证明目前腾讯接口不是很稳定,到时候估计会闹2.b/2.c/2.d/2.e/2.*,或者过一定时间后oauth.net推出3.0版本时,可以通过修改oauth_version去支持。

腾讯的例子:
https://open.t.qq.com/api/{API接口}?oauth_consumer_key={AppKey}&access_token={AccessToken}&openid={Openid}&clientip={ClientIP}&oauth_version=2.a&scope=all

在这说一下,腾讯的参数中客户端ip(clientip)可以不填(博主未确认应用部署上线后是否需要提供,因为应用都在开发期。。。)

 

 

ok,关于腾讯跟新浪的资源服务器API调用规范的重要部分已经介绍完毕了。接下来放送新浪腾讯API列表,因为调用他们的API不单单只是提供Access Token还需要根据接口的说明文档区确认是GET还是POST那些参数是可选的,那些参数是必选的之类。

新浪API接口地址腾讯API接口地址

附:腾讯接口Q&A新浪接口Q&A

II:访问资源服务器API示例

首先下载dotNetDR_OAuth2程序集 codeplex下载地址介绍

然后新建一个MVC3的应用程序!将刚刚下载的OAuth2组件引用进来。 (WebForm示例
image

接着在项目代码文件里添加你的AppKey, AppSecret
image

然后再Home控制器的Index Action加上跳转到新浪和腾讯微博授权页面的超级链接。

HomeController.cs:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Dynamic;

//引入dotNetDR_OAuth2组件命名空间
using dotNetDR_OAuth2;
using dotNetDR_OAuth2.AccessToken;

namespace dotNetDR_OAuth2.Sample.MVC.Controllers
{
public class HomeController : Controller
{
//获取新浪、腾讯的IAuthorizationCodeBase接口实例
   private IAuthorizationCodeBase sina = AccessTokenFactory.Create(DefaultAppConfigs.Sina);
private IAuthorizationCodeBase tencent = AccessTokenFactory.Create(DefaultAppConfigs.Tencent);

public ActionResult Index()
{
dynamic model = new ExpandoObject();

//生成主机头例如:http://www.yourhost.com:8081 (注:默认80端口则不会显示:80)
var hostPath = AccessTokenToolkit.GenerateHostPath(Request.Url);

//定义授权成功后返回的url地址
    var sinaRedirectUrl = hostPath + Url.Action("Index", "Sina");
var tencentRedirectUrl = hostPath + Url.Action("Index", "Tencent");

//设置超级链接
            model.SinaLink = sina.GenerateCodeUrl(sinaRedirectUrl);
            model.TencentLink = tencent.GenerateCodeUrl(tencentRedirectUrl);

return View(model);
}

public ActionResult About()
{
return View();
}
}
}

 

然后Index.cshtml:


@{
ViewBag.Title = "Home Page";
}
@model dynamic

<h2>dotNetDR_OAuth2 微博API访问组件示例</h2>
<div>
@if (Model != null)
{
<a href="@Model.SinaLink"><img src="http://www.cnblogs.com/Content/Images/xlwb.gif" />新浪微博登陆</a><text>|</text>
<a href="@Model.TencentLink"><img src="http://www.cnblogs.com/Content/Images/txwb.gif" />腾讯微博登陆</a>
}
else
{
<h3>Error: Model没有值</h3>
}
</div>

image

上图是效果图

 

接着我们建立各自的实现:SinaController, TencentController.

新浪部分 - SinaController.cs:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
//导入组件命名空间
using dotNetDR_OAuth2;
using dotNetDR_OAuth2.AccessToken;
using dotNetDR_OAuth2.APIs.Providers.Sina;

namespace dotNetDR_OAuth2.Sample.MVC.Controllers
{
public class SinaController : Controller
{
private IAuthorizationCodeBase _authCode = AccessTokenFactory.Create(DefaultAppConfigs.Sina);

public ActionResult Index(string code)
{
if (Session["accessToken"] == null)
{
if (!string.IsNullOrEmpty(code))
{
var redirectUrl = AccessTokenToolkit.GenerateHostPath(Request.Url) + Url.Action("Index");

var accessToken = _authCode.GetResult(_authCode.GenerateAccessTokenUrl(redirectUrl, code));

if (Session["accessToken"] != null)
{
Session.Remove("accessToken");
}

Session.Add("accessToken", accessToken);

var hasAccessToken = new object();
return View(hasAccessToken);
}
else
{
return GotoIndex();
}
}

return View(new object());
}

public ActionResult ShowUserInfo()
{
if (Session["accessToken"] == null)
{
return GotoIndex();
}

var accessTokenObj = Session["accessToken"] as dynamic;
var uid = accessTokenObj.uid;
var accessToken = accessTokenObj.access_token;

var model = SinaApi.CallGet("users/show.json?uid=" + uid, accessToken);

SinaError err;

if (!SinaApi.HasError(model, out err))
{
return View(model);
}
else
{
Session["err"] = err;
return RedirectToAction("Error");
}
}

public ActionResult PublishMsg()
{
if (Session["accessToken"] == null)
{
return GotoIndex();
}

var accessTokenObj = Session["accessToken"] as dynamic;
var uid = accessTokenObj.uid;
var accessToken = accessTokenObj.access_token;

var msg = "Time: " + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss.fffff") + ": 这是一条来自dotNetDR_OAuth2组件发出的1条测试微博信息!";
var formData = new Dictionary<string, string>();
formData.Add("status", Server.UrlEncode(msg));

SinaError err;

var result = SinaApi.CallPost("statuses/update.json", accessToken, formData);
if (!SinaApi.HasError(result, out err))
{
return View();
}
else
{
Session["err"] = err;
return RedirectToAction("Error");
}
}

public ActionResult Error()
{
var err = Session["err"] as SinaError;

return View(err);
}


#region NonAction
[NonAction]
private ActionResult GotoIndex()
{
return RedirectToAction("Index", "Home");
}
#endregion
}
}

 

Index.cshtml:


@{
ViewBag.Title = "Index";
}

@model object

<h2>操作</h2>
<p>@Html.ActionLink("返回", "Index", "Home")</p>
@if (Model != null)
{
@Html.ActionLink("显示用户信息", "ShowUserInfo") <text> | </text>
@Html.ActionLink("发送测试微博", "PublishMsg")
}

 

PublishMsg.cshtml:


@{
ViewBag.Title = "PublishMsg";
}

<h2>发送成功</h2>

 

ShowUserInfo.cshtml:


@{
ViewBag.Title = "ShowUserInfo";
}

<h2>用户:@Model.screen_name</h2>
<p>
用户UID: @Model.id<br />
用户昵称: @Model.screen_name<br />
友好显示名称: @Model.name<br />
用户所在地区ID: @Model.province<br />
用户所在城市ID: @Model.city<br />
用户所在地: @Model.location<br />
用户描述: @Model.description<br />
用户博客地址: @Model.url<br />
用户头像地址: @Model.profile_image_url @MvcHtmlString.Create(string.Format("<img src='{0}' />", Model.profile_image_url))<br />
用户的个性化域名: @Model.domain<br />
性别(m:男、f:女、n:未知): @Model.gender<br />
粉丝数: @Model.followers_count<br />
关注数: @Model.friends_count<br />
微博数: @Model.statuses_count<br />
收藏数: @Model.favourites_count<br />
创建时间: @Model.created_at<br />
当前登录用户是否已关注该用户: @Model.following<br />
是否允许所有人给我发私信: @Model.allow_all_act_msg<br />
是否允许带有地理信息: @Model.geo_enabled<br />
是否是微博认证用户,即带V用户: @Model.verified<br />
是否允许所有人对我的微博进行评论: @Model.allow_all_comment<br />
用户大头像地址: @Model.avatar_large @MvcHtmlString.Create(string.Format("<img src='{0}' />", @Model.avatar_large))<br />
认证原因: @Model.verified_reason<br />
该用户是否关注当前登录用户: @Model.follow_me<br />
用户的在线状态,0:不在线、1:在线: @Model.online_status<br />
用户的互粉数: @Model.bi_followers_count<br />
</p>

 

Error.cshtml:


@{
ViewBag.Title = "Error";
}

@model dotNetDR_OAuth2.APIs.Providers.Sina.SinaError

<h2>Error</h2>
<p>
error_code: @Model.error_code<br />
error: @Model.error<br />
request: @Model.request<br />
</p>

 

 

 

腾讯部分 - TencentController.cs:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

using dotNetDR_OAuth2;
using dotNetDR_OAuth2.AccessToken;
using dotNetDR_OAuth2.APIs.Providers.Tencent;

namespace dotNetDR_OAuth2.Sample.MVC.Controllers
{
public class TencentController : Controller
{
private IAuthorizationCodeBase _authCode = AccessTokenFactory.Create(DefaultAppConfigs.Tencent);

//
// GET: /Tencent/
public ActionResult Index(string code, string openid, string openkey)
{
if (Session["accessToken"] == null)
{
if (!string.IsNullOrEmpty(code))
{
var redirectUrl = AccessTokenToolkit.GenerateHostPath(Request.Url) + Url.Action("Index");

var accessToken = _authCode.GetResult(_authCode.GenerateAccessTokenUrl(redirectUrl, code));

if (Session["accessToken"] != null)
{
Session.Remove("accessToken");
}

accessToken.openid = openid; //注意GRD腾讯自家的微创新
accessToken.openkey = openkey; //注意GRD腾讯自家的微创新

Session.Add("accessToken", accessToken);

var hasAccessToken = new object();
return View(hasAccessToken);
}
else
{
return GotoIndex();
}
}

return View(new object());
}

public ActionResult ShowUserInfo()
{
if (Session["accessToken"] == null)
{
return GotoIndex();
}

var accessTokenObj = Session["accessToken"] as dynamic;
var uid = accessTokenObj.name;
var accessToken = accessTokenObj.access_token;
var openid = accessTokenObj.openid;

var model = TencentApi.CallGet("user/info?format=json", accessToken, openid);

TencentError err;

if (!TencentApi.HasError(model, out err))
{
var realModel = model.data;
return View(realModel);
}
else
{
Session["err"] = err;
return RedirectToAction("Error");
}
}

public ActionResult PublishMsg()
{
if (Session["accessToken"] == null)
{
return GotoIndex();
}

var accessTokenObj = Session["accessToken"] as dynamic;
var uid = accessTokenObj.name;
var accessToken = accessTokenObj.access_token;
var openid = accessTokenObj.openid;

var msg = "Time: " + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss.fffff") + ": 这是一条来自dotNetDR_OAuth2组件发出的1条测试微博信息!";
var formData = new Dictionary<string, string>();
formData.Add("content", Server.UrlEncode(msg));

TencentError err;

var result = TencentApi.CallPost("t/add?format=json", accessToken, openid, formData);
if (!TencentApi.HasError(result, out err))
{
return View();
}
else
{
Session["err"] = err;
return RedirectToAction("Error");
}
}

public ActionResult Error()
{
var err = Session["err"] as TencentError;

return View(err);
}

#region NonAction
[NonAction]
private ActionResult GotoIndex()
{
return RedirectToAction("Index", "Home");
}
#endregion
}
}

 

Index.cshtml:


@{
ViewBag.Title = "Index";
}
@model object

<h2>操作</h2>
<p>@Html.ActionLink("返回", "Index", "Home")</p>
@if (Model != null)
{
@Html.ActionLink("显示用户信息", "ShowUserInfo") <text> | </text>
@Html.ActionLink("发送测试微博", "PublishMsg")
}

 

PublishMsg.cshtml:


@{
ViewBag.Title = "PublishMsg";
}

<h2>发送成功</h2>

 

ShowUserInfo.cshtml:


@{
ViewBag.Title = "ShowUserInfo";
}

<h2>用户昵称: @Model.nick</h2>
<p>
出生天: @Model.birth_day <br />
出生月: @Model.birth_month <br />
出生年: @Model.birth_year <br />
城市id: @Model.city_code <br />
国家id: @Model.country_code <br />
邮箱: @Model.email <br />
听众数: @Model.fansnum <br />
收藏数: @Model.favnum <br />
头像url: @Model.head @MvcHtmlString.Create(string.Format("<img src=\"{0}/50\" />", @Model.head)) <br />
家乡所在城市id: @Model.homecity_code <br />
家乡所在国家id: @Model.homecountry_code <br />
个人主页: @Model.homepage <br />
家乡所在省id: @Model.homeprovince_code <br />
家乡所在城镇id: @Model.hometown_code <br />
收听的人数: @Model.idolnum <br />
行业id: @Model.industry_code <br />
个人介绍: @Model.introduction <br />
是否企业机构: @Model.isent <br />
是否在当前用户的黑名单中,0-不是,1-是: @Model.ismyblack <br />
是否是当前用户的听众,0-不是,1-是: @Model.ismyfans <br />
是否是当前用户的偶像,0-不是,1-是: @Model.ismyidol <br />
是否实名认证,0-老用户,1-已实名认证,2-未实名认证: @Model.isrealname <br />
是否认证用户: @Model.isvip <br />
所在地: @Model.location <br />
互听好友数: @Model.mutual_fans_num <br />
用户帐户名: @Model.name <br />
用户唯一id,与name相对应: @Model.openid <br />
地区id: @Model.province_code <br />
注册时间: @Model.regtime <br />
是否允许所有人给当前用户发私信,0-仅有偶像,1-名人+听众,2-所有人: @Model.send_private_flag <br />
用户性别,1-男,2-女,0-未填写: @Model.sex <br />
发表的微博数: @Model.tweetnum <br />
认证信息: @Model.verifyinfo <br />
</p>

 

Error.cshtml:


@{
ViewBag.Title = "Error";
}
@model dotNetDR_OAuth2.APIs.Providers.Tencent.TencentError

<h2>Error</h2>
<p>
ret: @Model.ret<br />
errcode: @Model.errcode<br />
msg: @Model.msg<br />
----------------------<br />
errcode=1 无效TOKEN,被吊销<br />
errcode=2 请求重放<br />
errcode=3 access_token不存在<br />
errcode=4 access_token超时<br />
errcode=5 oauth 版本不对<br />
errcode=6 oauth 签名方法不对<br />
errcode=7 参数错<br />
errcode=8 处理失败<br />
errcode=9 验证签名失败<br />
errcode=10 网络错误<br />
errcode=11 参数长度不对<br />
errcode=12 处理失败<br />
errcode=13 处理失败<br />
errcode=14 处理失败<br />
errcode=15 处理失败<br />
</p>

 

在这里重复上一下效果图吧!

image

image

发送微博的效果我就不贴了!!

 

 

这里附上一个各位OAuth开发者或许需要的流程图(专家请尽情喷小菜)

image

visio文件下载

 

III:dotNetDR_OAuth2 组件介绍

在上一节里面的代码!大家都可以看到这个组件已经隐藏了System.Net.HttpWebRequest, System.Net.HttpWebResponse这些细节,而且返回的值都是dynamic类型的,这样一下。我们就仅需要对这新浪或者腾讯的API文档来逐步调试了,因为博主不可能在组件里把每一个接口返回值得都定义成一个C#类文件:



如果都定义成claas我太累了,所以用.NET 4.0 提供的dynamic算了,更加具体内容我打算另外用一遍随笔去介绍!!转载的请声明及保留好出处!!

组件作者:博客园dotNetDR_ http://www.cnblogs.com/highend/

IV:Access Token的过期时间

新浪

image

 

腾讯

image

 

V:示例项目代码

注意:当你在测试环境下时,必须要把windows系统的hosts文件添加好具体的域名地址指向你本机,例如博主的:

image

 

 

然后就是需要打开dotNetDR_OAuth2.Sample.MVC.csproj手动更改IIS路径

image

代码下载

 

广告:OAuth2.0 组件讨论群:108441512 询问C#以外的OAuth 2.0 sdk同学勿入!谢谢合作。

本文到此结束!如果觉得文章对你帮助很大的,请点击[推荐]~谢谢。

posted @ 2012-07-10 10:06  dotNetDR_  阅读(7014)  评论(19编辑  收藏  举报