新浪,腾迅,网易微博OAuth统一认证接口实现

看到国内微博兴起.各大门微博都提供了统一的OAuth认证

开始有想法做一个统一访问接口了.到时候就可以利用各大门户的注册用户来为我们服务

从而也使得最终用户不用每个网站都要去注册一个帐号.还有安全性的问题了

从开始一时兴趣.到专心的架构,把博客园有关OAuth认证的文章都看了一下.

从不知.到了解,到熟悉再到自己造轮子.

利用休息时间.自己终于写好了国内四大门户的三大微博接口.

由于搜狐的文档还没有看.用一般的方式去认证老是失败.等有时间再完工

现在只有新浪,腾迅,网易的认证成功了

接下来.先上图.有图有真相.这是我的架构图

项目地址 http://weibooauth.codeplex.com/ (源代码在这里下载)
欢迎有兴趣的人事进行一起研究.有的话就注册一个codeplex帐号.一起进行开发liuju150@gmail.com
 

OAuth项目写了几个公共接口分别是
IOAuthConfig这个是得到web.config的配置信息接口

namespace OAuth
{
    public interface IOAuthConfig
    {
        /// <summary>
        /// 得到AppKey
        /// </summary>
        /// <returns></returns>
        string GetAppKey();

        /// <summary>
        /// 得到AppSecret
        /// </summary>
        /// <returns></returns>
        string GetAppSecret();

        /// <summary>
        /// 得到回调URL
        /// </summary>
        /// <returns></returns>
        Uri GetCallBackURI();

        /// <summary>
        /// 得到请求类型
        /// GET,POST,HEADER
        /// </summary>
        /// <returns></returns>
        OAuthEnum.RequestType GetRequestType();

        
    }
}

IOAuthMode这个接口得对OAuth认证的参数接口 这里接口比较多

namespace OAuth
{
    public interface IOAuthMode
    {
        /// <summary>
        /// 得到回调地址
        /// </summary>
        /// <returns></returns>
        OAuthParameter GetOAuthCallBack();

        /// <summary>
        /// 得到申请的ConsumerKey
        /// </summary>
        /// <returns></returns>
        OAuthParameter GetOAuthConsumerKey();

        /// <summary>
        /// 设置随机字符串
        /// </summary>
        /// <param name="OAuthNoncd"></param>
        void SetOAuthNonce(string OAuthNonceString);

        /// <summary>
        /// 得到随机字符串
        /// </summary>
        /// <returns></returns>
        OAuthParameter GetOAuthNonce();

        /// <summary>
        /// 得到签名方式
        /// </summary>
        /// <returns></returns>
        OAuthParameter GetOAuthSignatureMethod();

        /// <summary>
        /// 设置时间戳
        /// </summary>
        /// <param name="OAuthTimeStamp"></param>
        void SetOAuthTimeStamp(string OAuthTimeStampString);

        /// <summary>
        /// 得到时间戳
        /// </summary>
        /// <returns></returns>
        OAuthParameter GetOAuthTimeStamp();

        /// <summary>
        /// 得到OAuth版本
        /// </summary>
        /// <returns></returns>
        OAuthParameter GetOAuthVersion();

        /// <summary>
        /// 设置签名字符串
        /// </summary>
        void SetOAuthSignature(string OAuthSignatureString);

        /// <summary>
        /// 得到签名字符串
        /// </summary>
        /// <returns></returns>
        OAuthParameter GetOAuthSignature();

        /// <summary>
        /// 设置OAuthToken
        /// </summary>
        void SetOAuthToken(OAuthParameter OAuthToken);

        /// <summary>
        /// 得到OAuthToken
        /// </summary>
        /// <returns></returns>
        OAuthParameter GetOAuthToken();

        /// <summary>
        /// 设置OAuthTokenSecret
        /// </summary>
        void SetOAuthTokenSecret(OAuthParameter OAuthTokenSecret);

        /// <summary>
        /// 得到OAuthTokenSecret
        /// </summary>
        /// <returns></returns>
        OAuthParameter GetOAuthTokenSecret();

