http://stackoverflow.com/questions/12499602/body-joints-angle-using-kinect?rq=1

新浪微博跟update相关的api已经挂了很多天了一直没有恢复正常,返回错误:40070 Error limited application access api!,新浪开放平台的论坛里n多的人都在等这个恢复,新浪官方也相当的恶心出问题了连个公告都没有,既不说什么原因又不说什么时候能恢复,。还是有版主说是api正在升级礼拜1恢复正常今天都礼拜2了还是不行。基于这个原因我的android版的新浪微博客户端已经停工好几天了,刚好是跟update相关的一些功能。

客户端开发不成了,就自己做做服务端程序,提供类似新浪微博rest api服务, api其实说简单也很简单了,无法是通过链接对外提供json或者xml格式的数据和接收外部提供的数据进去相应的存储、删除、更新等操作。过程中碰到的最麻烦的问题就是OAuth认证功能了,在做android版的新浪微博客户端时候也花了蛮长的时间对OAuth认证进行研究,在客户端原先是采用了oauth-signpost开源项目,后来由于某些原因就放弃了这个开源类库,自己重新写了OAuth认证部分的实现, 现在做服务端的OAuth认证,其实有过做客户端的经验做服务端也差不多,简单的说无非是客户端对参数字符串进行签名然后把签名值传输到服务端,服务端也对同样对参数字符串进行签名,把从客户端传过来的签名值进去比较,简单的说就这么个过程,具体实现肯定比这个要复杂多了,不明真相的同学可以google一下OAuth进行深入的学习研究了。

服务端程序用asp.net和C#编写了而非java,理由很简单本人对.net更加熟悉。由于想快速的实现效果采用了oauth-dot-net开源项目并没有全部自己写。

一、首先新建名为Rest Api的ASP.NET Web应用程序,然后添加 oauth-dot-net开源项目相关的几个dll(Castle.Core.dll、Castle.MicroKernel.dll、Castle.Windsor.dll、CommonServiceLocator.WindsorAdapter.dll、Microsoft.Practices.ServiceLocation.dll、OAuth.Net.Common.dll、OAuth.Net.Components.dll、OAuth.Net.ServiceProvider.dll)。

二、在Web.config文件里添加相应的配置,具体可以参考OAuth.Net.Examples.EchoServiceProvider项目,然后在Global.asax.cs添加如下代码:


public override void Init()
        {
            IServiceLocator injector =
                new WindsorServiceLocator(
                    new WindsorContainer(
                        new XmlInterpreter(
                            new ConfigResource("oauth.net.components"))));             ServiceLocator.SetLocatorProvider(() => injector);

}

接下来是比较重要,就是request_token、authorize、access_token的实现,OAuth认证实现的几个过程,不理解可以看android开发我的新浪微博客户端-OAuth篇(2.1) ,具体代码实现很多是参考OAuth.Net.Examples.EchoServiceProvider示例项目。

三、 首先新建ConsumerStore.cs类,用来存储Consumer信息,由于测试项目所以存储在内存中并没有考虑保存到数据库,真实项目的时候请把相应的Consumer信息保存到数据库中。Consumer信息对应新浪微博其实就是应用的App Key和App Secret,当开发者在新浪微博建一个新的应用获取App Key和App Secret,所以完整的应该还需要一个开发一个提供给第三方开发者申请获取App Key和App Secret的功能页面,这里就不具体实现,直接在代码里写死了一个名为测试应用的Consumer,App Key:2433927322,App Secret:87f042c9e8183cbde0f005a00db1529f,这个提供给客户端测试用。 具体代码如下:


public sealed class ConsumerStore : InMemoryConsumerStore, IConsumerStore
    {
        internal static readonly IConsumer FixedConsumer = new OAuthConsumer("2433927322", "87f042c9e8183cbde0f005a00db1529f", "测试应用", ConsumerStatus.Valid);         public ConsumerStore()
        {
            this.ConsumerDictionary.Add(
                ConsumerStore.FixedConsumer.Key, 
                ConsumerStore.FixedConsumer);
        }         public override bool Add(IConsumer consumer)
        {
            throw new NotSupportedException("Consumers cannot be added to this store--it is fixed.");
        }         public override bool Contains(string consumerKey)
        {
            return ConsumerStore.FixedConsumer.Key.Equals(consumerKey);
        }         public override bool Update(IConsumer consumer)
        {
            throw new NotSupportedException("Consumers cannot be updated in this store--it is fixed.");
        }         public override bool Remove(IConsumer consumer)
        {
            throw new NotSupportedException("Consumers cannot be removed from this store--it is fixed.");
        }

}

