<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_自由、创新、研究、探索</title><subtitle type="text">Linux/Windows Mono/DotNet             [ Open Source .NET Development/使用开源工具进行DotNet软件开发]</subtitle><id>http://feed.cnblogs.com/blog/u/782/rss</id><updated>2012-02-11T01:33:08Z</updated><author><name>张善友</name><uri>http://www.cnblogs.com/shanyou/</uri></author><generator>CNBlogs BlogServer</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/shanyou/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/782/rss"/><entry><id>http://www.cnblogs.com/shanyou/archive/2012/02/10/2346144.html</id><title type="text">在 Windows Phone上使用QQConnect  OAuth2</title><summary type="text">QQ互联OAuth2.0 .NET SDK 发布以及网站QQ登陆示例代码 这篇文章讲述的普通的ASP.NET站点上使用QQ互联，本篇文章主要介绍在WindowsPhone环境使用QQ互联OAuth2 SDK，本文的程序改自Google OAuth2 on Windows Phone。QQ互联的OAuth2和Google 的OAuth2的流程上差不多，QQ互联的还更简单一点。</summary><published>2012-02-10T13:55:00Z</published><updated>2012-02-10T13:55:00Z</updated><author><name>张善友</name><uri>http://www.cnblogs.com/shanyou/</uri></author><link rel="alternate" href="http://www.cnblogs.com/shanyou/archive/2012/02/10/2346144.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/shanyou/archive/2012/02/10/2346144.html"/><content type="html">&lt;p&gt;&lt;a href="http://www.cnblogs.com/shanyou/archive/2012/02/05/2338797.html"&gt;QQ互联OAuth2.0 .NET SDK 发布以及网站QQ登陆示例代码&lt;/a&gt; 这篇文章讲述的普通的ASP.NET站点上使用QQ互联，本篇文章主要介绍在WindowsPhone环境使用QQ互联OAuth2 SDK，本文的程序改自&lt;a title="http://www.codeproject.com/Articles/321291/Google-OAuth2-on-Windows-Phone" href="http://www.codeproject.com/Articles/321291/Google-OAuth2-on-Windows-Phone"&gt;Google OAuth2 on Windows Phone&lt;/a&gt;。QQ互联的OAuth2和Google 的OAuth2的流程上差不多，QQ互联的还更简单一点。&lt;/p&gt;&#xD;
&lt;p&gt;代码中使用了如下三个类库：&lt;/p&gt;&#xD;
&lt;ul&gt;&#xD;
&lt;li&gt;&lt;a href="http://restsharp.org/"&gt;RestSharp&lt;/a&gt;&lt;/li&gt;&#xD;
&lt;li&gt;&lt;a href="http://json.codeplex.com/"&gt;JSON.NET&lt;/a&gt;&lt;/li&gt;&#xD;
&lt;li&gt;&lt;a href="http://mvvmlight.codeplex.com/"&gt;MVVM Light&lt;/a&gt;&lt;/li&gt;&#xD;
&lt;/ul&gt;&#xD;
&lt;p&gt;这些库都可以通过NuGet包安装，需要注意的是JSON.NET (4.0.7)目前和RestSharp的最新版本102.6.0.0不兼容，需要使用JSON.NET (4.0.5)版本。&lt;/p&gt;&#xD;
&lt;p&gt;想把这个例子跑起来，需要到&lt;a href="http://connect.qq.com"&gt;http://connect.qq.com&lt;/a&gt; 注册获取到appkey和appscrect，填写到配置文件：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/shanyou/201202/201202102154447580.png"&gt;&lt;img style="display: inline; border: 0px;" title="image" src="http://images.cnblogs.com/cnblogs_com/shanyou/201202/201202102154473177.png" alt="image" width="659" height="219" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;其中CallBackURI是在登记的回调地址。程序采用MVVM模式，将OAuth2认证的页面为AuthenticationPage.xaml，登陆的逻辑都在ViewModel对应于AuthenticationViewModel，和QQ互联服务器交互的是AuthenticationProcess。交互的流程参照&lt;a title="http://wiki.opensns.qq.com/wiki/%E3%80%90QQ%E7%99%BB%E5%BD%95%E3%80%91%E5%BC%80%E5%8F%91%E6%94%BB%E7%95%A5_Client-side" href="http://wiki.opensns.qq.com/wiki/%E3%80%90QQ%E7%99%BB%E5%BD%95%E3%80%91%E5%BC%80%E5%8F%91%E6%94%BB%E7%95%A5_Client-side" target="_blank"&gt;【QQ登录】开发攻略_Client-side&lt;/a&gt;。&lt;/p&gt;&#xD;
&lt;p&gt;AuthenticationViewModel::GetAccessCode封装了OAuth2的验证授权的逻辑。&lt;/p&gt;&#xD;
&lt;p&gt;private bool _isAuthenticating; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private Queue&amp;lt;Action&amp;lt;string,string&amp;gt;&amp;gt; _queuedRequests = new Queue&amp;lt;Action&amp;lt;string,string&amp;gt;&amp;gt;();&lt;/p&gt;&#xD;
&lt;p&gt;public void GetAccessCode(Action&amp;lt;string,string&amp;gt; callback) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; lock (_sync) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (_isAuthenticating) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _queuedRequests.Enqueue(callback); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else if (HasAuthenticated) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (!_process.AuthResult.IsExpired) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; callback(_process.AuthResult.AccessToken,_process.AuthResult.OpenId); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; InvokeCallback(callback); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; InvokeCallback(callback); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&#xD;
&lt;p&gt;private void InvokeCallback(Action&amp;lt;string, string&amp;gt; callback) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _isAuthenticating = true; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _queuedRequests.Enqueue(callback);&lt;/p&gt;&#xD;
&lt;p&gt;((PhoneApplicationFrame)App.Current.RootVisual).Navigate(new Uri("/AuthenticationPage.xaml", UriKind.Relative)); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; AuthUri = _process.AuthUri; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&#xD;
&lt;p&gt;1、如果正在认证过程中，把调用方法放到队列里，然后返回。&lt;/p&gt;&#xD;
&lt;p&gt;2、如果验证过了，并且票据还是有效的，直接回调方法。&lt;/p&gt;&#xD;
&lt;p&gt;3、如果没有认证过，或者票据已经失效了，转到验证页面，可以使用QQ号码登陆。&lt;/p&gt;&#xD;
&lt;p&gt;AuthenticationPage.xaml页面带了一个WebBrowser对象，将一个绑定是AuthenticationViewModel的AuthUri ，类似于&lt;/p&gt;&#xD;
&lt;p&gt;http://openapi.qzone.qq.com/oauth/show?which=Login&amp;amp;display=mobile&amp;amp;response_type=token&amp;amp;client_id=204134&amp;amp;redirect_uri=win8charm.com&amp;amp;scope=get_user_info,add_share,list_album,upload_pic,check_page_fans,add_t,add_pic_t,del_t,get_repost_list,get_info,get_other_info,get_fanslist,get_idolist,add_idol,del_idol,add_one_blog,add_topic,get_tenpay_addr&amp;amp;display=mobile&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/shanyou/201202/201202102154498915.png"&gt;&lt;img style="display: inline; border: 0px;" title="qoauth2windowsphone" src="http://images.cnblogs.com/cnblogs_com/shanyou/201202/201202102154502701.png" alt="qoauth2windowsphone" width="252" height="577" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;用户登陆后，如果是首次登陆还需要授权API的访问，然后会返回到redirect_uri参数指定的地址，这里可以拿到返回的用户的Access Token：&lt;/p&gt;&#xD;
&lt;p&gt;private void webBrowser1_Navigating(object sender, NavigatingEventArgs e) &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (e.Uri.Host.Equals("win8charm.com")) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; webBrowser1.Visibility = Visibility.Collapsed; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; e.Cancel = true; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // setting this text will bind it back to the view model &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; codeBlock.Text = e.Uri.Fragment.Replace("#", ""); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;把返回的AccessToken通过页面的一个CodeBlock的掩藏TextBlock将结果传递给View Model ，将Access Token和OpenID结果解析完成，完成整个验证过程。&lt;/p&gt;&#xD;
&lt;p&gt;private string _code; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public string Code &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return _code; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; set &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _code = value; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _process.ExchangeCodeForToken(Code); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&#xD;
&lt;p&gt;public void ExchangeCodeForToken(string code) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (string.IsNullOrEmpty(code)) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; OnAuthenticationFailed(EventArgs.Empty); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; OAuthToken response = this.restApi.GetUserAccessToken(code); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; GetAccessToken(response); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&#xD;
&lt;p&gt;void GetAccessToken(OAuthToken response) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Debug.Assert(response != null); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; AuthResult = new Model.AuthResult() &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; AccessToken = response.AccessToken, &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Expires = response.ExpiresAt &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } ; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; restApi.GetUserOpenIdAsync(AuthResult.AccessToken, GetUserOpenId, GetUserOpenIdFailure); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&#xD;
&lt;p&gt;void GetUserOpenId(string response) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (string.IsNullOrEmpty(response)) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; OnAuthenticationFailed(EventArgs.Empty); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; AuthResult.OpenId = response; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; OnAuthenticated(); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&#xD;
&lt;p&gt;在认证成功或者失败的时候引发认证成功或者失败的事件最终完成整个登陆过程。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/shanyou/aggbug/2346144.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/shanyou/archive/2012/02/10/2346144.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/shanyou/archive/2012/02/08/2343280.html</id><title type="text">OAuth2.0 .NET版SDK,支持Mono</title><summary type="text">如果你是.NET版的网站 如果你还在苦苦钻研OAuth1.0 如果你还没成功安装QQ登录 如果你还在到处找人帮忙 那oauth2.0的.NET SDK将帮您解决一切烦恼！ 为什么有了OAut...</summary><published>2012-02-08T14:10:00Z</published><updated>2012-02-08T14:10:00Z</updated><author><name>张善友</name><uri>http://www.cnblogs.com/shanyou/</uri></author><link rel="alternate" href="http://www.cnblogs.com/shanyou/archive/2012/02/08/2343280.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/shanyou/archive/2012/02/08/2343280.html"/><content type="html">&lt;p&gt;如果你是.NET版的网站&lt;/p&gt;  &lt;p&gt;如果你还在苦苦钻研OAuth1.0&lt;/p&gt;  &lt;p&gt;如果你还没成功安装QQ登录&lt;/p&gt;  &lt;p&gt;如果你还在到处找人帮忙&lt;/p&gt;  &lt;p&gt;那oauth2.0的.NET SDK将帮您解决一切烦恼！&lt;/p&gt;  &lt;p&gt;为什么有了OAuth1.0，还要使用oauth2.0？&lt;/p&gt;  &lt;p&gt;因为他更加&lt;strong&gt;简单&lt;/strong&gt;。更&lt;strong&gt;易安装&lt;/strong&gt;！ QQ登录OAuth2.0采用OAuth2.0标准协议来进行用户身份验证和获取用户授权，相对于之前的OAuth1.0协议，其认证流程更简单和更安全。&lt;/p&gt;  &lt;p&gt;点击下载吧 &lt;a href="http://opensns.codeplex.com/releases/view/81729"&gt;http://opensns.codeplex.com/releases/view/81729&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/shanyou/aggbug/2343280.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/shanyou/archive/2012/02/08/2343280.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/shanyou/archive/2012/02/08/2342151.html</id><title type="text">Kinect for Windows 正式发布</title><summary type="text">Kinect for Windows 如约而至，美国当地时间2012年2月1日正式发布，Kinect for Windows 的官方网站也已经上线。微软同时还提供了 Kinect for Window...</summary><published>2012-02-08T00:04:00Z</published><updated>2012-02-08T00:04:00Z</updated><author><name>张善友</name><uri>http://www.cnblogs.com/shanyou/</uri></author><link rel="alternate" href="http://www.cnblogs.com/shanyou/archive/2012/02/08/2342151.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/shanyou/archive/2012/02/08/2342151.html"/><content type="html">&lt;p&gt;&lt;u&gt;&lt;u&gt;Kinect&lt;/u&gt; &lt;u&gt;for&lt;/u&gt; &lt;u&gt;Windows&lt;/u&gt; 如约而至，美国当地时间2012年2月1日正式发布，&lt;/u&gt;&lt;a href="http://www.microsoft.com/en-us/kinectforwindows/"&gt;&lt;u&gt;&lt;u&gt;Kinect&lt;/u&gt; &lt;u&gt;for&lt;/u&gt; &lt;u&gt;Windows&lt;/u&gt;&lt;/u&gt;&lt;/a&gt;&lt;u&gt; 的官方网站也已经上线。微软同时还提供了 &lt;u&gt;Kinect&lt;/u&gt; &lt;u&gt;for&lt;/u&gt; &lt;u&gt;Windows&lt;/u&gt; 的 &lt;u&gt;SDK&lt;/u&gt;，感兴趣的开发人员可以从这里下载：&lt;/u&gt;&lt;a href="http://www.microsoft.com/en-us/kinectforwindows/develop/overview.aspx"&gt;&lt;u&gt;&lt;u&gt;Download&lt;/u&gt; &lt;u&gt;Kinect&lt;/u&gt; &lt;u&gt;for&lt;/u&gt; &lt;u&gt;Windows&lt;/u&gt; &lt;u&gt;SDK&lt;/u&gt;&lt;/u&gt;&lt;/a&gt;&lt;u&gt;。&lt;/u&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/shanyou/201202/201202080804153346.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="kinect-hero" border="0" alt="kinect-hero" src="http://images.cnblogs.com/cnblogs_com/shanyou/201202/201202080804175986.jpg" width="727" height="278" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;u&gt;&lt;u&gt;Kinect&lt;/u&gt; &lt;u&gt;for&lt;/u&gt; &lt;u&gt;Windows&lt;/u&gt; 目前支持 &lt;u&gt;Windows&lt;/u&gt; 7，&lt;u&gt;Windows&lt;/u&gt; &lt;u&gt;Embedded&lt;/u&gt; Standard7 和 &lt;u&gt;Windows&lt;/u&gt; 8 &lt;u&gt;Developer&lt;/u&gt; &lt;u&gt;Preview&lt;/u&gt;（&lt;u&gt;desktop&lt;/u&gt; &lt;u&gt;applications&lt;/u&gt; &lt;u&gt;only&lt;/u&gt;）。 在美国当地的 &lt;/u&gt;&lt;a href="http://www.amazon.com/Microsoft-L6M-00001-Kinect-Sensor-Windows/dp/B006UIS53K/ref=sr_1_1?ie=UTF8&amp;amp;qid=1327348853&amp;amp;sr=8-1"&gt;&lt;u&gt;&lt;u&gt;Amazon&lt;/u&gt;&lt;/u&gt;&lt;/a&gt;&lt;u&gt; 和 &lt;/u&gt;&lt;a href="http://www.microsoftstore.com/store/msstore/en_US/pd/productID.244210600"&gt;&lt;u&gt;&lt;u&gt;Microsoft&lt;/u&gt; &lt;u&gt;Store&lt;/u&gt;&lt;/u&gt;&lt;/a&gt;&lt;u&gt; 都有销售，价格为：249美元。未来还将在澳大利亚、加拿大、法国、德国、意大利、爱尔兰、日本、墨西哥、新西兰、西班牙和英国上市销售&lt;/u&gt;.&lt;/p&gt;&lt;img src="http://www.cnblogs.com/shanyou/aggbug/2342151.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/shanyou/archive/2012/02/08/2342151.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/shanyou/archive/2012/02/07/2340810.html</id><title type="text">腾讯社区开放平台.NET SDK在Mono下运行</title><summary type="text">腾讯社区开放平台.NET SDK在CentOS下运行发生了如下错误： QzoneException: QConnectSDK.Exceptions.QzoneException: Exceptio...,这个问题可以说是windows平台和linux平台的差异造成的。我们的开发和应用多跑在windows平台上，好处是这个平台为我们作了很多幕后工作，坏处是我们清楚她做了些什么，看来后面的移植过程中出现的问题，第一要考虑的就是时不时平台差异造成的。mono本身在发行的时候是不带任何证书的，这和windows平台似乎恰恰相反。不过有工具，允许我们自行安装证书。</summary><published>2012-02-06T23:59:00Z</published><updated>2012-02-06T23:59:00Z</updated><author><name>张善友</name><uri>http://www.cnblogs.com/shanyou/</uri></author><link rel="alternate" href="http://www.cnblogs.com/shanyou/archive/2012/02/07/2340810.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/shanyou/archive/2012/02/07/2340810.html"/><content type="html">&lt;p&gt;&lt;a href="http://opensns.codeplex.com/"&gt;腾讯社区开放平台.NET SDK&lt;/a&gt;在CentOS下运行发生了如下错误：&lt;/p&gt;&#xD;
&lt;p&gt;QzoneException:&amp;nbsp; &lt;br /&gt;QConnectSDK.Exceptions.QzoneException: Exception of type 'QConnectSDK.Exceptions.QzoneException' was thrown. at QConnectSDK.Api.RestApi.Execute (RestSharp.RestRequest request) [0x00000] in :0 at QConnectSDK.Api.RestApi.GetAccessToken (System.String oAuthVericode, System.String state) [0x00000] in :0 at QConnectSDK.Context.QzoneContext.GetAccessToken (System.String state) [0x00000] in :0 at QConnectSDK.QOpenClient..ctor (System.String verifierCode, System.String state) [0x00000] in :0 at ASP.qq_auth_auth_aspx.__RenderTree (System.Web.UI.HtmlTextWriter __output, System.Web.UI.Control parameterContainer) [0x00000] in :0&lt;/p&gt;&#xD;
&lt;p&gt;开始怀疑是RestSharp这个库的兼容问题，后来在Mac上运行成功和Jexus的作者宇内的排查，终于在Linux上成功运行腾讯社区开放平台.NET SDK。&lt;/p&gt;&#xD;
&lt;p&gt;查看了mono的文档知道，地址&lt;a href="http://www.mono-project.com/FAQ:_Security"&gt;http://www.mono-project.com/FAQ:_Security&lt;/a&gt;，Linux本身在发行的时候是不带任何证书的，这和windows平台似乎恰恰相反。不过有工具，允许我们自行安装证书。&lt;/p&gt;&#xD;
&lt;p&gt;安装根证书，这由 mozroots 来完成&lt;/p&gt;&#xD;
&lt;p&gt;mozroots --import /&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ##导入证书&lt;/p&gt;&#xD;
&lt;p&gt;--ask-remove&amp;nbsp; /&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ##仅删除时确认&lt;/p&gt;&#xD;
&lt;p&gt;--machine&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ##保存在全局环境&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/shanyou/201202/20120207075831163.png"&gt;&lt;img style="display: inline; border: 0px;" title="image" src="http://images.cnblogs.com/cnblogs_com/shanyou/201202/201202070758354496.png" alt="image" width="743" height="351" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;这个问题可以说是windows平台和linux平台的差异造成的。我们的开发和应用多跑在windows平台上，好处是这个平台为我们作了很多幕后工作，坏处是我们清楚她做了些什么，看来后面的移植过程中出现的问题，第一要考虑的就是时不时平台差异造成的。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/shanyou/aggbug/2340810.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/shanyou/archive/2012/02/07/2340810.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/shanyou/archive/2012/02/05/2339164.html</id><title type="text">QQ互联打通腾讯三大社交平台 推社会化营销浪潮</title><summary type="text">原文来自：http://news.ctocio.com.cn/398/12227398.shtml 如果你是一个网站主，如果你是一个网络营销人，如果你还盯着SEO，那么说明你已经out了，现在网...</summary><published>2012-02-05T09:55:00Z</published><updated>2012-02-05T09:55:00Z</updated><author><name>张善友</name><uri>http://www.cnblogs.com/shanyou/</uri></author><link rel="alternate" href="http://www.cnblogs.com/shanyou/archive/2012/02/05/2339164.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/shanyou/archive/2012/02/05/2339164.html"/><content type="html">&lt;p&gt;原文来自：&lt;a title="http://news.ctocio.com.cn/398/12227398.shtml" href="http://news.ctocio.com.cn/398/12227398.shtml"&gt;http://news.ctocio.com.cn/398/12227398.shtml&lt;/a&gt;&amp;#160; &lt;/p&gt;  &lt;p&gt;如果你是一个网站主，如果你是一个网络营销人，如果你还盯着SEO，那么说明你已经out了，现在网络营销领域最火的词不再是SEO，而是SMO，即社会化媒体优化。&lt;/p&gt;  &lt;p&gt;近日，QQ互联openAPI分享接口完全开放，第三方网站可以一站式接入QQ空间、朋友网、腾讯微博三大社交平台。同时，用户也可以通过QQ登陆第三方网站,并将在其它网站的动态同步到三大平台。业内人士表示，作为中国最具影响力的社交网络，腾讯三大社交平台在通过QQ互联openAPI实现一站互联、全线打通，也为SMO提供了极为广阔的应用空间。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;QQ互联一站接入 腾讯开放战略纵深发展&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;据介绍，QQ互联是腾讯开放平台为第三方网站和应用提供的开放接入方式，主要包含QQ登录、分享组件、赞组件和关注组件。本次腾讯开放平台QQ互联openAPI分享接口全面开放，包括开放同步动态接口，实现用户动态一键分享到QQ空间、朋友网、腾讯微博三大社交平台 ;同时QQ互联与微博openAPI实现双向互通，开放微博十种接口，开发者使用“QQ账号登录”之后，也可以调用腾讯微博的相应 API 接口，丰富了整个开放平台的开放能力。此举可以说是腾讯开放平台深入贯彻开放战略的重要举措之一。&lt;/p&gt;  &lt;p&gt;&lt;img alt="" src="http://image.tianjimedia.com/uploadImages/2011/354/AXT79FL136IN.jpg" width="380" height="250" /&gt;&lt;/p&gt;  &lt;p&gt;例如,用户用 QQ 账号登录土豆网，并授权了“同步发送动态”选项之后，在土豆网进行某些动作(挖，发帖等)时，均发送一条动态到QQ空间、朋友网、腾讯微博。通过动态的同步，以吸引社区好友点击，为网站带来回流。不仅如此，第三方网站可以根据自己网站的特性利用丰富的开放接口进行更有个性化的开发。&lt;/p&gt;  &lt;p&gt;QQ互联相关负责人表示，在实现一站互联、全线打通之后，第三方网站和应用可以通过用户的QQ关系链、朋友关系链、微博关系链进行三大维度的传播，迅速形成口碑效应，提升品牌知名度，为网站和应用真正导入社会化流量，快速带动其人气提升。作为腾讯开放平台的重要组成部分，QQ互联将随着开放的推进不断整合内部和外部资源，为用户提供更加便捷和丰富的网络服务体验，同时致力于为合作伙伴创造实实在在的价值。&lt;/p&gt;  &lt;p&gt;加入QQ互联的网站主表示，与SEO相比，SMO的优势在于社交网站拥有庞大的粘性用户群，QQ空间月活跃用户超过5.3亿，朋友网用户2.5亿，腾讯微博用户2亿。这三大社交网站的用户群以学生和白领人群为主，网络活跃度非常高。每个用户都可以成为传播渠道，网站内容通过用户好友关系链的多次分享后，将会获得多次生命，为网站带来大量的访问量和品牌曝光。&lt;/p&gt;  &lt;p&gt;早在年初，QQ互联为YOKA带去的流量已经超越了搜索引擎，优酷、56网、大众点评、拉手网、好乐买、凤凰网、招商银行和冷笑话等网站在加入QQ互联之后均在短期内获得可观的流量或收益。这足以证明，QQ互联的营销价值相当巨大。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt; 社交网络崛起 SMO来势汹汹&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;自从Facebook在2004年异军突起后，社会化媒体的浪潮在短短几年间席卷全球。社交网站已成为众商家品牌推广、形象塑造的竞争新高地，以社会化媒体为基础的优化推广策略体系也由此应运而生。2010年6月据DCCI对中国互联网监测数据显示，2010年上半年UGC(User Generated Content的简称，即用户生成内容)的流量超过网站专业制作内容的流量，前者页面浏览量占互联网总量的比例达50.7%，后者为47.32%。社区类应用流量超新闻、搜索、电商等总和。 对于网站主和企业而言，这意味着在一定程度上SMO营销将变得比SEO营销更加重要。网络用户之间的即时沟通与分享渐渐成为信息获取的主渠道，人们对于搜索引擎的等信息检索工具的依赖将会降低。而通过口碑、沟通、对话、分享、交流的传播效果越来越强，甚至有可能超过传统的促销、广告。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;占据制高点 QQ互联推动社会化营销浪潮&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Jiathis发布份的社会化分享排行榜显示，QQ空间稳居榜首，腾讯微博维持第3位不变，朋友网排名第11位，较10月上升1位。腾讯三大社交平台占有中国社会化媒体分享百分比之和接近20%，回点百分比之和达到46.8%，成为中国社会化媒体流量贡献的绝对主力。&lt;/p&gt;  &lt;p&gt;&lt;img alt="" src="http://image.tianjimedia.com/uploadImages/2011/354/KL4JVH0468P6.jpg" width="28" height="30" /&gt;&lt;/p&gt;  &lt;p&gt;图注：2011年11月份的社会化分享排行榜，来自Jiathis&lt;/p&gt;  &lt;p&gt;QQ互联有关负责人介绍，每条被分享到腾讯社交平台的动态信息，平均引发3-6次的回流，单个网站最高日均达到数十万回流。&lt;/p&gt;  &lt;p&gt;QQ互联全面打通之后，腾讯社交平台用户的强关系链传播效应将进一步被放大。用户动态实现QQ空间、朋友网、腾讯微博跨平台交流和沟通，其分享量和回点率将大幅提升，为第三方网站带来巨大的续发流量。&lt;/p&gt;  &lt;p&gt;事实上，对SMO而言，续发流量比原始流量更有价值。因为原始流量一般都是大量涌进的，而通过分享链接回点过来的访问者通常都会对网站的内容有兴趣。在读者看来，这内容是来自某网站的，所以他们会认可这个网站，久而久之便产生品牌认同和品牌依赖，这是SMO的最终目的。&lt;/p&gt;  &lt;p&gt;业内人士表示，SNS和微博的迅速发展引爆了互联网的社会化趋势。各种各样的营销模式充斥市场，让操作者们眼花缭乱。但从根本上来讲，社会化营销的效果取决于社交平台的规模和影响力。QQ互联充分地整合腾讯三大社交平台的优势，连通无数第三方网站，构成一个庞大的沟通生态圈，使得社交传播效果获得无限放大。目前，社会化平台产业链已初步形成，商业生态也在不断完善，社会化营销将成为社会化平台的重要盈利模式。QQ互联所代表的沟通生态圈，将充分引发用户与品牌、用户与用户之间关于品牌的对话，推动中国社会化营销浪潮的到来。&lt;/p&gt;  &lt;p&gt;原文来自：&lt;a title="http://news.ctocio.com.cn/398/12227398.shtml" href="http://news.ctocio.com.cn/398/12227398.shtml"&gt;http://news.ctocio.com.cn/398/12227398.shtml&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/shanyou/aggbug/2339164.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/shanyou/archive/2012/02/05/2339164.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/shanyou/archive/2012/02/05/2338797.html</id><title type="text">QQ互联OAuth2.0 .NET SDK 发布以及网站QQ登陆示例代码</title><summary type="text">QQ互联网站已经提供了PHP，JS，Android和iOS的SDK，缺少.NET版本的SDK，春节假期期间利用一些空闲时间封装了一个具有完全功能的.NET SDK,后续将封装一个对应的Windows Phone的SDK，并开源放在http://opensns.codeplex.com ,专门搭建了一个示例网站http://www.win8charm.com/ 和MSDN风格的在线帮助网站http://help.win8charm.com/ 。今天这篇文章主要介绍使用.NET SDK实施QQ登陆功能。</summary><published>2012-02-05T02:44:00Z</published><updated>2012-02-05T02:44:00Z</updated><author><name>张善友</name><uri>http://www.cnblogs.com/shanyou/</uri></author><link rel="alternate" href="http://www.cnblogs.com/shanyou/archive/2012/02/05/2338797.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/shanyou/archive/2012/02/05/2338797.html"/><content type="html">&lt;p&gt;&lt;strong&gt;OAuth&lt;/strong&gt;： OAuth（开放授权）是一个开放标准，允许用户授权第三方网站访问他们存储在另外的服务提供者上的信息，而不需要将用户名和密码提供给第三方网站或分享他们数据的所有内容。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;QQ登录OAuth2.0&lt;/strong&gt;：对于用户相关的OpenAPI（例如获取用户信息，动态同步，照片，日志，分享等），为了保护用户数据的安全和隐私，第三方网站访问用户数据前都需要显式的向用户征求授权。 &lt;br /&gt;QQ登录OAuth2.0采用OAuth2.0标准协议来进行用户身份验证和获取用户授权，相对于之前的&lt;a href="http://wiki.opensns.qq.com/wiki/%E3%80%90QQ%E7%99%BB%E5%BD%95%E3%80%91Qzone_OAuth_1.0%E8%AE%A4%E8%AF%81%E7%AE%80%E4%BB%8B"&gt;OAuth1.0协议&lt;/a&gt;，其认证流程更简单和安全。具体参考文档 &lt;a href="http://wiki.opensns.qq.com/wiki/%E3%80%90QQ%E7%99%BB%E5%BD%95%E3%80%91Qzone_OAuth2.0%E7%AE%80%E4%BB%8B"&gt;：【QQ登录】OAuth2.0开发文档&lt;/a&gt;。&lt;/p&gt;&#xD;
&lt;p&gt;QQ互联网站已经提供了PHP，JS，Android和iOS的SDK，缺少.NET版本的SDK，春节假期期间利用一些空闲时间封装了一个具有完全功能的.NET SDK,后续将封装一个对应的Windows Phone的SDK，并开源放在&lt;a href="http://opensns.codeplex.com"&gt;http://opensns.codeplex.com&lt;/a&gt; ,专门搭建了一个示例网站&lt;a title="http://www.win8charm.com/" href="http://www.win8charm.com/"&gt;http://www.win8charm.com/&lt;/a&gt; 和MSDN风格的在线帮助网站&lt;a title="http://help.win8charm.com/" href="http://help.win8charm.com/"&gt;http://help.win8charm.com/&lt;/a&gt; 。今天这篇文章主要介绍使用.NET SDK实施QQ登陆功能。&lt;/p&gt;&#xD;
&lt;p&gt;从这里&lt;a title="http://opensns.codeplex.com/" href="http://opensns.codeplex.com/"&gt;http://opensns.codeplex.com/&lt;/a&gt; 下载最新版本的SDK，最新版本是Beta， 完成SDK的封装，希望大家使用帮忙测试，SDK依赖于Newtonsoft.Json和RestSharp两个程序集，具体可以参考&lt;a href="http://www.cnblogs.com/shanyou/archive/2012/01/27/RestSharp.html"&gt;使用RestSharp 库消费Restful Service&lt;/a&gt;。 主要是两个类QzoneContext（QQ登陆的上下文数据）&amp;nbsp; 和 QOpenClient （QQ互联API入口），其他类主要是模型，配置类。&lt;/p&gt;&#xD;
&lt;p&gt;1、你得去&lt;a href="http://connect.qq.com/"&gt;http://connect.qq.com/&lt;/a&gt; 申请一个账号，会得到一个APP ID和App Key，这两个东东会在生成请求的时候用到。你的去填一些资料，还要提交一些资料审核。&lt;/p&gt;&#xD;
&lt;p&gt;在配置文件web.config加入QQ登陆所需要的一些配置参数，如下图所示：&lt;/p&gt;&#xD;
&lt;p&gt;&amp;lt;configuration&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;configSections&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;sectionGroup name="QQSectionGroup"&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;section name="QzoneSection" type="System.Configuration.NameValueSectionHandler,System, Version=4.0.0.0, Culture=neutral,PublicKeyToken=b77a5c561934e089" /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/sectionGroup&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;/configSections&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;lt;QQSectionGroup&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;QzoneSection&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add key="AppKey" value="" /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add key="AppSecret" value="" /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add key="CallBackURI" value="" /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add key="AuthorizeURL" value="&lt;a href="https://graph.qq.com/oauth2.0/authorize"&gt;https://graph.qq.com/oauth2.0/authorize&lt;/a&gt;" /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/QzoneSection&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;/QQSectionGroup&amp;gt;&lt;/p&gt;&#xD;
&lt;p&gt;AppKey是申请QQ登录成功后，分配给应用的appid；AppSecret是申请QQ登录成功后，分配给网站的appkey；CallBackURI是QQ登陆成功后的回调地址：AuthorizeURL是QQ互联的OAth2认证地址：&lt;/p&gt;&#xD;
&lt;p&gt;2、在项目中添加三个引用Newtonsoft.Json.dll、RestSharp.dll和 QConnectSDK.dll， 在页面上放置按钮，打开qq登录的页面，然后登录成功之后回调您的网站的页面。此时如果用户在你的网站有账号，那就可以绑定现有账号，或者新注册一个账号。如果你是新建站，也可以完全使用qq登录来作为用户体系。&lt;/p&gt;&#xD;
&lt;p&gt;下面上代码：&lt;/p&gt;&#xD;
&lt;p&gt;/// &amp;lt;summary&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// QQ登陆页面 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;/summary&amp;gt;&lt;/p&gt;&#xD;
&lt;p&gt;[HttpGet] &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public ActionResult Login(string returnUrl) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.Session[RETURNURL] = returnUrl; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var context = new QzoneContext(); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string state = Guid.NewGuid().ToString().Replace("-", ""); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Session["requeststate"] = state; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string scope = "get_user_info,add_share,list_album,upload_pic,check_page_fans,add_t,add_pic_t,del_t,get_repost_list,get_info,get_other_info,get_fanslist,get_idolist,add_idol,del_idol,add_one_blog,add_topic,get_tenpay_addr"; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var authenticationUrl = context.GetAuthorizationUrl(state, scope); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return new RedirectResult(authenticationUrl);&lt;/p&gt;&#xD;
&lt;p&gt;}&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;/// &amp;lt;summary&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// 回调页面 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;/summary&amp;gt;&lt;/p&gt;&#xD;
&lt;p&gt;public ActionResult QQConnect(LoginModel model) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (Request.Params["code"] != null) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; QOpenClient qzone = null;&lt;/p&gt;&#xD;
&lt;p&gt;var verifier = Request.Params["code"]; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var state = Request.Params["state"]; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string requestState = Session["requeststate"].ToString();&lt;/p&gt;&#xD;
&lt;p&gt;if (state == requestState) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; qzone = new QOpenClient(verifier, state); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var currentUser = qzone.GetCurrentUser(); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (this.Session["QzoneOauth"] == null) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.Session["QzoneOauth"] = qzone; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var friendlyName = currentUser.Nickname;&lt;/p&gt;&#xD;
&lt;p&gt;var isPersistentCookie = true; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SetAuthCookie(qzone.OAuthToken.OpenId, isPersistentCookie, friendlyName);&lt;/p&gt;&#xD;
&lt;p&gt;return Redirect(Url.Action("Index", "Home")); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&#xD;
&lt;p&gt;} &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return View(); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&#xD;
&lt;p&gt;上面的代码是ASP.NET MVC的，项目示例运行在&lt;a title="http://www.win8charm.com/" href="http://www.win8charm.com/"&gt;http://www.win8charm.com/&lt;/a&gt; ，下面贴个ASP.NET WebForm的代码示例：&lt;/p&gt;&#xD;
&lt;p&gt;QQ登陆页面&lt;/p&gt;&#xD;
&lt;p&gt;namespace OpenConnect.WebSample.Account &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public partial class LoginToQQ : System.Web.UI.Page &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; protected void Page_Load(object sender, EventArgs e) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; GetRequestToken(); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&#xD;
&lt;p&gt;private void GetRequestToken() &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var context = new QzoneContext(); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string state = Guid.NewGuid().ToString().Replace("-", ""); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string scope = "get_user_info,add_share,list_album,upload_pic,check_page_fans,add_t,add_pic_t,del_t,get_repost_list,get_info,get_other_info,get_fanslist,get_idolist,add_idol,del_idol,add_one_blog,add_topic,get_tenpay_addr"; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var authenticationUrl = context.GetAuthorizationUrl(state,scope); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //request token, request token secret 需要保存起来 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //在demo演示中，直接保存在全局变量中.真实情况需要网站自己处理 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Session["requeststate"] = state;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Response.Redirect(authenticationUrl);&lt;/p&gt;&#xD;
&lt;p&gt;} &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;回调页面&lt;/p&gt;&#xD;
&lt;p&gt;namespace OpenConnect.WebSample.Account &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public partial class QQCallback : System.Web.UI.Page &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; protected void Page_Load(object sender, EventArgs e) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (Request.Params["code"] != null) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; QOpenClient qzone = null; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; User currentUser = null;&lt;/p&gt;&#xD;
&lt;p&gt;var verifier = Request.Params["code"]; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string state = Session["requeststate"].ToString(); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; qzone = new QOpenClient(verifier, state); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; currentUser = qzone.GetCurrentUser(); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (null != currentUser) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.result.Text = "成功登陆"; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.Nickname.Text = currentUser.Nickname; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.Figureurl.ImageUrl = currentUser.Figureurl; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Session["QzoneOauth"] = qzone;&lt;/p&gt;&#xD;
&lt;p&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;span style="color: #ff0000;"&gt;这里说明一下使用QQ互联登陆是获取不到用户的QQ号的，只会获取到用户的OpenId，OpenID和QQ号是一一对应关系。&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;a name="本地测试"&gt;&lt;/a&gt;本地测试&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ul&gt;&#xD;
&lt;li&gt;前提准备，了解本地Host文件的作用&lt;/li&gt;&#xD;
&lt;/ul&gt;&#xD;
&lt;ol&gt;&#xD;
&lt;li&gt;找到C:\WINDOWS\system32\drivers\etc\hosts这个文件&lt;/li&gt;&#xD;
&lt;li&gt;用文本方式打开&lt;/li&gt;&#xD;
&lt;li&gt;增加一行：127.0.0.1 www.domain.com&lt;/li&gt;&#xD;
&lt;li&gt;启动本地服务器&lt;/li&gt;&#xD;
&lt;li&gt;启动浏览器访问 &lt;a href="http://www.domain.com/"&gt;http://www.domain.com/&lt;/a&gt;&lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;a name="其他"&gt;&lt;/a&gt;其他&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ul&gt;&#xD;
&lt;li&gt;下载： &lt;a title="http://opensns.codeplex.com/" href="http://opensns.codeplex.com/"&gt;http://opensns.codeplex.com/&lt;/a&gt;&lt;/li&gt;&#xD;
&lt;li&gt;项目示例：&lt;a title="http://www.win8charm.com/" href="http://www.win8charm.com/"&gt;http://www.win8charm.com/&lt;/a&gt;&amp;nbsp;&lt;/li&gt;&#xD;
&lt;li&gt;SDK 在线文档：&lt;a title="http://www.win8charm.com/" href="http://help.win8charm.com/"&gt;http://help.win8charm.com/&lt;/a&gt;&amp;nbsp;&lt;/li&gt;&#xD;
&lt;li&gt;QQ群：80767552&lt;/li&gt;&#xD;
&lt;li&gt;注：众人拾柴火焰高，欢迎各位反馈使用中的bug。&lt;/li&gt;&#xD;
&lt;li&gt;报告issue请来：&lt;a title="http://opensns.codeplex.com/workitem/list/basic" href="http://opensns.codeplex.com/workitem/list/basic"&gt;http://opensns.codeplex.com/workitem/list/basic&lt;/a&gt;&lt;/li&gt;&#xD;
&lt;li&gt;站内信或者下面方式&lt;/li&gt;&#xD;
&lt;li&gt;微博：&lt;a href="http://t.qq.com/geffzhang"&gt;http://t.qq.com/geffzhang&lt;/a&gt;&lt;/li&gt;&#xD;
&lt;li&gt;邮箱：geffzhang#qq.com&lt;/li&gt;&#xD;
&lt;li&gt;博客：&lt;a title="http://www.cnblogs.com/shanyou" href="http://www.cnblogs.com/shanyou"&gt;http://www.cnblogs.com/shanyou&lt;/a&gt;&amp;nbsp;&lt;/li&gt;&#xD;
&lt;/ul&gt;&lt;img src="http://www.cnblogs.com/shanyou/aggbug/2338797.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/shanyou/archive/2012/02/05/2338797.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/shanyou/archive/2012/01/29/2331003.html</id><title type="text">Redis 在Centos Linux 上的启动脚本</title><summary type="text">Redis管理脚本基于Ubuntu 的发行版上的,Ubuntu的可以看这篇文章ubuntu安装启动redis，在Centos linux 上并不能用，下面的脚本可以用于CentOS： 用这个脚本管理...</summary><published>2012-01-29T04:03:00Z</published><updated>2012-01-29T04:03:00Z</updated><author><name>张善友</name><uri>http://www.cnblogs.com/shanyou/</uri></author><link rel="alternate" href="http://www.cnblogs.com/shanyou/archive/2012/01/29/2331003.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/shanyou/archive/2012/01/29/2331003.html"/><content type="html">&lt;p&gt;Redis管理脚本基于Ubuntu 的发行版上的,Ubuntu的可以看这篇文章&lt;a href="http://www.cnblogs.com/viaivi/archive/2011/12/08/2281319.html"&gt;ubuntu安装启动redis&lt;/a&gt;，在Centos linux 上并不能用，下面的脚本可以用于CentOS：&lt;/p&gt;  &lt;p&gt;用这个脚本管理之前，需要先配置下面的内核参数，否则Redis脚本在重启或停止redis时，将会报错，并且不能自动在停止服务前同步数据到磁盘上：&lt;/p&gt;  &lt;p&gt;# vi /etc/sysctl.conf&lt;/p&gt;  &lt;p&gt;vm.overcommit_memory = 1&lt;/p&gt;  &lt;p&gt;然后应用生效：&lt;/p&gt;  &lt;p&gt;# sysctl –p&lt;/p&gt;  &lt;p&gt;建立redis启动脚本：&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;# vim /etc/init.d/redis&lt;/p&gt;  &lt;p&gt;#!/bin/bash   &lt;br /&gt;#    &lt;br /&gt;# Init file for redis    &lt;br /&gt;#    &lt;br /&gt;# chkconfig: - 80 12    &lt;br /&gt;# description: redis daemon    &lt;br /&gt;#    &lt;br /&gt;# processname: redis    &lt;br /&gt;# config: /etc/redis.conf    &lt;br /&gt;# pidfile: /var/run/redis.pid    &lt;br /&gt;source /etc/init.d/functions    &lt;br /&gt;#BIN=&amp;quot;/usr/local/bin&amp;quot;    &lt;br /&gt;BIN=&amp;quot;/usr/local/bin&amp;quot;    &lt;br /&gt;CONFIG=&amp;quot;/etc/redis.conf&amp;quot;    &lt;br /&gt;PIDFILE=&amp;quot;/var/run/redis.pid&amp;quot;    &lt;br /&gt;### Read configuration    &lt;br /&gt;[ -r &amp;quot;$SYSCONFIG&amp;quot; ] &amp;amp;&amp;amp; source &amp;quot;$SYSCONFIG&amp;quot;    &lt;br /&gt;RETVAL=0    &lt;br /&gt;prog=&amp;quot;redis-server&amp;quot;    &lt;br /&gt;desc=&amp;quot;Redis Server&amp;quot;    &lt;br /&gt;start() {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if [ -e $PIDFILE ];then    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; echo &amp;quot;$desc already running....&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; exit 1    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; fi    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; echo -n $&amp;quot;Starting $desc: &amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; daemon $BIN/$prog $CONFIG    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; RETVAL=$?    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; echo    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; [ $RETVAL -eq 0 ] &amp;amp;&amp;amp; touch /var/lock/subsys/$prog    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return $RETVAL    &lt;br /&gt;}    &lt;br /&gt;stop() {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; echo -n $&amp;quot;Stop $desc: &amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; killproc $prog    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; RETVAL=$?    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; echo    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; [ $RETVAL -eq 0 ] &amp;amp;&amp;amp; rm -f /var/lock/subsys/$prog $PIDFILE    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return $RETVAL    &lt;br /&gt;}    &lt;br /&gt;restart() {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; stop    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; start    &lt;br /&gt;}    &lt;br /&gt;case &amp;quot;$1&amp;quot; in    &lt;br /&gt;&amp;#160; start)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; start    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ;;    &lt;br /&gt;&amp;#160; stop)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; stop    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ;;    &lt;br /&gt;&amp;#160; restart)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; restart    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ;;    &lt;br /&gt;&amp;#160; condrestart)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; [ -e /var/lock/subsys/$prog ] &amp;amp;&amp;amp; restart    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; RETVAL=$?    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ;;    &lt;br /&gt;&amp;#160; status)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; status $prog    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; RETVAL=$?    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ;;    &lt;br /&gt;&amp;#160;&amp;#160; *)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; echo $&amp;quot;Usage: $0 {start|stop|restart|condrestart|status}&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; RETVAL=1    &lt;br /&gt;esac    &lt;br /&gt;exit $RETVAL&lt;/p&gt;  &lt;p&gt;然后增加服务并开机自启动：&lt;/p&gt;  &lt;p&gt;# chmod 755 /etc/init.d/redis   &lt;br /&gt;# chkconfig --add redis    &lt;br /&gt;# chkconfig --level 345 redis on    &lt;br /&gt;# chkconfig --list redis&lt;/p&gt;&lt;img src="http://www.cnblogs.com/shanyou/aggbug/2331003.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/shanyou/archive/2012/01/29/2331003.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/shanyou/archive/2012/01/29/2330997.html</id><title type="text">用Sysctl 调整Linux操作系统的性能</title><summary type="text">Sysctl是一个允许您改变正在运行中的Linux系统的接口。它包含一些 TCP/IP 堆栈和虚拟内存系统的高级选项， 这可以让有经验的管理员提高引人注目的系统性能。用sysctl可以读取设置超过五百...</summary><published>2012-01-29T03:56:00Z</published><updated>2012-01-29T03:56:00Z</updated><author><name>张善友</name><uri>http://www.cnblogs.com/shanyou/</uri></author><link rel="alternate" href="http://www.cnblogs.com/shanyou/archive/2012/01/29/2330997.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/shanyou/archive/2012/01/29/2330997.html"/><content type="html">&lt;p&gt;Sysctl是一个允许您改变正在运行中的Linux系统的接口。它包含一些 TCP/IP 堆栈和虚拟内存系统的高级选项， 这可以让有经验的管理员提高引人注目的系统性能。用sysctl可以读取设置超过五百个系统变量。基于这点，sysctl(8) 提供两个功能：读取和修改系统设置。 &lt;/p&gt;  &lt;p&gt;查看所有可读变量： &lt;/p&gt;  &lt;p&gt;% sysctl -a &lt;/p&gt;  &lt;p&gt;读一个指定的变量，例如 kern.maxproc： &lt;/p&gt;  &lt;p&gt;% sysctl kern.maxproc kern.maxproc: 1044 &lt;/p&gt;  &lt;p&gt;要设置一个指定的变量，直接用 variable=value 这样的语法： &lt;/p&gt;  &lt;p&gt;# sysctl kern.maxfiles=5000 &lt;/p&gt;  &lt;p&gt;kern.maxfiles: 2088 –&amp;gt; 5000 &lt;/p&gt;  &lt;p&gt;sysctl -w&lt;/p&gt;  &lt;p&gt;-w&amp;#160;&amp;#160;&amp;#160;&amp;#160; Use this option when you want to change a sysctl setting.&lt;/p&gt;  &lt;p&gt;注意,这个参数是用来改变当前值即虚拟文件系统/proc下的值.&lt;/p&gt;  &lt;p&gt;sysctl -p&lt;/p&gt;  &lt;p&gt;-p&amp;#160;&amp;#160;&amp;#160;&amp;#160; Load&amp;#160; in&amp;#160; sysctl settings from the file specified or /etc/sysctl.conf if none given.&amp;#160; Specifying - as filename means reading data from standard input.&lt;/p&gt;  &lt;p&gt;注: 指定要加载的配置文件并显示参数.如果不指定加载文件的路径,默认为:/etc/sysctl.conf&lt;/p&gt;  &lt;p&gt;比如,如果你添加了某个参数到/etc/sysctl.conf,&lt;/p&gt;  &lt;p&gt;echo &amp;quot;net.ipv4.tcp_keepalive_time=20&amp;quot;&amp;gt;&amp;gt;/etc/sysctl.conf &lt;/p&gt;  &lt;p&gt;那么运行sysctl -p将重新加载配置文件,这样新增加到配置文件的参数便能及时生效了.并且还会显示所有该配置文件中的参数.&lt;/p&gt;  &lt;p&gt;您可以使用sysctl修改系统变量，也可以通过编辑sysctl.conf文件来修改系统变量。sysctl.conf 看起来很像 rc.conf。它用 variable=value 的形式来设定值。指定的值在系统进入多用户模式之后被设定。并不是所有的变量都可以在这个模式下设定。 &lt;/p&gt;  &lt;p&gt;sysctl 变量的设置通常是字符串、数字或者布尔型。 (布尔型用 1 来表示'yes'，用 0 来表示'no')。 &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ############################### &lt;/p&gt;  &lt;p&gt;net.inet.ip.sourceroute=0&lt;/p&gt;  &lt;p&gt;net.inet.ip.accept_sourceroute=0&lt;/p&gt;  &lt;p&gt;#############################&lt;/p&gt;  &lt;p&gt;通过源路由，攻击者可以尝试到达内部IP地址 --包括RFC1918中的地址，所以&lt;/p&gt;  &lt;p&gt;不接受源路由信息包可以防止你的内部网络被探测。&lt;/p&gt;  &lt;p&gt;#################################&lt;/p&gt;  &lt;p&gt;net.inet.tcp.drop_synfin=1&lt;/p&gt;  &lt;p&gt;###################################&lt;/p&gt;  &lt;p&gt;安全参数，编译内核的时候加了options TCP_DROP_SYNFIN才可以用，可以阻止某些OS探测。&lt;/p&gt;  &lt;p&gt;##################################&lt;/p&gt;  &lt;p&gt;kern.maxvnodes=8446&lt;/p&gt;  &lt;p&gt;vnode 是对文件或目录的一种内部表达。 因此， 增加可以被操作系统利用的 vnode 数量将降低磁盘的 I/O。&lt;/p&gt;  &lt;p&gt;一般而言， 这是由操作系统自行完成的，也不需要加以修改。但在某些时候磁盘 I/O 会成为瓶颈，&lt;/p&gt;  &lt;p&gt;而系统的 vnode 不足， 则这一配置应被增加。此时需要考虑是非活跃和空闲内存的数量。&lt;/p&gt;  &lt;p&gt;要查看当前在用的 vnode 数量：&lt;/p&gt;  &lt;p&gt;# sysctl vfs.numvnodes&lt;/p&gt;  &lt;p&gt;vfs.numvnodes: 91349&lt;/p&gt;  &lt;p&gt;要查看最大可用的 vnode 数量：&lt;/p&gt;  &lt;p&gt;# sysctl kern.maxvnodes&lt;/p&gt;  &lt;p&gt;kern.maxvnodes: 100000&lt;/p&gt;  &lt;p&gt;如果当前的 vnode 用量接近最大值，则将 kern.maxvnodes 值增大 1,000 可能是个好主意。&lt;/p&gt;  &lt;p&gt;您应继续查看 vfs.numvnodes 的数值， 如果它再次攀升到接近最大值的程度，&lt;/p&gt;  &lt;p&gt;仍需继续提高 kern.maxvnodes。 在 top(1) 中显示的内存用量应有显著变化，&lt;/p&gt;  &lt;p&gt;更多内存会处于活跃 (active) 状态。&lt;/p&gt;  &lt;p&gt;####################################&lt;/p&gt;  &lt;p&gt;kern.maxproc: 964&lt;/p&gt;  &lt;p&gt;Maximum number of processes&lt;/p&gt;  &lt;p&gt;####################################&lt;/p&gt;  &lt;p&gt;kern.maxprocperuid: 867&lt;/p&gt;  &lt;p&gt;Maximum processes allowed per userid&lt;/p&gt;  &lt;p&gt;####################################&lt;/p&gt;  &lt;p&gt;因为我的maxusers设置的是256，20+16*maxusers＝4116。&lt;/p&gt;  &lt;p&gt;maxprocperuid至少要比maxproc少1，因为init(8) 这个系统程序绝对要保持在运作状态。&lt;/p&gt;  &lt;p&gt;我给它设置的2068。&lt;/p&gt;  &lt;p&gt;kern.maxfiles: 1928&lt;/p&gt;  &lt;p&gt;系统中支持最多同时开启的文件数量，如果你在运行数据库或大的很吃描述符的进程，那么应该设置在20000以上，&lt;/p&gt;  &lt;p&gt;比如kde这样的桌面环境，它同时要用的文件非常多。&lt;/p&gt;  &lt;p&gt;一般推荐设置为32768或者65536。&lt;/p&gt;  &lt;p&gt;####################################&lt;/p&gt;  &lt;p&gt;kern.argmax: 262144&lt;/p&gt;  &lt;p&gt;&amp;#160; maximum number of bytes (or characters) in an argument list.&lt;/p&gt;  &lt;p&gt;命令行下最多支持的参数，比如你在用find命令来批量删除一些文件的时候&lt;/p&gt;  &lt;p&gt;find . -name &amp;quot;*.old&amp;quot; -delete，如果文件数超过了这个数字，那么会提示你数字太多的。&lt;/p&gt;  &lt;p&gt;可以利用find . -name &amp;quot;*.old&amp;quot; -ok rm {} ;来删除。&lt;/p&gt;  &lt;p&gt;默认的参数已经足够多了，因此不建议再做修改。&lt;/p&gt;  &lt;p&gt;####################################&lt;/p&gt;  &lt;p&gt;kern.securelevel: -1&lt;/p&gt;  &lt;p&gt;&amp;#160; -1：这是系统默认级别，没有提供任何内核的保护错误；&lt;/p&gt;  &lt;p&gt;0：基本上作用不多，当你的系统刚启动就是0级别的，当进入多用户模式的时候就自动变成1级了。&lt;/p&gt;  &lt;p&gt;1：在这个级别上，有如下几个限制：&lt;/p&gt;  &lt;p&gt;a. 不能通过kldload或者kldunload加载或者卸载可加载内核模块；&lt;/p&gt;  &lt;p&gt;b. 应用程序不能通过/dev/mem或者/dev/kmem直接写内存；&lt;/p&gt;  &lt;p&gt;c. 不能直接往已经装在(mounted)的磁盘写东西，也就是不能格式化磁盘，但是可以通过标准的内核接口执行写操作；&lt;/p&gt;  &lt;p&gt;d. 不能启动X-windows，同时不能使用chflags来修改文件属性；&lt;/p&gt;  &lt;p&gt;2：在 1 级别的基础上还不能写没装载的磁盘，而且不能在1秒之内制造多次警告，这个是防止DoS控制台的；&lt;/p&gt;  &lt;p&gt;3：在 2 级别的级别上不允许修改IPFW防火墙的规则。&lt;/p&gt;  &lt;p&gt;如果你已经装了防火墙，并且把规则设好了，不轻易改动，那么建议使用3级别，如果你没有装防火墙，而且还准备装防火墙的话，不建议使用。&lt;/p&gt;  &lt;p&gt;我们这里推荐使用 2 级别，能够避免比较多对内核攻击。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ####################################&lt;/p&gt;  &lt;p&gt;kern.maxfilesperproc: 1735&lt;/p&gt;  &lt;p&gt;每个进程能够同时打开的最大文件数量，网上很多资料写的是32768&lt;/p&gt;  &lt;p&gt;除非用异步I/O或大量线程，打开这么多的文件恐怕是不太正常的。&lt;/p&gt;  &lt;p&gt;我个人建议不做修改，保留默认。&lt;/p&gt;  &lt;p&gt;####################################&lt;/p&gt;  &lt;p&gt;kern.ipc.maxsockbuf: 262144&lt;/p&gt;  &lt;p&gt;最大的套接字缓冲区，网上有建议设置为2097152（2M）、8388608（8M）的。&lt;/p&gt;  &lt;p&gt;我个人倒是建议不做修改，保持默认的256K即可，缓冲区大了可能造成碎片、阻塞或者丢包。&lt;/p&gt;  &lt;p&gt;####################################&lt;/p&gt;  &lt;p&gt;kern.ipc.somaxconn: 128&lt;/p&gt;  &lt;p&gt;最大的等待连接完成的套接字队列大小，即并发连接数。&lt;/p&gt;  &lt;p&gt;高负载服务器和受到Dos攻击的系统也许会因为这个队列被塞满而不能提供正常服务。&lt;/p&gt;  &lt;p&gt;默认为128，推荐在1024-4096之间，根据机器和实际情况需要改动，数字越大占用内存也越大。&lt;/p&gt;  &lt;p&gt;####################################&lt;/p&gt;  &lt;p&gt;kern.ipc.nmbclusters: 4800&lt;/p&gt;  &lt;p&gt;这个值用来调整系统在开机后所要分配给网络 mbufs 的 cluster 数量，&lt;/p&gt;  &lt;p&gt;由于每个 cluster 大小为 2K，所以当这个值为 1024 时，也是会用到 2MB 的核心内存空间。&lt;/p&gt;  &lt;p&gt;假设我们的网页同时约有 1000 个联机，而 TCP 传送及接收的暂存区大小都是 16K，&lt;/p&gt;  &lt;p&gt;则最糟的情况下，我们会需要 (16K+16K) * 1024，也就是 32MB 的空间，&lt;/p&gt;  &lt;p&gt;然而所需的 mbufs 大概是这个空间的二倍，也就是 64MB，所以所需的 cluster 数量为 64MB/2K，也就是 32768。&lt;/p&gt;  &lt;p&gt;对于内存有限的机器，建议值是 1024 到 4096 之间，而当拥有海量存储器空间时，我们可以将它设定为 4096 到 32768 之间。&lt;/p&gt;  &lt;p&gt;我们可以使用 netstat 这个指令并加上参数 -m 来查看目前所使用的 mbufs 数量。&lt;/p&gt;  &lt;p&gt;要修改这个值必须在一开机就修改，所以只能在 /boot/loader.conf 中加入修改的设定&lt;/p&gt;  &lt;p&gt;kern.ipc.nmbclusters=32768&lt;/p&gt;  &lt;p&gt;####################################&lt;/p&gt;  &lt;p&gt;kern.ipc.shmmax: 33554432&lt;/p&gt;  &lt;p&gt;共享内存和信号灯(&amp;quot;System VIPC&amp;quot;)如果这些过小的话，有些大型的软件将无法启动&lt;/p&gt;  &lt;p&gt;安装xine和mplayer提示的设置为67108864，即64M，&lt;/p&gt;  &lt;p&gt;如果内存多的话，可以设置为134217728，即128M&lt;/p&gt;  &lt;p&gt;####################################&lt;/p&gt;  &lt;p&gt;kern.ipc.shmall: 8192&lt;/p&gt;  &lt;p&gt;&amp;#160; 共享内存和信号灯(&amp;quot;System VIPC&amp;quot;)如果这些过小的话，有些大型的软件将无法启动&lt;/p&gt;  &lt;p&gt;安装xine和mplayer提示的设置为32768&lt;/p&gt;  &lt;p&gt;####################################&lt;/p&gt;  &lt;p&gt;kern.ipc.shm_use_phys: 0 &lt;/p&gt;  &lt;p&gt;如果我们将它设成 1，则所有 System V 共享内存 (share memory，一种程序间沟通的方式)部份都会被留在实体的内存 (physical memory) 中，&lt;/p&gt;  &lt;p&gt;而不会被放到硬盘上的 swap 空间。我们知道物理内存的存取速度比硬盘快许多，而当物理内存空间不足时，&lt;/p&gt;  &lt;p&gt;部份数据会被放到虚拟的内存上，从物理内存和虚拟内存之间移转的动作就叫作 swap。如果时常做 swap 的动作，&lt;/p&gt;  &lt;p&gt;则需要一直对硬盘作 I/O，速度会很慢。因此，如果我们有大量的程序 (数百个) 需要共同分享一个小的共享内存空间，&lt;/p&gt;  &lt;p&gt;或者是共享内存空间很大时，我们可以将这个值打开。&lt;/p&gt;  &lt;p&gt;这一项，我个人建议不做修改，除非你的内存非常大。&lt;/p&gt;  &lt;p&gt;####################################&lt;/p&gt;  &lt;p&gt;kern.ipc.shm_allow_removed: 0&lt;/p&gt;  &lt;p&gt;共享内存是否允许移除？这项似乎是在fb下装vmware需要设置为1的，否则会有加载SVGA出错的提示&lt;/p&gt;  &lt;p&gt;作为服务器，这项不动也罢。&lt;/p&gt;  &lt;p&gt;####################################&lt;/p&gt;  &lt;p&gt;kern.ipc.numopensockets: 12&lt;/p&gt;  &lt;p&gt;已经开启的socket数目，可以在最繁忙的时候看看它是多少，然后就可以知道maxsockets应该设置成多少了。&lt;/p&gt;  &lt;p&gt;####################################&lt;/p&gt;  &lt;p&gt;kern.ipc.maxsockets: 1928&lt;/p&gt;  &lt;p&gt;这是用来设定系统最大可以开启的 socket 数目。如果您的服务器会提供大量的 FTP 服务，&lt;/p&gt;  &lt;p&gt;而且常快速的传输一些小档案，您也许会发现常传输到一半就中断。因为 FTP 在传输档案时，&lt;/p&gt;  &lt;p&gt;每一个档案都必须开启一个 socket 来传输，但关闭 socket 需要一段时间，如果传输速度很快，&lt;/p&gt;  &lt;p&gt;而档案又多，则同一时间所开启的 socket 会超过原本系统所许可的值，这时我们就必须把这个值调大一点。&lt;/p&gt;  &lt;p&gt;除了 FTP 外，也许有其它网络程序也会有这种问题。&lt;/p&gt;  &lt;p&gt;然而，这个值必须在系统一开机就设定好，所以如果要修改这项设定，我们必须修改 /boot/loader.conf 才行&lt;/p&gt;  &lt;p&gt;kern.ipc.maxsockets=&amp;quot;16424&amp;quot;&lt;/p&gt;  &lt;p&gt;####################################&lt;/p&gt;  &lt;p&gt;kern.ipc.nsfbufs: 1456&lt;/p&gt;  &lt;p&gt;经常使用 sendfile(2) 系统调用的繁忙的服务器，&lt;/p&gt;  &lt;p&gt;有必要通过 NSFBUFS 内核选项或者在 /boot/loader.conf (查看 loader(8) 以获得更多细节) 中设置它的值来调节 sendfile(2) 缓存数量。&lt;/p&gt;  &lt;p&gt;这个参数需要调节的普通原因是在进程中看到 sfbufa 状态。sysctl kern.ipc.nsfbufs 变量在内核配置变量中是只读的。&lt;/p&gt;  &lt;p&gt;这个参数是由 kern.maxusers 决定的，然而它可能有必要因此而调整。&lt;/p&gt;  &lt;p&gt;在/boot/loader.conf里加入&lt;/p&gt;  &lt;p&gt;kern.ipc.nsfbufs=&amp;quot;2496&amp;quot;&lt;/p&gt;  &lt;p&gt;####################################&lt;/p&gt;  &lt;p&gt;kern.maxusers: 59&lt;/p&gt;  &lt;p&gt;maxusers 的值决定了处理程序所容许的最大值，20+16*maxusers 就是你将得到的所容许处理程序。&lt;/p&gt;  &lt;p&gt;系统一开机就必须要有 18 个处理程序 (process)，即便是简单的执行指令 man 又会产生 9 个 process，&lt;/p&gt;  &lt;p&gt;所以将这个值设为 64 应该是一个合理的数目。&lt;/p&gt;  &lt;p&gt;如果你的系统会出现 proc table full 的讯息的话，可以就把它设大一点，例如 128。&lt;/p&gt;  &lt;p&gt;除非您的系统会需要同时开启很多档案，否则请不要设定超过 256。&lt;/p&gt;  &lt;p&gt;可以在 /boot/loader.conf 中加入该选项的设定，&lt;/p&gt;  &lt;p&gt;kern.maxusers=256&lt;/p&gt;  &lt;p&gt;####################################&lt;/p&gt;  &lt;p&gt;kern.coredump: 1&lt;/p&gt;  &lt;p&gt;如果设置为0，则程序异常退出时不会生成core文件，作为服务器，不建议这样。&lt;/p&gt;  &lt;p&gt;####################################&lt;/p&gt;  &lt;p&gt;kern.corefile: %N.core&lt;/p&gt;  &lt;p&gt;可设置为kern.corefile=&amp;quot;/data/coredump/%U-%P-%N.core&amp;quot;&lt;/p&gt;  &lt;p&gt;其中 %U是UID，%P是进程ID，%N是进程名，当然/data/coredump必须是一个实际存在的目录&lt;/p&gt;  &lt;p&gt;####################################&lt;/p&gt;  &lt;p&gt;vm.swap_idle_enabled: 0&lt;/p&gt;  &lt;p&gt;vm.swap_idle_threshold1: 2&lt;/p&gt;  &lt;p&gt;vm.swap_idle_threshold2: 10&lt;/p&gt;  &lt;p&gt;#########################&lt;/p&gt;  &lt;p&gt;在有很多用户进入、离开系统和有很多空闲进程的大的多用户系统中很有用。&lt;/p&gt;  &lt;p&gt;可以让进程更快地进入内存，但它会吃掉更多的交换和磁盘带宽。&lt;/p&gt;  &lt;p&gt;系统默认的页面调度算法已经很好了，最好不要更改。&lt;/p&gt;  &lt;p&gt;########################&lt;/p&gt;  &lt;p&gt;vfs.ufs.dirhash_maxmem: 2097152&lt;/p&gt;  &lt;p&gt;#########################&lt;/p&gt;  &lt;p&gt;默认的dirhash最大内存,默认2M&lt;/p&gt;  &lt;p&gt;增加它有助于改善单目录超过100K个文件时的反复读目录时的性能&lt;/p&gt;  &lt;p&gt;建议修改为33554432（32M）&lt;/p&gt;  &lt;p&gt;#############################&lt;/p&gt;  &lt;p&gt;vfs.vmiodirenable: 1&lt;/p&gt;  &lt;p&gt;#################&lt;/p&gt;  &lt;p&gt;这个变量控制目录是否被系统缓存。大多数目录是小的，在系统中只使用单个片断(典型的是1K)并且在缓存中使用的更小 (典型的是512字节)。&lt;/p&gt;  &lt;p&gt;当这个变量设置为关闭 (0) 时，缓存器仅仅缓存固定数量的目录，即使您有很大的内存。&lt;/p&gt;  &lt;p&gt;而将其开启 (设置为1) 时，则允许缓存器用 VM 页面缓存来缓存这些目录，让所有可用内存来缓存目录。&lt;/p&gt;  &lt;p&gt;不利的是最小的用来缓存目录的核心内存是大于 512 字节的物理页面大小(通常是 4k)。&lt;/p&gt;  &lt;p&gt;我们建议如果您在运行任何操作大量文件的程序时保持这个选项打开的默认值。&lt;/p&gt;  &lt;p&gt;这些服务包括 web 缓存，大容量邮件系统和新闻系统。&lt;/p&gt;  &lt;p&gt;尽管可能会浪费一些内存，但打开这个选项通常不会降低性能。但还是应该检验一下。&lt;/p&gt;  &lt;p&gt;####################&lt;/p&gt;  &lt;p&gt;vfs.hirunningspace: 1048576&lt;/p&gt;  &lt;p&gt;############################&lt;/p&gt;  &lt;p&gt;这个值决定了系统可以将多少数据放在写入储存设备的等候区。通常使用默认值即可，&lt;/p&gt;  &lt;p&gt;但当我们有多颗硬盘时，我们可以将它调大为 4MB 或 5MB。&lt;/p&gt;  &lt;p&gt;注意这个设置成很高的值(超过缓存器的写极限)会导致坏的性能。&lt;/p&gt;  &lt;p&gt;不要盲目的把它设置太高！高的数值会导致同时发生的读操作的迟延。&lt;/p&gt;  &lt;p&gt;#############################&lt;/p&gt;  &lt;p&gt;vfs.write_behind: 1&lt;/p&gt;  &lt;p&gt;#########################&lt;/p&gt;  &lt;p&gt;这个选项预设为 1，也就是打开的状态。在打开时，在系统需要写入数据在硬盘或其它储存设备上时，&lt;/p&gt;  &lt;p&gt;它会等到收集了一个 cluster 单位的数据后再一次写入，否则会在一个暂存区空间有写入需求时就立即写到硬盘上。&lt;/p&gt;  &lt;p&gt;这个选项打开时，对于一个大的连续的文件写入速度非常有帮助。但如果您遇到有很多行程延滞在等待写入动作时，您可能必须关闭这个功能。&lt;/p&gt;  &lt;p&gt;############################&lt;/p&gt;  &lt;p&gt;net.local.stream.sendspace: 8192&lt;/p&gt;  &lt;p&gt;##################################&lt;/p&gt;  &lt;p&gt;本地套接字连接的数据发送空间&lt;/p&gt;  &lt;p&gt;建议设置为65536&lt;/p&gt;  &lt;p&gt;###################################&lt;/p&gt;  &lt;p&gt;net.local.stream.recvspace: 8192&lt;/p&gt;  &lt;p&gt;##################################&lt;/p&gt;  &lt;p&gt;本地套接字连接的数据接收空间&lt;/p&gt;  &lt;p&gt;建议设置为65536&lt;/p&gt;  &lt;p&gt;###################################&lt;/p&gt;  &lt;p&gt;net.inet.ip.portrange.lowfirst: 1023&lt;/p&gt;  &lt;p&gt;net.inet.ip.portrange.lowlast: 600&lt;/p&gt;  &lt;p&gt;net.inet.ip.portrange.first: 49152&lt;/p&gt;  &lt;p&gt;net.inet.ip.portrange.last: 65535&lt;/p&gt;  &lt;p&gt;net.inet.ip.portrange.hifirst: 49152&lt;/p&gt;  &lt;p&gt;net.inet.ip.portrange.hilast: 65535&lt;/p&gt;  &lt;p&gt;###################&lt;/p&gt;  &lt;p&gt;以上六项是用来控制TCP及UDP所使用的port范围，这个范围被分成三个部份，低范围、预设范围、及高范围。&lt;/p&gt;  &lt;p&gt;这些是你的服务器主动发起连接时的临时端口的范围，预设的已经1万多了，一般的应用就足够了。&lt;/p&gt;  &lt;p&gt;如果是比较忙碌的FTP server，一般也不会同时提供给1万多人访问的，&lt;/p&gt;  &lt;p&gt;当然如果很不幸，你的服务器就要提供很多，那么可以修改first的值，比如直接用1024开始&lt;/p&gt;  &lt;p&gt;#########################&lt;/p&gt;  &lt;p&gt;net.inet.ip.redirect: 1&lt;/p&gt;  &lt;p&gt;#########################&lt;/p&gt;  &lt;p&gt;设置为0，屏蔽ip重定向功能&lt;/p&gt;  &lt;p&gt;###########################&lt;/p&gt;  &lt;p&gt;net.inet.ip.rtexpire: 3600&lt;/p&gt;  &lt;p&gt;net.inet.ip.rtminexpire: 10&lt;/p&gt;  &lt;p&gt;########################&lt;/p&gt;  &lt;p&gt;很多apache产生的CLOSE_WAIT状态，这种状态是等待客户端关闭，但是客户端那边并没有正常的关闭，于是留下很多这样的东东。&lt;/p&gt;  &lt;p&gt;建议都修改为2&lt;/p&gt;  &lt;p&gt;#########################&lt;/p&gt;  &lt;p&gt;以上内容未经本站验证,请在使用之前使用sysctl grep option对选项默认值进行查找,对于命令无法搜索到的选项请谨慎操作,可能导致无法启动系统或者系统某些功能异常.&lt;/p&gt;&lt;img src="http://www.cnblogs.com/shanyou/aggbug/2330997.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/shanyou/archive/2012/01/29/2330997.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/shanyou/archive/2012/01/28/2330478.html</id><title type="text">Redis Web界面管理工具</title><summary type="text">一个很友好的Redis Web界面管理工具。基于.NET实现。可以通过Mono部署到Linux上，下面是我部署在CentOS 5.7 ＋ Mono 2.10.8 + Jexus 5.0.1： ...</summary><published>2012-01-28T03:33:00Z</published><updated>2012-01-28T03:33:00Z</updated><author><name>张善友</name><uri>http://www.cnblogs.com/shanyou/</uri></author><link rel="alternate" href="http://www.cnblogs.com/shanyou/archive/2012/01/28/2330478.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/shanyou/archive/2012/01/28/2330478.html"/><content type="html">&lt;p&gt;一个很友好的Redis Web界面管理工具。基于.NET实现。可以通过Mono部署到Linux上，下面是我部署在CentOS 5.7 ＋ Mono 2.10.8 + Jexus 5.0.1：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/shanyou/201201/201201281132576347.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/shanyou/201201/201201281133058841.png" width="816" height="480" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;详情介绍：&lt;a href="http://www.servicestack.net/mythz_blog/?p=381"&gt;http://www.servicestack.net/mythz_blog/?p=381&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;项目地址：&lt;a title="https://github.com/ServiceStack/ServiceStack.RedisWebServices" href="https://github.com/ServiceStack/ServiceStack.RedisWebServices"&gt;https://github.com/ServiceStack/ServiceStack.RedisWebServices&lt;/a&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;源码下载地址：&lt;a title="https://github.com/ServiceStack/ServiceStack.RedisWebServices/downloads" href="https://github.com/ServiceStack/ServiceStack.RedisWebServices/downloads"&gt;https://github.com/ServiceStack/ServiceStack.RedisWebServices/downloads&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;立刻体验：&lt;a href="http://www.servicestack.net/RedisAdminUI/AjaxClient/#"&gt;http://www.servicestack.net/RedisAdminUI/AjaxClient/#&lt;/a&gt; 或者 &lt;a title="http://cms.win8charm.com:8080/AjaxClient/" href="http://cms.win8charm.com:8080/AjaxClient/"&gt;http://cms.win8charm.com:8080/AjaxClient/&lt;/a&gt; （有效期2012年2月17日）。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/shanyou/aggbug/2330478.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/shanyou/archive/2012/01/28/2330478.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/shanyou/archive/2012/01/28/2330451.html</id><title type="text">Redis 起步</title><summary type="text">Rdis和JQuery一样是纯粹为应用而产生的，这里记录的是在CentOS 5.7上学习入门文章： 1.安装Redis redis的安装出奇的简单，这可能也是他风靡的一个原因，让人很容易上手，不像...</summary><published>2012-01-28T02:00:00Z</published><updated>2012-01-28T02:00:00Z</updated><author><name>张善友</name><uri>http://www.cnblogs.com/shanyou/</uri></author><link rel="alternate" href="http://www.cnblogs.com/shanyou/archive/2012/01/28/2330451.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/shanyou/archive/2012/01/28/2330451.html"/><content type="html">&lt;p&gt;Rdis和JQuery一样是纯粹为应用而产生的，这里记录的是在CentOS 5.7上学习入门文章：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;1.Redis简介&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://code.google.com/p/redis/"&gt;&lt;img style="display: inline; border: 0px;" title="redis" src="http://images.cnblogs.com/cnblogs_com/shanyou/201201/201201281031521927.png" alt="redis" width="116" height="90" border="0" /&gt; Redis&lt;/a&gt;是一个key-value存储系统。和Memcached类似，但是解决了断电后数据完全丢失的情况，而且她支持更多无化的value类型，除了和string外，还支持lists（链表）、sets（集合）和zsets（有序集合）几种数据类型。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作，而且这些操作都是原子性的。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;2.Redis的性能&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;下面是官方的bench-mark数据：&lt;/p&gt;&#xD;
&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&#xD;
&lt;ul&gt;&#xD;
&lt;li&gt;The test was done with 50 simultaneous clients performing 100000 requests.&lt;/li&gt;&#xD;
&lt;li&gt;The value SET and GET is a 256 bytes string.&lt;/li&gt;&#xD;
&lt;li&gt;The Linux box is running &lt;strong&gt;Linux 2.6&lt;/strong&gt;, it&amp;rsquo;s &lt;strong&gt;Xeon X3320 2.5Ghz&lt;/strong&gt;.&lt;/li&gt;&#xD;
&lt;li&gt;Text executed using the loopback interface (127.0.0.1).&#xD;
&lt;p&gt;Results: &lt;strong&gt;about 110000 SETs per second, about 81000 GETs per second.&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;/li&gt;&#xD;
&lt;/ul&gt;&#xD;
&lt;/blockquote&gt;&#xD;
&lt;p&gt;更多详细数据请见官方bench-mark page（&lt;a href="http://code.google.com/p/redis/wiki/Benchmarks"&gt;http://code.google.com/p/redis/wiki/Benchmarks&lt;/a&gt;）&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;strong&gt;3.安装Redis&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;Redis的代码遵循ANSI-C编写，可以在所有POSIX系统（如Linux, &lt;tt&gt;*&lt;/tt&gt;BSD, Mac OS X, Solaris等）上安装运行。而且Redis并不依赖任何非标准库，也没有编译参数必需添加。redis的安装出奇的简单，这可能也是他风靡的一个原因，让人很容易上手，不像某些东西，编译阶段就能让人完全绝望。&lt;/p&gt;&#xD;
&lt;p&gt;先去官网下载源码：&lt;/p&gt;&#xD;
&lt;p&gt;wget &lt;a href="http://redis.googlecode.com/files/redis-2.4.6.tar.gz"&gt;http://redis.googlecode.com/files/redis-2.4.6.tar.gz&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;解压：&lt;/p&gt;&#xD;
&lt;p&gt;tar &amp;ndash;zxvf redis-2.4.6.tar.gz&lt;/p&gt;&#xD;
&lt;p&gt;编译&lt;/p&gt;&#xD;
&lt;p&gt;需要说明的事，redis的安装非常简单，已经有现成的Makefile文件，直接运行make命令即可。&lt;/p&gt;&#xD;
&lt;p&gt;make&lt;/p&gt;&#xD;
&lt;p&gt;make install&lt;/p&gt;&#xD;
&lt;p&gt;Redis 由四个可执行文件：&lt;strong&gt;redis-benchmark&lt;/strong&gt;、&lt;strong&gt;redis-cli&lt;/strong&gt;、&lt;strong&gt;redis-server&lt;/strong&gt;、&lt;strong&gt;redis-stat &lt;/strong&gt;这四个文件，加上一个&lt;strong&gt;redis.conf&lt;/strong&gt;就构成了整个redis的最终可用包。它们的作用如下：&lt;/p&gt;&#xD;
&lt;ul&gt;&#xD;
&lt;li&gt;redis-server：Redis服务器的daemon启动程序&lt;/li&gt;&#xD;
&lt;li&gt;redis-cli：Redis命令行操作工具。当然，你也可以用telnet根据其纯文本协议来操作&lt;/li&gt;&#xD;
&lt;li&gt;redis-benchmark：Redis性能测试工具，测试Redis在你的系统及你的配置下的读写性能&lt;/li&gt;&#xD;
&lt;li&gt;redis-stat：Redis状态检测工具，可以检测Redis当前状态参数及延迟状况&lt;/li&gt;&#xD;
&lt;/ul&gt;&#xD;
&lt;p&gt;现在就可以启动redis了，redis只有一个启动参数，就是他的配置文件路径。&lt;/p&gt;&#xD;
&lt;p&gt;redis-server /etc/redis.conf&lt;/p&gt;&#xD;
&lt;p&gt;注意，默认复制过去的&lt;strong&gt;redis.conf&lt;/strong&gt;文件的&lt;strong&gt;daemonize&lt;/strong&gt;参数为&lt;strong&gt;no&lt;/strong&gt;，所以redis不会在后台运行，这时要测试，我们需要重新开一个终端。修改为&lt;strong&gt;yes&lt;/strong&gt;则为后台运行redis。另外配置文件中规定了pid文件，log文件和数据文件的地址，如果有需要先修改，默认log信息定向到stdout.&lt;/p&gt;&#xD;
&lt;p&gt;下面是redis.conf的主要配置参数的意义：&lt;/p&gt;&#xD;
&lt;ul&gt;&#xD;
&lt;li&gt;daemonize：是否以后台daemon方式运行&lt;/li&gt;&#xD;
&lt;li&gt;pidfile：pid文件位置&lt;/li&gt;&#xD;
&lt;li&gt;port：监听的端口号&lt;/li&gt;&#xD;
&lt;li&gt;timeout：请求超时时间&lt;/li&gt;&#xD;
&lt;li&gt;loglevel：log信息级别&lt;/li&gt;&#xD;
&lt;li&gt;logfile：log文件位置&lt;/li&gt;&#xD;
&lt;li&gt;databases：开启数据库的数量&lt;/li&gt;&#xD;
&lt;li&gt;save * *：保存快照的频率，第一个*表示多长时间，第三个*表示执行多少次写操作。在一定时间内执行一定数量的写操作时，自动保存快照。可设置多个条件。&lt;/li&gt;&#xD;
&lt;li&gt;rdbcompression：是否使用压缩&lt;/li&gt;&#xD;
&lt;li&gt;dbfilename：数据快照文件名（只是文件名，不包括目录）&lt;/li&gt;&#xD;
&lt;li&gt;dir：数据快照的保存目录（这个是目录）&lt;/li&gt;&#xD;
&lt;li&gt;appendonly：是否开启appendonlylog，开启的话每次写操作会记一条log，这会提高数据抗风险能力，但影响效率。&lt;/li&gt;&#xD;
&lt;li&gt;appendfsync：appendonlylog如何同步到磁盘（三个选项，分别是每次写都强制调用fsync、每秒启用一次fsync、不调用fsync等待系统自己同步）&lt;/li&gt;&#xD;
&lt;/ul&gt;&#xD;
&lt;p&gt;这时你可以打开一个终端进行测试了，配置文件中默认的监听端口是&lt;strong&gt;6379&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;我们可以开启一个Redis客户端进行测试&lt;/p&gt;&#xD;
&lt;p&gt;[root@SNDA-192-168-1-114 ~]# redis-cli &lt;br /&gt;Could not connect to Redis at 127.0.0.1:6379: Connection refused &lt;br /&gt;not connected&amp;gt; exit &lt;br /&gt;[root@SNDA-192-168-1-114 ~]# redis-server /etc/redis.conf &lt;br /&gt;[root@SNDA-192-168-1-114 ~]# redis-cli &lt;br /&gt;redis 127.0.0.1:6379&amp;gt; quit&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;strong&gt;4.redis数据结构&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;redis 的作者antirez曾称其为一个数据结构服务器（&lt;strong&gt;data structures server&lt;/strong&gt;），这是一个非常准确的表述，redis的所有功能就是将数据以其固有的几种结构保存，并提供给用户操作这几种结构的接口。我们可以想象我们在各种语言中的那些固有数据类型及其操作。&lt;/p&gt;&#xD;
&lt;p&gt;redis目前提供四种数据类型：&lt;strong&gt;string&lt;/strong&gt;,&lt;strong&gt;list&lt;/strong&gt;,&lt;strong&gt;set&lt;/strong&gt;及&lt;strong&gt;zset&lt;/strong&gt;(sorted set)和&lt;strong&gt;Hash&lt;/strong&gt;。&lt;/p&gt;&#xD;
&lt;ul&gt;&#xD;
&lt;li&gt;&lt;strong&gt;string&lt;/strong&gt;是最简单的类型，你可以理解成与Memcached一模一个的类型，一个key对应一个value，其上支持的操作与Memcached的操作类似。但它的功能更丰富。&lt;/li&gt;&#xD;
&lt;li&gt;&lt;strong&gt;list&lt;/strong&gt;是一个链表结构，主要功能是push、pop、获取一个范围的所有值等等。操作中key理解为链表的名字。&lt;/li&gt;&#xD;
&lt;li&gt;&lt;strong&gt;set&lt;/strong&gt;是集合，和我们数学中的集合概念相似，对集合的操作有添加删除元素，有对多个集合求交并差等操作。操作中key理解为集合的名字。&lt;/li&gt;&#xD;
&lt;li&gt;&lt;strong&gt;zset&lt;/strong&gt;是set的一个升级版本，他在set的基础上增加了一个顺序属性，这一属性在添加修改元素的时候可以指定，每次指定后，zset会自动重新按新的值调整顺序。可以理解了有两列的mysql表，一列存value，一列存顺序。操作中key理解为zset的名字。&lt;/li&gt;&#xD;
&lt;li&gt;&lt;strong&gt;Hash&lt;/strong&gt;数据类型允许用户用Redis存储对象类型,Hash数据类型的一个重要优点是,当你存储的数据对象只有很少几个key值时,数据存储的内存消耗会很小.更多关于Hash数据类型的说明请见: &lt;a href="http://code.google.com/p/redis/wiki/Hashes"&gt;http://code.google.com/p/redis/wiki/Hashes&lt;/a&gt;&lt;/li&gt;&#xD;
&lt;/ul&gt;&#xD;
&lt;p&gt;在官网上给出了所有支持的接口列表，并副副附有详细的介绍，地址：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://code.google.com/p/redis/wiki/CommandReference"&gt;http://code.google.com/p/redis/wiki/CommandReference&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;另外，作者还提供了一个非常贴心的web命令行模拟页面，供初学者试用redis，地址：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://try.redis-db.com/"&gt;http://try.redis-db.com/&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;strong&gt;5.redis数据存储&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;redis的存储分为内存存储、磁盘存储和log文件三部分，配置文件中有三个参数对其进行配置。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;save seconds updates&lt;/strong&gt;，&lt;strong&gt;save&lt;/strong&gt;配置，指出在多长时间内，有多少次更新操作，就将数据同步到数据文件。这个可以多个条件配合，比如默认配置文件中的设置，就设置了三个条件。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;appendonly yes&lt;/strong&gt;/&lt;strong&gt;no &lt;/strong&gt;，&lt;strong&gt;appendonly&lt;/strong&gt;配置，指出是否在每次更新操作后进行日志记录，如果不开启，可能会在断电时导致一段时间内的数据丢失。因为redis本身同步数据文件是按上面的save条件来同步的，所以有的数据会在一段时间内只存在于内存中。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;appendfsync no&lt;/strong&gt;/&lt;strong&gt;always&lt;/strong&gt;/&lt;strong&gt;everysec &lt;/strong&gt;，&lt;strong&gt;appendfsync&lt;/strong&gt;配置，&lt;strong&gt;no&lt;/strong&gt;表示等操作系统进行数据缓存同步到磁盘，&lt;strong&gt;always&lt;/strong&gt;表示每次更新操作后手动调用&lt;strong&gt;fsync&lt;/strong&gt;()将数据写到磁盘，&lt;strong&gt;everysec&lt;/strong&gt;表示每秒同步一次。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;strong&gt;6.redis主从配置&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;redis支持&lt;strong&gt;master-slave&lt;/strong&gt;的主从配置，配置方法是在从机的配置文件中指定&lt;strong&gt;slaveof&lt;/strong&gt;参数为主机的ip和port即可&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;strong&gt;7.redis起步(链接整理)&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;项目首页，下方是各种语言支持列表：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://code.google.com/p/redis/"&gt;http://code.google.com/p/redis/&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;作者在wiki中给出了一个非常好的例子，以使我们可以快速上手，地址：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://code.google.com/p/redis/wiki/TwitterAlikeExample"&gt;http://code.google.com/p/redis/wiki/TwitterAlikeExample&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;同时作者推荐的另一个教程，地址：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://labs.alcacoop.it/doku.php?id=articles:redis_land"&gt;http://labs.alcacoop.it/doku.php?id=articles:redis_land&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;一个redis爱好者创建的相关问题讨论网站：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://www.rediscookbook.org/"&gt;http://www.rediscookbook.org/&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;为什么使用 Redis及其产品定位&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a title="http://www.infoq.com/cn/articles/tq-why-choose-redis" href="http://www.infoq.com/cn/articles/tq-why-choose-redis"&gt;http://www.infoq.com/cn/articles/tq-why-choose-redis&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;Redis内存使用优化与存储&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a title="http://www.infoq.com/cn/articles/tq-redis-memory-usage-optimization-storage" href="http://www.infoq.com/cn/articles/tq-redis-memory-usage-optimization-storage"&gt;http://www.infoq.com/cn/articles/tq-redis-memory-usage-optimization-storage&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/shanyou/aggbug/2330451.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/shanyou/archive/2012/01/28/2330451.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry></feed>