        /// <summary>
        /// 设置OAuthVerifier
        /// </summary>
        /// <param name="OAuthVerifier"></param>
        void SetOAuthVerifier(OAuthParameter OAuthVerifier);

        /// <summary>
        /// 得到OAuthVerifier
        /// </summary>
        /// <returns></returns>
        OAuthParameter GetOAuthVerifier();

        /// <summary>
        /// 得到接口提供商
        /// </summary>
        /// <returns></returns>
        OAuthEnum.OAuthInterface GetOAuthInterface();
    }
}

IOAuthRequestURL这个接口是对请求地址的接口

namespace OAuth
{
    public interface IOAuthRequestURL
    {
        /// <summary>
        /// 获取未授权的Request Token
        /// </summary>
        /// <returns></returns>
        Uri GetRequestTokenURL();

        /// <summary>
        /// 请求用户授权Token
        /// </summary>
        /// <returns></returns>
        Uri GetRequestOAuthTokenURL();

        /// <summary>
        /// 获取授权过的Access Token
        /// </summary>
        /// <returns></returns>
        Uri GetRequestAccessTokenURL();
    }
}

然后各个微博都实现这里几个接口(看到图片就知道.每个微博都实现了这三个接口)

然后OAuthBase就是实现OAuth认证.

拿新浪来说的OAuth认证反正都是经过三个步骤

第一次.请求RequestToken

得到OAuthToken和OAuthTokenSecret

第二步.用OAuthToken去认证得到OAuthVerifier

第三步就是得到真正的OAuthToken和OAuthTokenSecret

详细实现(新浪)

第一步

oauth_callback(回调地址,要UrlEncoding)

oauth_consumer_key(在新浪申请到的consumer_key)

oauth_nonce(随机字符串,听说腾迅要小于32位.我用GUID)

oauth_signature_method(签名方式,现在都是HMAC-SHA1)

oauth_timestamp(时间戳,1970-1-1 0:0:0到现在时间的整型值)

oauth_version(OAuth版本,新浪,腾迅为1.0a,网易为1.0)(目前)

生成参数字符串.用上面的参数 格式为:参数名1=参数值1&参数名2=参数值2,和URL一样.你懂的