四、接下来就是request_token功能,新建RequestTokenHandler.cs ,这个是OAuth.Net.ServiceProvider.RequestTokenHandler子类,并且是httpHandlers所以需要在Web.config中添加httpHandlers配置,这个用来接收客户端程序的请求,返回给客户端程序Request Token和Request Secret用,具体代码如下:


public sealed class RequestTokenHandler : OAuth.Net.ServiceProvider.RequestTokenHandler
    {   
        protected override void IssueRequestToken(HttpContext httpContext, OAuthRequestContext requestContext)
        {
            //产生RequestToken
            IRequestToken token = this.GenerateRequestToken(httpContext, requestContext);             requestContext.RequestToken = token;
            Uri callbackUri;
            if (Uri.TryCreate(requestContext.Parameters.Callback, UriKind.Absolute, out callbackUri))
            {
                if (!ServiceProviderContext.CallbackStore.ContainsCallback(token))
                {
                    //保存Callback地址了
                    ServiceProviderContext.CallbackStore.AddCallback(token, callbackUri);
                }
            }
            else
                OAuthRequestException.ThrowParametersRejected(new string[] { Constants.CallbackParameter }, "Not a valid Uri.");             //把token.Token和token.Secret输出到客户端,
            requestContext.ResponseParameters[Constants.TokenParameter] = token.Token;
            requestContext.ResponseParameters[Constants.TokenSecretParameter] = token.Secret;
        }         protected override IRequestToken GenerateRequestToken(HttpContext httpContext, OAuthRequestContext requestContext)
        {
            
            return ServiceProviderContext.TokenGenerator.CreateRequestToken(requestContext.Consumer, requestContext.Parameters);
        }

}

五、 接着是authorize功能,新建名为authorize.aspx的页面,用来给用户输入账号和密码进行授权的页面,这个页面很简单具体如下图,在这个页面中获取用户输入的账户和密码跟数据库中存储的用户账号和密码进行验证,如果验证通过返回之前客户端提供的callback地址,并且给这个地址添加一个校验码,具体代码如下:


public partial class authorize : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {         }         protected void Button1_Click(object sender, EventArgs e)
        {
            if (loginName.Text == "test" && password.Text == "123")
            {
                string toke = Request.Params["oauth_token"];
                IRequestToken tk = ServiceProviderContext.TokenStore.GetRequestToken(toke);
                Uri callback = ServiceProviderContext.CallbackStore.GetCalback(tk);
                string oauth_verifier = ServiceProviderContext.VerificationProvider.Generate(tk);
                Response.Redirect(callback.ToString() + "?oauth_verifier=" + oauth_verifier);
            }
            
        }

}

六、接下来就是access_token功能,新建AccessTokenHandler.cs , 这个是OAuth.Net.ServiceProvider.AccessTokenHandler子类,并且是httpHandlers所以需要在Web.config中添加httpHandlers配置,这个用来接收客户端程序的请求,返回给客户端程序Access Token和Access Secret用,具体代码如下:


public sealed class AccessTokenHandler : OAuth.Net.ServiceProvider.AccessTokenHandler
    {
        protected override void IssueAccessToken(HttpContext httpContext, OAuthRequestContext requestContext)
        {
            //产生access token
            IAccessToken accessToken = this.GenerateAccessToken(httpContext, requestContext);             accessToken.Status = TokenStatus.Authorized;             // 把accessToken和accessSecret输出到客户端,
            requestContext.ResponseParameters[Constants.TokenParameter] = accessToken.Token;
            requestContext.ResponseParameters[Constants.TokenSecretParameter] = accessToken.Secret;
        }         protected override IAccessToken GenerateAccessToken(HttpContext httpContext,  OAuthRequestContext requestContext)
        {
            return ServiceProviderContext.TokenGenerator.CreateAccessToken(requestContext.Consumer, requestContext.RequestToken);
        }
    } public class TokenGenerator : ITokenGenerator
    {
        internal static readonly IRequestToken FixedRequestToken = new OAuthRequestToken("requestkey",
            "requestsecret",
            ConsumerStore.FixedConsumer,
            TokenStatus.Authorized,
            null,
            ServiceProviderContext.DummyIdentity,
            new string[] { });         internal static readonly IAccessToken FixedAccessToken = new OAuthAccessToken(
            "accesskey",
            "accesssecret",
            ConsumerStore.FixedConsumer,
            TokenStatus.Authorized,
            TokenGenerator.FixedRequestToken);         public IRequestToken CreateRequestToken(IConsumer consumer, OAuthParameters parameters)
        {
            return TokenGenerator.FixedRequestToken;
        }         public IAccessToken CreateAccessToken(IConsumer consumer, IRequestToken requestToken)
        {
            return TokenGenerator.FixedAccessToken;
        }
    } public class TokenStore : InMemoryTokenStore, ITokenStore
    {
        public TokenStore()
        {
            this.RequestTokenDictionary.Add(
                TokenGenerator.FixedRequestToken.Token,
                TokenGenerator.FixedRequestToken);             this.AccessTokenDictionary.Add(
                TokenGenerator.FixedAccessToken.Token,
                TokenGenerator.FixedAccessToken);
        }         public override bool Add(IRequestToken token)
        {
            throw new NotSupportedException("Tokens cannot be added to the token store--it is fixed.");
        }         public override bool Add(IAccessToken token)
        {
            throw new NotSupportedException("Tokens cannot be added to the token store--it is fixed.");
        }         public override bool Update(IRequestToken token)
        {
            throw new NotSupportedException("Tokens cannot be updated in the token store--it is fixed.");
        }         public override bool Update(IAccessToken token)
        {
            throw new NotSupportedException("Tokens cannot be updated in the token store--it is fixed.");
        }         public override bool Remove(IRequestToken token)
        {
            throw new NotSupportedException("Tokens cannot be removed from the token store--it is fixed.");
        }         public override bool Remove(IAccessToken token)
        {
            throw new NotSupportedException("Tokens cannot be removed from the token store--it is fixed.");
        }

}

这样就完成了一个最最简单小型的服务端OAuth认证,然后用android客户端进行测试ok通过。

注意点:

一、android模拟器访问本地服务地址为10.0.2.2,比如http://localhost:3423/authorize.aspx在模拟器中用http://10.0.2.2:3423/authorize.aspx。

二、OAuth.Net类库的OAuth.Net.Common项目中的interface ICallbackStore 添加了一个Uri GetCalback(IRequestToken token);并且在具体的实现类InMemoryCallbackStore添加了实习代码:

public Uri GetCalback(IRequestToken token)

        {
            lock (this.callbackStore)
            {
                if (this.callbackStore.ContainsKey(token))
                {
                    return this.callbackStore[token];
                }
                else
                {
                    return null;
                }
            }
        }
 

三、为了能用我前面做的给新浪用的android客户端,对于类库源代码AccessTokenHandler的ParseParameters方法做了如下修改,因为新浪请求api的时候都会加一个source的参数:

protected virtual void ParseParameters(HttpContext httpContext, OAuthRequestContext requestContext)

        {
            .......
            parameters.AllowOnly(
                    Constants.ConsumerKeyParameter,
                    Constants.TokenParameter,
                    Constants.SignatureMethodParameter,
                    Constants.SignatureParameter,
                    Constants.TimestampParameter,
                    Constants.NonceParameter,
                    Constants.VerifierParameter,
                    Constants.VersionParameter, // (optional)
                    Constants.RealmParameter, // (optional)
                    "source");
 
            ......
        }
 