然后string.format("{0}&{1}&{2}",{1:请求方式GET,POST},{2:请求地址UrlEncode(http://api.t.sina.com.cn/oauth/request_token)},{3:UrlEncode(参数字符串)})

这个就是签名的BaseString,然后用你申请得到的AppSecret+"&"为KEY,来进行签名生成签名字符串.然后也要对其UrlEncode

然后生成为签名字符串为oauth_signature的值

然后生成请求URL(GET)

http://api.t.sina.com.cn/oauth/request_token?参数名1=参数值1&参数名2=参数值2

这里和生成参数字符串一样.只是要加上oauth_signature

这里就是请求的URL.然后会得到
oauth_token=ce9cc416a9ad8f37feba547541f81ec9&oauth_token_secret=a6966e6898480428574f04f768da1249

这样第一步RequestToken就完成了

第二步

http://api.t.sina.com.cn/oauth/authorize?oauth_token=ce9cc416a9ad8f37feba547541f81ec9
打开这个地下进行用户认证.这里的oauth_token为第一步得到的oauth_token

服务器返回oauth_token=ce9cc416a9ad8f37feba547541f81ec9&oauth_verifier=1234567

第三步.

用第一步的参数加上第二步得到的
 oauth_token和oauth_verifier

得到新的签名字条串,然后用AppSecret+"&"+oauth_token_secret(第一步得到的)为KEY对

然后再进行签名(注意这里的oauth_nonce,oauth_timestamp要重新生成)

得到新的oauth_signature

然后像第一步一样生成URL进行请求.

得到真正的oauth_token和oauth_token_secret

然后就可以用这个调用相关接口了

    protected void imgBtnSina_Click(object sender, ImageClickEventArgs e)
    {
        SinaOAuthMode OAuthMode = new SinaOAuthMode();
        OAuthBase Base = new OAuthBase(new SinaOAuthRequestURL(), new SinaOAuthConfig(), OAuthMode);
        OAuthMode = (SinaOAuthMode)Base.RequestToken();
        string res = string.Format("{0}:{1}&{2}:{3}", OAuthMode.GetOAuthToken().ParameterName, OAuthMode.GetOAuthToken().ParameterValue, OAuthMode.GetOAuthTokenSecret().ParameterName, OAuthMode.GetOAuthTokenSecret().ParameterValue);
        labMsg.Text = res;
        string RequestOAuthTokenURL = Base.GetAccessTokenURL().ToString();
        Session["OAuthMode"] = OAuthMode;
        Page.ClientScript.RegisterStartupScript(GetType(), "W_CallBack", "<script language=\"javascript\" type=\"text/javascript\">imgBtnClick('" + RequestOAuthTokenURL + "')</script>");
    }

点击按钮

    private void SinaCallBack()
    {
        SinaOAuthMode Mode = (SinaOAuthMode)Session["OAuthMode"];
        Mode.SetOAuthToken(new OAuthParameter("oauth_token", Request.QueryString["oauth_token"]));
        Mode.SetOAuthVerifier(new OAuthParameter("oauth_verifier", Request.QueryString["oauth_verifier"]));
        OAuthBase Base = new OAuthBase(new SinaOAuthRequestURL(), new SinaOAuthConfig(), Mode);
        Mode = (SinaOAuthMode)Base.RequestAccessToken();
        Session["OAuthMode"] = Mode;
    }

回调页面

<?xml version="1.0"?>
<configuration>
    <configSections>
        <sectionGroup name="SinaSectionGroup">
            <section name="SinaSection" type="System.Configuration.NameValueSectionHandler,System"/>
        </sectionGroup>
        <sectionGroup name="QQSectionGroup">
            <section name="QQSection" type="System.Configuration.NameValueSectionHandler,System"/>
        </sectionGroup>
        <sectionGroup name="WangYiSectionGroup">
            <section name="WangYiSection" type="System.Configuration.NameValueSectionHandler,System"/>
        </sectionGroup>
        <sectionGroup name="SohuSectionGroup">
            <section name="SohuSection" type="System.Configuration.NameValueSectionHandler,System"/>
        </sectionGroup>
    </configSections>
    <SinaSectionGroup>
        <SinaSection>
            <add key="AppKey" value="*************"/>
            <add key="AppSecret" value="**************************"/>
            <add key="CallBackURI" value="http://localhost/OAuthWeb/OAuthCallBack.aspx?Type=Sina"/>
            <add key="RequestType" value="GET"/>
        </SinaSection>
    </SinaSectionGroup>
    <QQSectionGroup>
        <QQSection>
            <add key="AppKey" value="*************"/>
            <add key="AppSecret" value="**************************"/>
            <add key="CallBackURI" value="http://localhost/OAuthWeb/OAuthCallBack.aspx?Type=QQ"/>
            <add key="RequestType" value="GET"/>
        </QQSection>
    </QQSectionGroup>
    <WangYiSectionGroup>
        <WangYiSection>
            <add key="AppKey" value="*************"/>
            <add key="AppSecret" value="**************************"/>
            <add key="CallBackURI" value="http://localhost/OAuthWeb/OAuthCallBack.aspx?Type=WangYi"/>
            <add key="RequestType" value="GET"/>
        </WangYiSection>
    </WangYiSectionGroup>
    <SohuSectionGroup>
        <SohuSection>
            <add key="AppKey" value="*************"/>
            <add key="AppSecret" value="**************************"/>
            <add key="CallBackURI" value="http://localhost/OAuthWeb/OAuthCallBack.aspx?Type=Sohu"/>
            <add key="RequestType" value="GET"/>
        </SohuSection>
    </SohuSectionGroup>
    <system.web>
        <compilation debug="true" targetFramework="4.0"/>
    </system.web>
</configuration>
web.config
posted @ 2011-05-14 17:11  Giant150  阅读(16006)  评论(90编辑  收藏  举报