服务端API的OAuth认证实现的更多相关文章

  1. .Net分布式异常报警系统-客户端及服务端API

    客户端 客户端的作用就是捕获未处理异常, 发送异常到服务端. 关于捕获未处理异常的方法参考 http://www.cnblogs.com/youring2/archive/2012/04/25/246 ...

  2. 安卓推送——个推服务端api使用误区

    首先你需要在个推开放着平台上注册你的应用,以及获得以下几个必要的值APPID |APPKEY | MASTERSECRET,本文假设你已经完成上述步骤以及完成客户端SDK的集成. 原理 个推服务端ap ...

  3. Identity4实现服务端+api资源控制+客户端请求

    准备写一些关于Identity4相关的东西,最近也比较对这方面感兴趣.所有做个开篇笔记记录一下,以便督促自己下一个技术方案方向 已经写好的入门级别Identity4的服务+api资源访问控制和简单的客 ...

  4. JAVA通过http访问其他服务端API

    项目要实现这么一个功能,用户通过点击按钮,通过axios来访问python的API(算法,java不好做)得到一个结果存储到数据库并且返回到页面. 但是python不是在tomcat上面运行的,所以不 ...

  5. 服务端API 工作经验(没有工作的是体会不到的)

    1.慢慢了解以下内容 [{xx:xxx,xx:xxx},{xx:xxx,xx:xxx},{xx:xxx,xx:xxx},]-- 数据 data 服务端API 状态代码(01代表成功) message ...

  6. CMDB学习之五服务端api

    服务端api 对发送来的数据进行处理,并返回结果,首先要创建一个Django项目 第一步,就是写URL路由在分支中写url api 主路由 from django.conf.urls import u ...

  7. C#开发BIMFACE系列6 服务端API之获取文件信息

    在<C#开发BIMFACE系列4 服务端API之源上传文件>.<C#开发BIMFACE系列5 服务端API之文件直传>两篇文章中详细介绍了如何将本地文件上传到BIMFACE服务 ...

  8. C#开发BIMFACE系列4 服务端API之源上传文件

    在注册成为BIMFACE的应用开发者后,要能在浏览器里浏览你的模型或者获取你模型内的BIM数据, 首先需要把你的模型文件上传到BIMFACE.根据不同场景,BIMFACE提供了丰富的文件相关的接口. ...

  9. C#开发BIMFACE系列3 服务端API之获取应用访问凭证AccessToken

    系列目录     [已更新最新开发文章,点击查看详细] BIMFACE 平台为开发者提供了大量的服务器端 API 与 JavaScript API,用于二次开发 BIM 的相关应用. BIMFACE ...

随机推荐

  1. openjpa框架入门_openbooks项目Overview(四)

  2. C语言的本质(15)——C语言的函数接口入门

    C语言的本质(15)--C语言的函数接口 函数的调用者和其实现者之间存在一个协议,在调用函数之前,调用者要为实现者提供某些条件,在函数返回时,实现者完成调用者需要的功能. 函数接口通过函数名,参数和返 ...

  3. [转]Geoserver实现WFS操作

    From:http://liushaobo2005.blog.163.com/blog/static/253056702011541462372/ wfs是OGC的标准规范,主要用于提供对矢量地理数据 ...

  4. linux命令之pwd(print working drectory)

    Linux中用 pwd 命令来查看”当前工作目录“的完整路径. 简单得说,每当你在终端进行操作时,你都会有一个当前工作目录. 在不太确定当前位置时,就会使用pwd来判定当前目录在文件系统内的确切位置. ...

  5. 【C/C++】Linux下system()函数引发的错误

    http://my.oschina.net/renhc/blog/54582 [C/C++]Linux下system()函数引发的错误 恋恋美食  恋恋美食 发布时间: 2012/04/21 11:3 ...

  6. IDE idea 更换项目的JDK步骤

    1.如图:

  7. C# in Depth阅读笔记1:C#1特性

    1.委托 委托是对包含返回值和参数的行为的一种封装,类似于单一方法的接口. 委托是不易变的(就像string),system.delegate下的combine和remove方法都只能产生一个新的委托 ...

  8. HTML5 canvas 绘制精美的图形

    HTML5 是一个新兴标准,它正在以越来越快的速度替代久经考验的 HTML4.HTML5 是一个 W3C “工作草案” — 意味着它仍然处于开发阶段 — 它包含丰富的元素和属性,它们都支持现行的 HT ...

  9. 使用ADO.net中的链接字符串

    需要引用:System.Configuration命名空间 ConfigurationManager.ConnectionStrings["sqlConnStr"].Connect ...

  10. NSDate 的一些操作(比较、创建、在现有date加减一定时间等)

    创建当前时间 NSDate *date = [NSDate date]; 从现在开始的24小时 NSTimeInterval a_day = 24*60*60; NSDate *tomorrow = ...