[转载]使用HtmlAgilityPack实现简单的博客园主页内容抓取(2014-03-31) - DavionKnight - 博客园

mikel阅读(924)

[转载]使用HtmlAgilityPack实现简单的博客园主页内容抓取(2014-03-31) – DavionKnight – 博客园.

一、时间:

2014-03-31  18:08:32,又到了下班的时间了,忙了一天,也累了,中午都没吃饭。。。。。


 

二、事件:

win8刚出来那会,有个想法,想做一个第三方的博客园软件应用,奈何技术太渣,琐事良多,只能不了了之,最近想自己做个网站,于是就想抓取园子里面的内容,因为每天看博客都会让我成长,学到很多!


 

三、实现方法:

本来想自己存取网页,利用正则解析页面,奈何到解析标题时各种问题,而且自己想想也知道效率不是很高,于是就有了使用HtmlAgilityPack(下载地址:http://htmlagilitypack.codeplex.com/,开源的dll,很不错!)来实现网页解析,也可以用微软自己的mshtml,相对而言HtmlAgilityPack更好,于是就用了!

 


 

 

四、代码简单实现:

using System;
using System.Collections;
using System.IO;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using HtmlAgilityPack;
namespace 测试
{
class Program
{
static void Main(string[] args)
{
////指定请求
//HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://www.cnblogs.com/#p2");

////得到返回
//HttpWebResponse response = (HttpWebResponse)request.GetResponse();

////得到流
//Stream recStream = response.GetResponseStream();

////编码方式
//Encoding gb2312 = Encoding.UTF8;

////指定转换为gb2312编码
//StreamReader sr = new StreamReader(recStream, gb2312);

////以字符串方式得到网页内容
//String content = sr.ReadToEnd();

WebClient wc = new WebClient();
wc.BaseAddress = "http://www.cnblogs.com/sitehome/p/2";
wc.Encoding = Encoding.UTF8;
HtmlDocument doc = new HtmlDocument();
string html = wc.DownloadString("http://www.cnblogs.com/sitehome/p/2");
doc.LoadHtml(html);
string listNode = "/html/body/div[1]/div[4]/div[6]";
string[] title = new string[20];
string[] digest = new string[20];
string[] time = new string[20];
string[] uriList = new string[20];
string str;
HtmlNode node;
for(int i=0;i<20;i++)
{
str = listNode + "/div[" + (i+1) + "]/div[2]/h3[1]";
node = doc.DocumentNode.SelectSingleNode(str);
title[i]=node.InnerText;
str = listNode + "/div[" + (i+1) + "]/div[2]/p[1]";
node = doc.DocumentNode.SelectSingleNode(str);
digest[i] = node.InnerText;
str = listNode + "/div[" + (i+1) + "]/div[2]/div[1]";
node = doc.DocumentNode.SelectSingleNode(str);
Regex r = new Regex("\\s20\\d\\d-\\d\\d-\\d\\d\\s\\d\\d:\\d\\d");
Match m = r.Match(node.InnerText);
time[i] = m.ToString();

str = listNode + "/div[" + (i + 1) + "]/div[2]/h3[1]/a[1]";
node = doc.DocumentNode.SelectSingleNode(str);
uriList[i] = node.Attributes["href"].Value;
}
foreach(string str2 in title)
{
Console.WriteLine(str2);
}
foreach (string str2 in uriList)
{
Console.WriteLine(str2);
}
foreach (string str2 in time)
{
Console.WriteLine(str2);
}
Console.ReadKey();
}

 

五、结果:

 

 


 

六、简单说明:

前20行博客主题

中间20行博客地址

后面20行时间

 


 

七、注意:

1. http://www.cnblogs.com/sitehome/p/2 :主页第二页,前面使用http://www.cnblogs.com/#p2一直不行,看了源码部分的js才明白,

2.本人技术有限,不喜勿喷,但是欢迎提意见交流,

3.本人新建一群:交友&&知识学习&&职业交流,希望:互帮互助,互相学习。。。。闲人勿进,有意请冒泡一下!

[转载]那些年一起用过的iOS开发利器 - LloydSheng - 博客园

mikel阅读(1053)

[转载]那些年一起用过的iOS开发利器 – LloydSheng – 博客园.

CodePilot

CodePilot , Code Pilot 是一个 Xcode 5 插件,允许你不许使用鼠标就能快速地查找项目内的文件、方法和标识符。它使用模糊查询匹配(fuzzy query matching)去计算出一个根据相关性排序好结果列表;通过少许的按键你就可以跳到你想要查找的方法了。

cocoapods

cocoapodsCocoaPods 是一个负责管理iOS项目中第三方开源代码的工具。CocoaPods项目的源码在Github上管理。该项目开始于2011年8月12日,经过一年多的 发展,现在已经超过1000次提交,并且持续保持活跃更新。开发iOS项目不可避免地要使用第三方开源库,CocoaPods的出现使得我们可以节省设置 和更新第三方开源库的时间。 

Parse

ParseParse是一 群美国人开发的专为移动APP服务的云计算平台,与现有的其他云计算平台相比,Parse除了提供Restful的service 之外,也提供了官方的iOS和Android SDK。个人认为高质量的client端SDK是Parse区分与其他云服务的核心优势。

内测宝

内测宝, 个人觉得比TestFlight更简单好用,开发者只需要简单把打好的ipa包上传上去,获得一个短链接,测试人员在手机浏览器中打开这个项目链接,就可以直接安装最新的测试版本了,好用的让人想哭。

SimPholders

SimPholders, SimPholders是一个快速简单的小工具,可以帮助开发者快速访问iPhone模拟器应用。它可以访问模拟器的文件夹,重置库和文件,以及删除选定的应用程序。

[转载]ASP.NET Identity登录原理 - Claims-based认证和OWIN - Jesse Liu - 博客园

mikel阅读(1118)

[转载]ASP.NET Identity登录原理 – Claims-based认证和OWIN – Jesse Liu – 博客园.

目录

ASP.NET Identity登录原理

废话少说,我们直接切入正题。在上一篇从Membership到ASP.NET Identity,我们已经给了一个简单的实例,并且大致的描述了一下ASP.NET Identity的结构体系,但是ASP.NET Identity主要提供的功能是帮助我们管理用户,角色等信息,它主要负责的是存储这一块,也就是我们的信息存到哪里去的问题。但是用户是如何实现登录的? 是Forms认证么?用到Cookie了么Cookie里面有保存明文信息么(咳咳,最近某程旅游网好像很火?),接下来我们就来一一的回答这些问题。

在上一篇的例子中,我们可以简单的发现,要实现登录实际上只有简单的三行代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
private IAuthenticationManager AuthenticationManager
{
get { return HttpContext.GetOwinContext().Authentication; }
}
private async Task SignInAsync()
{
// 1. 利用ASP.NET Identity获取用户对象
var user = await UserManager.FindAsync("UserName", "Password");
// 2. 利用ASP.NET Identity获取identity 对象
var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
// 3. 将上面拿到的identity对象登录
AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = true }, identity);

我们发现UserManager.CreateIdentityAsync返回给我们的对象是一个ClaimsIdentity,这又是一个什么玩意?它和我们原来所熟知的Identity对象有什么关联么?毕竟长的那么像,在深入之前,我们先要了解一下下面的概念。

什么是Claims-based(基于声明)的认证

首先这个玩意不是微软特有的,Claims-based认证和授权在国外被广泛使用,包括微软的ADFS,Google,Facebook等。 国内我就不知道了,没有使用过国内的第三方登录,有集成过QQ登录或者支付宝登录的同学可以解释一下。

Claims-based认证主要解决的问题?

  对比我们传统的Windows认证和Forms认证,claims-based认证这种方式将认证和授权与 登录代码分开,将认证和授权拆分成另外的web服务。活生生的例子就是我们的qq集成登录,未必qq集成登录采用的是claims-based认证这种模 式,但是这种场景,千真万确就非常适合claims-based认证。

Claims-based认证的主要特点:

  • 将认证与授权拆分成独立的服务
  • 服务调用者(一般是网站),不需要关注你如何去认证,你用Windows认证也好,用令牌手机短信也好,与我无关。
  • 如果用户成功登录的话,认证服务(假如是QQ) 会返回给我们一个令牌。
  • 令牌当中包含了服务调用者所需要的信息,用户名,以及角色信息等等。

总的来说就是,我再也不用管你怎么登录,怎么样去拿你有哪些角色了,我只需要把你跳到那个登录站点上,然后它返回给我令牌信息,我从令牌上获取需要的信息来确定你是谁,你拥有什么角色就可以了。 

  进一步理解Claims-based 认证

  为了让大家进一步理解Claims-based认证,我们从一个普通的登录场景开始说起,拿QQ集成登录来举例。

  1. 用户跑到我们的网站来访问一个需要登录的页面
  2. 我们的网站检测到用户没有登录,返回一个跳转到QQ登录页的响应(302 指向QQ登录页面的地址并加上一个返回的链接页面,通常是returnUrl=)
  3. 用户被跳转到指定QQ的登录页面
  4. 用户在QQ登录页面上输入用户名和密码,QQ会到自己的数据库中查询,一旦登录成功,会返回一个跳转到我们站点的响应(302指向我们的网站页面)
  5. 用户被跳转到我们网站的一个检测登录的页面,我们可以拿到用户的身份信息,建立ClaimsPrinpical和ClaimsIdentity对象,生成cookie等。
  6. 我们再把用户带到指定的页面,也就是returnUrl,那是用户登录前最后一次访问的页面

简单的来说,就是把登录的代码(验证用户,获取用户信息)拆分成独立的服务或组件。

ASP.NET 下的 Claims-based认证实现

说完什么是Claims-based认证之后,我们接下来就可以看看ClaimsIdentity以及ClaimsPrincipal这两个 类,他们是.NET下Claims-based认证的主要基石。当然正如我们所想,他们继承了接口IIdentity和IPrincipal。

IIdentity封装用户信息

  这个接口很简单,它只包含了三个最基本的用户身份信息。

IPrincipal 代表着一个安全上下文

  这个安全上下文对象包含了上面的identity以及一些角色和组的信息,每一个线程都会关联一个Principal的对象,但是这个对象是属性进程或者AppDomain级别的。ASP.NET自带的 RoleProvider就是基于这个对象来实现的。

CalimsIdentity和ClaimsPrincipal

  在System.Security.Claims命名空间下去,我们可以发现这两个对象。下面我们来做一个 小例子,这个小例子会告诉我们这两个对象是如何进行认证和授权的。我们要做的demo很简单,建一个空的mvc站点,然后加上一个 HomeController,和两个Action。并且给这个HomeController打上Authroize的标签,但是注意我们没有任何登录的 代码,只有这个什么也没有的Controller和两个什么也没有的Action。

当然,结果也是可想而知的,我们得到了401页面,因为我们没有登录。

下面我们就来实现登录,这里的登录非常简单,我们手动去创建这个ClaimsIdentity和ClaimsPrincipal对象,然后将Principal对象指给当前的HttpContext.Current.User。

我们在Global.asax中添加了Application_AuthenticateRequest方法,也就是每次MVC要对用户进行认证的时候都会进到我们这个方法里面,然后我们就这样神奇的把用户给登录了。

当然,我们没有Home/Manager的访问权限,因为我们上面只给了用户Users的Role。  

现在大家知道ClaimsIdentity和ClaimsPrincipal是如何使用了么?这里要注意一 下的是,我们没有设置IsAutheiticated为true,在.NET4.5以前,对于GenericIdentity只要设置它的Name的时候 IsAutheiticated就自动设置为true了,而对于ClaimsIdentity是在它有了第一个Claim的时候。在.NET4.5以后, 我们就可以灵活控制了,默认ClaimsIdentity的IsAutheiticated是false,只有当我们构造函数中指定 Authentication Type,它才为true。

最后结论,我们讲了ClaimsIdentity什么的,讲了这么多和今天的主题有嘛关系?我们上面说ASPNET Identity登录有三句话,第一句话可以略过,第二句话就是我们上面讲的。

1
var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);

UserManager实际上只是为我们创建了一个ClaimsIdentity的对象,还是通过我们自己从数据库里面取出来的对象来创建的, 它也就干了那么点事,一层小小的封装而已。不要被后面的DefaultAuthenticationTypes.ApplicationCookie吓到 了,这里还没有和cookie扯上半点关系,这就是一个字符串常量,和我们上面自己定义的MyClaimsLogin是没有区别的。

到这里,我想算是把登录代码的第二句话讲完了,讲清楚了,那么我们来看看第三句话,也就是最后一句,其实它才是登录的核心,第二句只是创建了一个ClaimsIdentity的对象。

1
2
3
4
5
private IAuthenticationManager AuthenticationManager
{
get { return HttpContext.GetOwinContext().Authentication; }
}
AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = true }, identity);

通过F12查看,发现IAuthenticationManager 在  Microsoft.Owin.Security命名空间下,而这个接口是定义在Microsoft.OWin.dll中的。这又是个什么玩意儿?带着这个疑问,我开始了我的OWin学习之旅。

到底什么是OWIN

首先我们来简单介绍一下OWin,它是由微 软ASP.NET小组成员组织成立的一个开源项目。目标是解耦服务器和应用,这里面的服务器主要是指web 服务器,比如说IIS等,全称是Open Web Interface for .Net。OWin可以说是一套定义,默认它是没有什么具体的实现的,那么在它的定义里面是如何实现服务器与应用程序的解耦的呢? 我们又该如何理解服务器与应用程序的解耦呢?

下面是个人的理解,抛砖引玉,希望大家多探讨。

问题引入: 为什么要解耦服务器与应用程序 ?

  既然是服务器和应用程序的解耦,那么这肯定是我们第一个应该考虑的问题。我们先来简单复习一下 ASP.NET 或者是IIS 集成模式管道模型,也就是说一个http请求在进入IIS之后 (我们这里指7.0及以后版本的集成模式),一直到返回response这中间所经历的步骤。

大家知道,我们可以开发自己的Http Module去注册这些事件,然后做相应的处理。比如说FormsAuthenticationModule就是注册了 AuthenticateRequest事件,然后在这里面去检查用户的cookie信息来判断用户是否登录的,这里就是一个典型的应用程序与服务器之间的交互问题。而这些事件最后是被IIS触发的,我们是通过web.config把我们自定义的http module注册进了iis。回到我们的问题,如果我们的网站不运行在iis了,我们自己开发的这些Http module还能使用么?

另外的问题就是,大家知道我们在ASP.NET 里面经常用到HttpContext,HttpApplicationt等对象,而ASP.NET所有的处理基本上都离不开这两个对象,因为我们的 Request以及Response都是封装在HttpContext里面的,而这些信息是从IIS中来,最后也是交给IIS处理,因为微软给IIS写代 码的时候直接集成了这一块,但是想一下,如果web服务器不是IIS,那么这些信息又从哪里获取呢?

为什么需要解耦,是因为他们彼此之间的依懒过大,从而导致我们不能够轻易的换掉其中任何一个。 即使现在,在web.config添加自己定义的http module 也不是一件能让人开心的事情,反正我一想到那个很长的类名以及程序集名就够蛋疼的。

显然,很多人已经开始意识到,在如今web飞快发展的年代,这种模式已经不能够满足灵活多变的需求。越是轻量级,组件化的东西,越能够快速适应 变化,更何况.NET现在要吸引开源社区的注意,只有把这一块打通了,越来越多的强大的开源组件才能够出现在.NET的世界里,比如说写一个开源的 ASP.NET web服务器。

OWin如何做到解耦

我们上面说Owin是一套定义,它通过将服务器与应用程序之间的交互归纳为一个方法签名,称之为“应用程序代理(application delegate)”

1
AppFunc = Func<IDictionary<string, object>, Task>;

在一个基于Owin的应用程序中的每一个组件都可以通过这样的一个代理来与服务器进行交互。 这们这里的交互其实是与服务器一起来处理http request,比如说ASP.NET管理模型中的那些事件,认证,授权,缓存等等,原先我们是通过自定义的http module,在里面拿到包含了request和response的HttpContext对象,进行处理。而现在我们能拿到的就是一个 Dictionary。

可是别小看了这个Dictionary,我们所有的信息比如Application state, request state,server state等等这些信息全部存在这个数据结构中。这个dictionary会在Owin处理request的管道中进行传递,没错有了OWin之后,我们 就不再是与ASP.NET 管道打交道了,而是OWin的管道,但是这个管道相对于ASP.NET 管道而言更灵活,更开放。

这个字典在OWin管道的各个组件中传输时,你可以任意的往里面添加或更改数据。 OWin默认为我们定义了以下的数据:

有了这些数据以后,我们就不需要和.NET的那些对象打交道了,比如说ASP.NET MVC中的HttpContextBase, 以及WEB API  中的HttpRequestMessage 和HttpResponseMessage。我们也不需要再考虑system.web 这个dll里的东西,我们只需要通过OWin就可以拿到我们想要的信息,做我们想做的事了。而OWin,它本身和web服务器或者IIS没有任何关系。

微软对OWin的开源实现Katana

我们上面讲到了OWin只是一套定义,它本身没有任何代码,我们可以把它看成是微软对外公开的一套标准。那么我们用到的Microsoft.OWin,这些dll又是从哪里来的呢? 好消息是它是开源的,代码我们可以从CodePlex上下载,坏消息是它现在还没有比较全的文档,可能是我暂时还没有找到。

它包括下面4个组件:

  • Host: 托管我们应用程序的进程,或者宿主,可以是IIS,可以我们自己写的程序等。主要是用来启动,加载OWin组件,以及合理的关闭他们
  • Server: 这个Server就是用来暴露TCP端口,维护我们上面讲到的那个字典数据,然后通过OWin管理处理http请求
  • Middleware : 这个中间件就是用来在OWin管道中处理请求的组件,你可以把它想象成一个自定义的httpModule,它会被注册到OWin管道中一起处理http request
  • Application: 这个最好理解,就我们自己开发的那个应用程序或者说是网站

  也就是说我们用到的Microsoft.OWin,那一系列的dll实现上是叫Katana(武士刀)象征着快,狠,准!下面来一些名词解释,是一些简单的概念有助于大家理解我们下面要讲的内容(ASP.NET Identity是如何借助 OWin来实现登录的)。

OWin Application( OWin 应用程序 )

  这个程序引入了OWin的dll,同时会使用OWin中的一些组件完成对request的一些处理,比如说我们下面要讲的OWin 认证。

OWin 组件

  我们也可能管它叫中间件,它通过暴露一个应用程序代理,也就是接收一个IDictionary<string,object>,返回一个Task来参与到OWin对request和处理管道中。

Start up 类

  每一个OWin的应用程序都需要有一个start up的类,用来声明我们要使用的OWin组件(即中间件)。Start up 类有以下几种声明方式:

  1. 命名约定: Owin会扫描在程序集的根下名叫 startup的类作为默认启动配置类
  2. OwinStartup 标签
    1
    [assembly: OwinStartup(typeof(StartupDemo.TestStartup))]
  3. config 文件
    1
    <add key="owin:AutomaticAppStartup " value="false" />

 OWin authentication

Owin的很大亮点之一就是它可以让我们的ASP.NET 网站摆脱IIS,但是毕竟大多数的ASP.NET 网站还是host在IIS上的,所以Katana项目还支持在IIS集成模式中运行Owin组件。 我们只需要在我们的项目中加上Microsoft.Owin.Host.SystemWeb这个包就可以了,其实默认MVC5程序已经为我们加上了。我们在VS2013中新建一个MVC5的站点,默认会为我们加上以下的dll:

  • OWin.dll
  • Microsoft.Owin.dll
  • Microsoft.Owin.Host.SystemWeb
  • Microsoft.Owin.Security
  • Microsoft.Owin.Security.Cookie

  他们对应nuget中的package:

  

  这就是为什么我们可以拿到Microsoft.Owin.Security.IAuthenticationManager,然后 再调用其 SignIn方法和SignOut方法。除了多了这些dll以外,VS还自动帮我们移除了FormsAuthenticationModule。

Forms 认证

我们来小小的复杂一下Forms认证,在Forms认证中我们检测完用户名和密码之后,只需要调用下面的代码就会为我们创建用户cookie。

1
FormsAuthentication.SetAuthCookie("Jesse", false);

然后FormsAuthenticateionModule会在ASP.NET 管道的 AuthenticateRequest 阶段去检查是否有这个cookie,并把它转换成我们需要的identity对象,这样的话我们就不需要每一次都让用户去输入用户名和密码了。所以登录的 过程实现上是这样的。

  1. 用户在没有登录的情况下访问了我们需要登录的页面
  2. FormsAuthenticationModule检查不到用户身份的cookie,没有生成identity对象,HttpContext.User.IsAuthenticated = false
  3. 在ASP.NET 管道 的Authroize 授权阶段,将用户跳转到登录页面
  4. 用户输入用户名和密码点击提交
  5. 我们检查用户名和密码,如果正确,就调用FormsAuthentication.SetAuthCookie方法生成登录cookie
  6. 用户可以正常访问我们需要登录的页面了
  7. 用户再次访问我们需要登录的页面
  8. FormsAuthenticationModule检查到了用户身份的cookie,并生成identity对象,HttpContext.User.IsAuthenticated = true
  9. ASP.NET 管道的 Authroize授权阶段,HttpContext.User.IsAuthenticated=true,可以正常浏览
  10. 7,8,9 循环

Forms认证有以下几不足:

  1. 用户名直接暴露在cookie中,需要额外的手段去将cookie加密
  2. 不支持claims-based 认证
  3. ….

我们上面Forms的登录过程,对于OWin登录来说同样适用。我们在上面讲ASP.NET Identity登录第二句话的时候已经拿到了ClaimsIdentity,那么我们接下来要看的问题就是如何借助于 IAuthenticationManager 去登录? FormsAuthenticationModuel没有了,谁来负责检测cookie?您请接着往下看!

MVC 5默认的start up配置类

VS除了为我们引用OWin相关dll,以及移除FormsAuthenticationModule以外,还为我们在App_Start文件夹里添加了一个Startup.Auth.cs的文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
public partial class Startup
{
    public void ConfigureAuth(IAppBuilder app)
    {
        // 配置Middleware 組件
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            LoginPath = new PathString("/Account/Login"),
            CookieSecure = CookieSecureOption.Never,
        });
    }
}

UseCookieAuthentication是一IAppBuilder 的一个扩展方法,定义在Microsoft.Owin.Security.Cookies.dll中。

CookieAuthenticationExtensions.cs

1
2
3
4
5
6
7
8
9
10
11
public static IAppBuilder UseCookieAuthentication(this IAppBuilder app,
    CookieAuthenticationOptions options)
{
    if (app == null)
    {
        throw new ArgumentNullException("app");
    }
    app.Use(typeof(CookieAuthenticationMiddleware), app, options);
    app.UseStageMarker(PipelineStage.Authenticate);
    return app;
}

将Owin Middleware绑定到IIS 集成模式的管道

UseCookieAuthentication主要调用了两个方法:

  • IAppBuilder.Use : 添加OWin middleware 组件到 OWin 管道
  • IAppBuilder.UseStageMarker : 为前面添加的middleware指定在IIS 管道的哪个阶段执行。

  PepelineStage这个枚举定义和我们IIS管道的那些顺序,也就是和我们Http Module里面可以绑定的那些事件是一样的。

我们可以回顾一样如何在http module中为Authenticate绑定事件。

1
2
3
4
5
6
7
8
9
10
11
public class MyModule : IHttpModule
{
    public void Init(HttpApplication context)
    {
        // 將ctx_AuthRequest 綁定的 AuthenticateRequest 事件
        context.AuthenticateRequest += ctx_AuthRequest;
    }
    void ctx_AuthRequest(object sender, EventArgs e)
    {
    }
}

Owin这里的Use,貌似是借用了Node.js的用法呀- -! 不管怎么说,通过这样一种方式,我们就可以将Owin 中间件注册进IIS 集成模式的管道了。也就是说我们上面注册的CookieAuthenticationMiddleware会在AuthenticaRequest 阶段执行。而它就是真正生成cookie以及读取cookie的那只背后的手。

CookieAuthenticationMiddelware 负责读取用户信息cookie

如果你看的还算认真的话,我们上面讲claims-based认证的时候有一个小例子。我们只需要在AuthenticateRequest阶段将 ClaimsPrincipal赋给当前的User对象就可以实现登录了,而这也是IAuthenticationManager.SignIn所做的。 但是我们上面讲Forms登录的过程一样,用户登录之后,我们需要生成cookie,这样用户下次访问的时候就不需要登录了,我们在 Authenticate Request去检测有没有这个cookie就可以了,CookieAuthenticationMiddleware就负责做了这两件事情。

我们可以到Katana的站点去下载源码,然后找到CookieAuthenticationMiddleware这个类,然后找到最后生成cookie和读取cookie的类:CookieAuthenticationHandler。

在CookieAuthenticationMiddleware中有两个方法:

  • AuthenticateCoreAsync : 从request中读取cookie值,附给到identity对象,没有什么内幕,就是读读cookie进行解密,转成identity对象。
  • ApplyResponseGrantAsync : 往response中写入cookie值,同样没有什么内幕,有兴趣的同学可以下载katana源码瞅瞅。

CookieAuthenticationMiddelware 对cookie的加密方式

在我们上篇文章中对ASP.NET Identity登录的例子中,如果你登录了,那么你会发现我们的cookie是经过加密的。而cookie的名称是以.AspNet.为前缀加上我们

Startup中配置的AuthenticationType。

那么接下来,我们就来看一下CookieAuthenticationMiddleware是以什么样的加密方式将我们的identity信息加密的,我们能不能将它解回来呢?

欲知后事如何,请听下回分解~

参考&小结

这一篇文章涉及到的新东西比较多,也花了我不少的时间。但是总的来说收获还是蛮大的,把Claims-based总结性的概括了一下,然后又开 始了Owin的学习之旅。越来越发现.NET的强大,在开源社区的不断贡献下.NET也逐渐开始绽放出新的生命力。后面还会继续Owin的学习,有兴趣的 朋友可以继续关注!还是我一直强调的,虽然ASP.NET Identity登录只有三行代码,但是背后却隐藏的如此之深,如果你不怀着一颗好奇以及好学的心,你永远不知道背后有多么美丽的故事。如果只是习惯了使 用框架,而不去了解它,那就会迷失在学习新技术的路上。但是如果你知道它的设计原理,你就会发现其实都差不多的,思想就是那么一套,但是外观却可能随时改 变。 另外的话我觉得这篇文章写的不错,值得点赞,你觉得呢?

我是Jesse Liu,关注我,跟我一起探寻.NET 那些新鲜,好玩,以及背后的故事吧 🙂

参考资料:

  • http://owin.org/
  • http://brockallen.com/2013/10/24/a-primer-on-owin-cookie-authentication-middleware-for-the-asp-net-developer/
  • http://www.asp.net/aspnet/overview/owin-and-katana/an-overview-of-project-katana
  • http://www.asp.net/aspnet/overview/owin-and-katana/owin-middleware-in-the-iis-integrated-pipeline
  • http://www.asp.net/aspnet/overview/owin-and-katana/owin-startup-class-detection
  • http://msdn.microsoft.com/en-us/library/ff359101.aspx

[转载]Android的Task和Activity相关 - Cyning - 博客园

mikel阅读(899)

[转载]Android的Task和Activity相关 – Cyning – 博客园.

Android:allowTaskReparenting
    用来标记Activity能否从启动的Task移动到有着affinity的Task(当这个Task进入到前台时)——“true”,表示能移动,“false”,表示它必须呆在启动时呆在的那个Task里。
如果这个特性没有被设定,设定到<application>元素上的allowTaskReparenting特性的值会应用到Activity上。默认值为“false”。
一般来说,当Activity启动后,它就与启动它的Task关联,并且在那里耗尽它的整个生命周期。当当前的Task不再显示时,你可以使用这个特性来 强制Activity移动到有着affinity的Task中。典型用法是:把一个应用程序的Activity移到另一个应用程序的主Task中。
例如,如果e-mail中包含一个web页的链接,点击它就会启动一个Activity来显示这个页面。这个Activity是由Browser应用程序 定义的,但是,现在它作为e-mail Task的一部分。如果它重新宿主到Browser Task里,当Browser下一次进入到前台时,它就能被看见,并且,当e-mail Task再次进入前台时,就看不到它了。
Actvity的affinity是由taskAffinity特性定义的。Task的affinity是通过读取根Activity的affinity 决定。因此,根据定义,根Activity总是位于相同affinity的Task里。由于启动模式为“singleTask”和 “singleInstance”的Activity只能位于Task的底部,因此,重新宿主只能限于“standard”和“singleTop”模 式。

Android:alwaysRetainTaskState
    用来标记Activity所在的Task的状态是否总是由系统来保持——“true”,表示总是;“false”,表示在某种情形下允许系统恢复Task 到它的初始化状态。默认值是“false”。这个特性只针对Task的根Activity有意义;对其它Activity来说,忽略之。
一般来说,特定的情形如当用户从主画面重新选择这个Task时,系统会对这个Task进行清理(从stack中删除位于根Activity之上的所有Activivity)。典型的情况,当用户有一段时间没有访问这个Task时也会这么做,例如30分钟。
然而,当这个特性设为“true”时,用户总是能回到这个Task的最新状态,无论他们是如何启动的。这非常有用,例如,像Browser应用程序,这里有很多的状态(例如多个打开的Tab),用户不想丢失这些状态。

Android:clearTaskOnLaunch
    用来标记是否从Task中清除所有的Activity,除了根Activity外(每当从主画面重新启动时)——“true”,表示总是清除至它的根 Activity,“false”表示不。默认值是“false”。这个特性只对启动一个新的Task的Activity(根Activity)有意义; 对Task中其它的Activity忽略。
当这个值为“true”,每次用户重新启动这个Task时,都会进入到它的根Activity中,不管这个Task最后在做些什么,也不管用户是使用 BACK还是HOME离开的。当这个值为“false”时,可能会在一些情形下(参考alwaysRetainTaskState特性)清除Task的 Activity,但不总是。
假设,某人从主画面启动了Activity P,并从那里迁移至Activity Q。接下来用户按下HOME,然后返回Activity P。一般,用户可能见到的是Activity Q,因为它是P的Task中最后工作的内容。然而,如果P设定这个特性为“true”,当用户按下HOME并使这个Task再次进入前台时,其上的所有的 Activity(在这里是Q)都将被清除。因此,当返回到这个Task时,用户只能看到P。
如果这个特性和allowTaskReparenting都设定为“true”,那些能重新宿主的Activity会移动到共享affinity的Task中;剩下的Activity都将被抛弃,如上所述。

android:finishOnTaskLaunch
    用来标记当用户再次启动它的Task(在主画面选择这个Task)时已经存在的Activity实例是否要关闭(结束)——“true”,表示应该关闭,“false”表示不关闭。默认值是“false”。
如果这个特性和allowTaskReparenting都设定为“true”,这个特性胜出。Activity的affinity忽略。这个Activity不会重新宿主,但是会销毁。

android:launchMode
    用于指示Activity如何启动。这里有四种模式,与Intent对象中的Activity Flags(FLAG_ACTIVITY_*变量)共同作用,来决定Activity如何启动来处理Intent。它们是:

“standard”
“singleTop”
“singleTask”
“singleInstance”

默认模式是“standard”。

这些模式可以分成两大组别,“standard”和“singleTop”一组,“singleTask”和“singleInstance”一组。具有 “standard”和“singleTop”启动模式的Activity可以实例化很多次。这些实例可以属于任何Task并且可以位于Activity stack的任何位置。典型的情况是,它们会进入调用startActivity()的Task(除非Intent对象包含 FLAG_ACTIVITY_NEW_TASK标志,在这种情况下会选择一个不同的Task——参考taskAffinity特性)。
相反的,“singleTask”和“singleInstance”只能启动一个Task。它们总是位于Activity stack的底部。甚至,设备一次只能拥有一个Activity的实例——只有一个这样的Task。
“standard”和“singleTop”模式只在一种情况下有差别:每次有一个新的启动“standard”Activity的Intent,就会 创建一个新的实例来响应这个Intent。每个实例处理一个Intent。相似的,一个“singleTop”的Activity实例也有可能被创建来处 理新的Intent。然而,如果目标Task已经有一个存在的实例并且位于stack的顶部,那么,这个实例就会接收到这个新的Intent(调用 onNewIntent());不会创建新的实例。在其他情况下——例如,如果存在的“singleTop”的Activity实例在目标Task中,但 不是在stack的顶部,或者它在一个stack的顶部,但不是在目标Task中——新的实例都会被创建并压入stack中。
“singleTask”和“singleInstance”模式也只在一种情况下有差别:“singleTask”Activity允许其它 Activity成为它的Task的部分。它位于Activity stack的底部,其它Activity(必须是“standard”和“singleTop”Activity)可以启动加入到相同的Task中。 “singleInstance”Activity,换句话说,不允许其它Activity成为它的Task的部分。它是Task中的唯一 Activity。如果它启动其它的Activity,这个Activity会被放置到另一个task中——好像Intent中包含了 FLAG_ACTIVITY_NEW_TASK标志。

android:noHistory
    用于标记当用户从Activity上离开并且它在屏幕上不再可见时Activity是否从Activity stack中清除并结束(调用finish()方法)——“true”,表示它应该关闭,“false”,表示不需要。默认值是“false”。
“true”值意味着Activity不会留下历史痕迹。因为它不会在Activity stack的Task中保留,因此,用户不能返回它。

android:taskAffinity
   Activity为Task拥有的一个affinity。拥有相同的affinity的Activity理论上属于相同的Task(在用户的角度是相同的“应用程序”)。Task的affinity是由它的根Activity决定的。
affinity决定两件事情——Activity重新宿主的Task(参考allowTaskReparenting特性)和使用FLAG_ACTIVITY_NEW_TASK标志启动的Activity宿主的Task。
默认情况,一个应用程序中的所有Activity都拥有相同的affinity。捏可以设定这个特性来重组它们,甚至可以把不同应用程序中定义的Activity放置到相同的Task中。为了明确Activity不宿主特定的Task,设定该特性为空的字符串。
如果这个特性没有设置,Activity将从应用程序的设定那里继承下来(参考<application>元素的taskAffinity特 性)。应用程序默认的affinity的名字是<manifest>元素中设定的package名。

FLAG_ACTIVITY_BROUGHT_TO_FRONT
    这个标志一般不是由程序代码设置的,如在launchMode中设置singleTask模式时系统帮你设定。

FLAG_ACTIVITY_CLEAR_TOP
    如果设置,并且这个Activity已经在当前的Task中运行,因此,不再是重新启动一个这个Activity的实例,而是在这个Activity上方 的所有Activity都将关闭,然后这个Intent会作为一个新的Intent投递到老的Activity(现在位于顶端)中。
例如,假设一个Task中包含这些Activity:A,B,C,D。如果D调用了startActivity(),并且包含一个指向Activity B的Intent,那么,C和D都将结束,然后B接收到这个Intent,因此,目前stack的状况是:A,B。
上例中正在运行的Activity B既可以在onNewIntent()中接收到这个新的Intent,也可以把自己关闭然后重新启动来接收这个Intent。如果它的启动模式声明为 “multiple”(默认值),并且你没有在这个Intent中设置FLAG_ACTIVITY_SINGLE_TOP标志,那么它将关闭然后重新创 建;对于其它的启动模式,或者在这个Intent中设置FLAG_ACTIVITY_SINGLE_TOP标志,都将把这个Intent投递到当前这个实 例的onNewIntent()中。
这个启动模式还可以与FLAG_ACTIVITY_NEW_TASK结合起来使用:用于启动一个Task中的根Activity,它会把那个Task中任 何运行的实例带入前台,然后清除它直到根Activity。这非常有用,例如,当从Notification Manager处启动一个Activity。

FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET
    如果设置,这将在Task的Activity stack中设置一个还原点,当Task恢复时,需要清理Activity。也就是说,下一次Task带着 FLAG_ACTIVITY_RESET_TASK_IF_NEEDED标记进入前台时(典型的操作是用户在主画面重启它),这个Activity和它之 上的都将关闭,以至于用户不能再返回到它们,但是可以回到之前的Activity。
这在你的程序有分割点的时候很有用。例如,一个e-mail应用程序可能有一个操作是查看一个附件,需要启动图片浏览Activity来显示。这个 Activity应该作为e-mail应用程序Task的一部分,因为这是用户在这个Task中触发的操作。然而,当用户离开这个Task,然后从主画面 选择e-mail app,我们可能希望回到查看的会话中,但不是查看图片附件,因为这让人困惑。通过在启动图片浏览时设定这个标志,浏览及其它启动的Activity在下 次用户返回到mail程序时都将全部清除。

FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
    如果设置,新的Activity不会在最近启动的Activity的列表中保存。

FLAG_ACTIVITY_FORWARD_RESULT
    如果设置,并且这个Intent用于从一个存在的Activity启动一个新的Activity,那么,这个作为答复目标的Activity将会传到这个 新的Activity中。这种方式下,新的Activity可以调用setResult(int),并且这个结果值将发送给那个作为答复目标的 Activity。

FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
    这个标志一般不由应用程序代码设置,如果这个Activity是从历史记录里启动的(常按HOME键),那么,系统会帮你设定。

FLAG_ACTIVITY_MULTIPLE_TASK
    不要使用这个标志,除非你自己实现了应用程序启动器。与FLAG_ACTIVITY_NEW_TASK结合起来使用,可以禁用把已存的Task送入前台的 行为。当设置时,新的Task总是会启动来处理Intent,而不管这是是否已经有一个Task可以处理相同的事情。
由于默认的系统不包含图形Task管理功能,因此,你不应该使用这个标志,除非你提供给用户一种方式可以返回到已经启动的Task。
如果FLAG_ACTIVITY_NEW_TASK标志没有设置,这个标志被忽略。

FLAG_ACTIVITY_NEW_TASK
    如果设置,这个Activity会成为历史stack中一个新Task的开始。一个Task(从启动它的Activity到下一个Task中的 Activity)定义了用户可以迁移的Activity原子组。Task可以移动到前台和后台;在某个特定Task中的所有Activity总是保持相 同的次序。
这个标志一般用于呈现“启动”类型的行为:它们提供用户一系列可以单独完成的事情,与启动它们的Activity完全无关。
使用这个标志,如果正在启动的Activity的Task已经在运行的话,那么,新的Activity将不会启动;代替的,当前Task会简单的移入前台。参考FLAG_ACTIVITY_MULTIPLE_TASK标志,可以禁用这一行为。
这个标志不能用于调用方对已经启动的Activity请求结果。

FLAG_ACTIVITY_NO_ANIMATION
    如果在Intent中设置,并传递给Context.startActivity()的话,这个标志将阻止系统进入下一个Activity时应用 Acitivity迁移动画。这并不意味着动画将永不运行——如果另一个Activity在启动显示之前,没有指定这个标志,那么,动画将被应用。这个标 志可以很好的用于执行一连串的操作,而动画被看作是更高一级的事件的驱动。

FLAG_ACTIVITY_NO_HISTORY
    如果设置,新的Activity将不再历史stack中保留。用户一离开它,这个Activity就关闭了。这也可以通过设置noHistory特性。

FLAG_ACTIVITY_NO_USER_ACTION
    如果设置,作为新启动的Activity进入前台时,这个标志将在Activity暂停之前阻止从最前方的Activity回调的onUserLeaveHint()。
典型的,一个Activity可以依赖这个回调指明显式的用户动作引起的Activity移出后台。这个回调在Activity的生命周期中标记一个合适的点,并关闭一些Notification。
如果一个Activity通过非用户驱动的事件,如来电或闹钟,启动的,这个标志也应该传递给Context.startActivity,保证暂停的Activity不认为用户已经知晓其Notification。

FLAG_ACTIVITY_PREVIOUS_IS_TOP
    If set and this intent is being used to launch a new activity from an existing one, the current activity will not be counted as the top activity for deciding whether the new intent should be delivered to the top instead of starting a new one. The previous activity will be used as the top, with the assumption being that the current activity will finish itself immediately.

FLAG_ACTIVITY_REORDER_TO_FRONT
    如果在Intent中设置,并传递给Context.startActivity(),这个标志将引发已经运行的Activity移动到历史stack的顶端。
例如,假设一个Task由四个Activity组成:A,B,C,D。如果D调用startActivity()来启动Activity B,那么,B会移动到历史stack的顶端,现在的次序变成A,C,D,B。如果FLAG_ACTIVITY_CLEAR_TOP标志也设置的话,那么这 个标志将被忽略。

FLAG_ACTIVITY_RESET_TASK_IF_NEEDED

If set, and this activity is either being started in a new task or bringing to the top an existing task, then it will be launched as the front door of the task. This will result in the application of any affinities needed to have that task in the proper state (either moving activities to or from it), or simply resetting that task to its initial state if needed.

FLAG_ACTIVITY_SINGLE_TOP
    如果设置,当这个Activity位于历史stack的顶端运行时,不再启动一个新的。

ActivityTask

 

之前提到的,一个Activity可以启动另一个,即便是定义在不同应用程序中的Activity。例如,假设你想让用户显示一些地方的街景。而这里已经有一个Activity可以做到这一点,因此,你的Activity所需要做的只是在Intent对象中添加必要的信息,并传递给startActivity()。地图浏览将会显示你的地图。当用户按下BACK键,你的Activity会再次出现在屏幕上。

 

对于用户来说,看起来好像是地图浏览与你的Activity一样,属于相同的应用程序,即便是它定义在其它的应用程序里,并运行在那个应用程序的进程里。Android通过将这两个Activity保存在同一个Task里来体现这一用户体验。简单来说,一个Task就是用户体验上的一个“应用”。它将相关的Activity组合在一起,以stack的方式管理。stack中根Activity启动Task——典型的,它就是用户在应用程序启动栏中选择的Activity。位于stack顶端的Activity是当前正在运行的——能够聚焦用户的动作。当一个Activity启动另一个,新的Activity进入stack;它成为正在运行的Activity。之前的Activity仍保留在stack中。当用户按下BACK键,当前的Activitystack中退出,之前的那个成为正在运行的Activity

 

stack包含对象,因此,如果一个Task中有多个同一个Activity的实例时——多个地图浏览,例如——stack为每个实例拥有一个独立的入口。位于stack中的Activity不会重新调整,只是进入和退出。

 

一个Task就是一组Activity,不是一个类或者在manifest中定义的一个元素。因此,没有办法为Task设置独立于它的Activity的属性值。Task的值作为整体在根Activity中设置。例如,下一个章节会讨论Task的“affinity”;那个值就是从Task中的根Activity中读取的。

 

Task中的所有Activity作为一个单元一起移动。整个Task(整个Activity stack)可以进入前台或者退到后台。例如,假设当前Task中的stack中有4Activity——3个位于当前Activity下方。用户按下HOME键,进入到应用程序启动栏,然后选择一个新的应用程序(实际上,一个新的Task)。当前Task退到后台,并且新Task中的根Activity会显示出来。然后,经过一段时间后,用户回到Home画面,然后再次选择前一个应用程序(前一个Task)。那个拥有4ActivityTask会进入前台。当用户按下BACK键,屏幕不会显示用户刚刚离开的Activity(前一个Task的根Activity)。而是,这个stack中的顶端Activity移除,相同Task中的前一个Activity会显示出来。

 

刚才描述的行为是ActivityTask的默认行为。但有方法来完全改变它。Task之间的关联,和一个Task中的一个Activity行为,受启动ActivityIntent对象中设置的Flagmanifest文件中Activity<activity>元素的特性值交互控制。调用者和响应者都有权决定如何发生。

 

核心的Intent Flag有:

FLAG_ACTIVITY_NEW_TASK

FLAG_ACTIVITY_CLEAR_TOP

FLAG_ACTIVITY_RESET_TASK_IF_NEEDED

FLAG_ACTIVITY_SINGLE_TOP

 

核心的<activity>特性有:

taskAffinity

launchMode

allowTaskReparenting

clearTaskOnLaunch

alwaysRetainTaskState

finishOnTaskLaunch

 

接下来的章节将描述一些Flag和特性的用法,如何相互影响,以及在使用时的建议。

 

Affinity和新Task

默认情况下,一个应用程序中的所有Activity都有affinity——也就是说,属于同一个Task中所有Activity有一个设定。然而,每个Activity都可以在<activity>元素的taskAffinity特性上设置单独的值。定义在不同应用程序中的Activity可以共享同一个affinity,或者定义在同一个应用程序中的Activity设置不同的affinityAffinity在两种环境下工作:Intent对象包含FLAG_ACTIVITY_NEW_TASK标志,和ActivityallowTaskReparenting特性设置为“true”。

FLAG_ACTIVITY_NEW_TASK:

之前描述的,一个Activity一般通过调用startActivity()启动并加入到Task中。它同调用者一样,进入同一个Task。然而,如果传递给startActivity()Intent对象中包含FLAG_ACTIVITY_NEW_TASK时,系统会搜索一个新的Task来容纳新的Activity。通常,如标志的名字所示,是一个新的Task。然而,并不是必须是。如果已经存在一个Task与新Activityaffinity相同,这个Activity就会加入到那个Task中。如果不是,启动一个新的Task

allowTaskReparenting

如果一个ActivityallowTaskReparenting特性设置为“true”,它就能从启动的Task中移到有着相同affinityTask(这个Task进入到前台的时候)。例如,在一个旅游的程序中定义了一个可以报告选择城市的天气情况的Activity。它和同一个应用程序的其它Activity一样,有着相同的Affinity(默认的Affinity),并且它允许重新宿主。你的Activity中的一个启动了天气预报,因此,它初始化到和你Activity相同的Task中。然而,当旅游应用程序下一次进入到前台时,天气预报那个Activity将会重新编排并在那个Task中显示。

 

如果从用户的角度出发,一个.apk文件包含多个“应用”的话,你可能希望为关联的Activity设置不同的affinity

 

Launch Mode

 

这里4种不同的启动模式可以设置到<activity>元素的launchMode特性上:

standard(默认模式)

singleTop

singleTask

singleInstance

 

这些模式有以下四点区别:

l  哪个Task将容纳响应IntentActivity。对于“standard”和“singleTop”来说,是产生Intent的那个Task(并调用startActivity())——除非Intent对象包含FLAG_ACTIVITY_NEW_TASK。在那种情况下,不同的Task将被选择,如“Affinity和新Task”中描述的那样。对比而言,“singleTask”和“singleInstance”指示Activity总是一个Task的根。它们定义一个Task;它们不会加入到另一个Task中。

l  是否有多个Activity的实例。“standard”和“singleTop”可以实例化多次。它们可以属于多个Task,一个特定的Task可以有相同Activity的多个实例。对比而言,“singleTask”和“singleInstance”只能有一个实例。因为这些Activity只能位于Task的底部,这一限制意味着在设备的某个时间,不会出现这样Task的多个实例。

l  是否可以在同一个Task中拥有其它的Activity。“singleInstanceActivity保持单身,在它的Task中它是仅有的Activity。如果它启动另一个Activity,那个Activity将会放入到不同的Task中,而不管它的启动模式——好像FLAG_ACTIVITY_NEW_TASKIntent中一样。对于其它方面,,“singleInstance”等同于“singleTask”。其它三个模式允许多个Activity加入到这个Task中。“singleTaskActivity总是位于Task的底部,但它可以启动其它的Activity并放入到它的Task中。“standard”和“singleTop”的Activity可以出现在stack的任何地方。

l  是否一个新的实例启动来处理新的Intent。对于默认的“standard”来说,都是创建一个新的实例来响应新的Intent。每个实例处理一个Intent。对于“singleTop”来说,如果它位于目标Task的顶端,那么,已经存在的实例就可以重复使用来处理这个新的Intent。如果它不在顶端,那么它就不能重复使用。替代的,新的实例将创建来响应新的Intent,并进入到stack中。

例如,假设一TaskActivity stack中包含根Activity A和其它Activity BCD,并且D位于顶端,因此,stackA-B-C-D。有一个Intent来了,它要启动D类型的Activity。如果D有默认的“standard”启动模式,那么,一个新的实例将被启动并且stack变成A-B-C-D-D。然而,如果D的启动模式“singleTop”,已经存在的实例将去处理新来的Intent(因为它正好处在stack的顶端),并且stack依旧是A-B-C-D

换句话说,如果来临的Intent是冲着B类型的,那么,B类型的实例将被创建启动而不管B的模式是“standard”或“singleTop”(因为B不处在stack的顶端),因此,stack将会是A-B-C-D-B

之前提到的,设备上不会出现超过一个实例的“singleTask”或“singleInstanceActivity,因此,那个实例都将去处理所有新来的Intent。“singleInstance alimama_pid=”mm_15626785_2176297_8615857″; alimama_titlecolor=”3366CC”; alimama_descolor =”000000″; alimama_bgcolor=”FFFFFF”; alimama_bordercolor=”CCCCCC”; alimama_linkcolor=”008000″; alimama_bottomcolor=”FFFFFF”; alimama_anglesize=”0″; alimama_bgpic=”0″; alimama_icon=”0″; alimama_sizecode=”9999″; alimama_width=468; alimama_height=90; alimama_type=2;

[转载]SQL SERVER – FIX : ERROR : (provider: Named Pipes Provider, error: 40 – Could not open a connection to SQL Server) (Microsoft SQL Server, Error: ) | Journey to SQL Authority with Pinal Dave

mikel阅读(1126)

[转载]SQL SERVER – FIX : ERROR : (provider: Named Pipes Provider, error: 40 – Could not open a connection to SQL Server) (Microsoft SQL Server, Error: ) | Journey to SQL Authority with Pinal Dave.

Regular readers of my blog are aware of the fact that I have written about this subject umpteen times earlier, and every time I have spoken about a new issue related to it. Few days ago, I had redone my local home network. I have LAN setup with wireless router connected with my four computers, two mobile devices, one printer and one VOIP solution. I had also formatted my primary computer and clean installed SQL Server 2008 into it. Yesterday, incidentally, I was sitting in my yard trying to connect SQL Server located in home office and suddenly I stumbled upon the following error. Finding the solution was the most infuriating part as it consumed my precious 10 minutes.

Let us look at few of the common errors received:

An error has occurred while establishing a connection to the server.

(provider: Named Pipes Provider, error: 40 – Could not open a connection to SQL Server) (Microsoft SQL Server, Error: 5)

An error has occurred while establishing a connection to the server.  When connecting to SQL Server 2005, this failure may be caused by the fact that under the default settings SQL Server does not allow remote connections. (provider: Named Pipes Provider, error: 40 – Could not open a connection to SQL Server) (Microsoft SQL Server, Error: 1326)

I eventually found the resolution to this error on this blog itself; so I was saved from hunting for the solution. I am sure there are a number of developers who had previously fixed this error while installing SQL Server 2008 or SQL Server 2005 but in due course forgot the right solution to this error. This is just a quick refresher. Make sure to bookmark this as you never know when you would need this solution.

Let us check into the steps to resolve this error.

1) SQL Server should be up and running.

Go to All Programs >> Microsoft SQL Server 2008 >> Configuration Tools >> SQL Server Configuration Manager >> SQL Server Services, and check if SQL Server service status is “Running”.

In addition, ensure that your remote server is in the same network. Run “sqlcmd -L” in your command prompt to ascertain if your server is included in your network list. You can even find tutorial for the same here SQL SERVER – Find All Servers From Local Network – Using sqlcmd – Detect Installed SQL Server on Network.

I have confronted numerous situations when these nerve-wracking errors crop up, and most of the time when I try to troubleshoot I notice that SQL Server services are neither running nor installed. If SQL Server is not installed as default instance SQL Server Browser should be running together with it; we will explore this further in Topic 5.

2) Enable TCP/IP in SQL Server Configuration

When two or more SQL Servers are connected across network they do all communication using TCP/IP. The default port of SQL Server installation is 1433. This port can be changed through SQL Server Configuration Manager. TCP/IP should be enabled for SQL Server to be connected.

Go to All Programs >> Microsoft SQL Server 2008 >> Configuration Tools >> SQL Server Configuration Manager >> Select TCP/IP

Right Click on TCP/IP >> Click on Enable

You must restart SQL Server Services for all the changes to take effect. Right click and go to menu properties to select location where default port of SQL Server can be changed.

3) Open Port in Windows Firewall

Windows Firewall is very efficacious in protecting the Operating system from all sorts of malicious attacks. By default, many of the ports and services are refrained from running by firewall. Time and again, SQL Server ports are not open in firewall as well. All the ports on which SQL Server is running should be added to exception and firewall should filter all the traffic from those ports. As described, by default SQL Server runs on port 1433, but if default port is changed then the new port should be added to exception. If SQL Server has named instance (another instance besides default instance) is installed, SQL Server browser should also be added to the exception, as described in Step 7.

Go to Control Panel >> Windows Firewall >> Change Settings >> Exceptions  >> Add Port

Make the following entries in popup “Add a Port” and click OK.
Name : SQL
Port Number: 1433
Protocol: Select TCP

4) Enable Remote Connection

Enabling remote connection is another important, yet oft-neglected step that is frequently missed by database administrators while setting up SQL Server. If this feature is turned off SQL Server will function smoothly on local machine, but it will let another server connect to it remotely. By default this feature is ON in SQL Server 2008.

Right click on the server node and select Properties.

Go to Left Tab of Connections and check “Allow remote connections to this server”

5) Enable SQL Server Browser Service

If SQL Server is not installed as default instance but instead installed as named instance and also if there is no specific TCP/IP port configured, it will give rise to the error that is being discussed in this article. If SQL Server Browser service is enabled, it will allow the server to be connected through dynamic TCP/IP port. Enabling this service is a one-time process, as on enabling it once it will apply to all the instances installed on the same server.

Go to All Programs >> Microsoft SQL Server 2008 >> Configuration Tools >> SQL Server Configuration Manager >> SQL Server Browser

Right Click on SQL Server Browser >> Click on Enable

6) Create exception of sqlbrowser.exe in Firewall

As elucidated in Step 6, sqlbrowser service needs to be enabled for named instance. Windows Firewall may prevent sqlbrowser.exe to execute. So, it is imperative to add exception for the same in windows firewall.

Search for sqlbrowser.exe on your local drive where SQL Server is installed. Copy the path of the sqlbrowser.exe like C:\Program Files\Microsoft SQL Server\90\Shared\sqlbrowser.exe and create the exception of the file in Firewall, as delineated in Step 3.

7) Recreate Alias

It is getting quite common to create alias of SQL Server and use it in application. This will ensure that in future if any physical SQL Server has to be moved, it will not be required to change any code or connection string. You can simply create alias with the same name pointing to different SQL Server and it will start working instantaneously. I have observed that a couple of times due to internal error while recreating alias this error was fixed.

Go to All Programs >> Microsoft SQL Server 2008 >> Configuration Tools >> SQL Native Client 10.0 Configuration >> Aliases

Delete the alias that is giving problem and recreate it with identical parameters.

I have tried my best to include all the methods of fixing this error and if I have missed any, please leave a comment and I will be very glad to include them here. I have put in my effort to encompass this issue in one article that needs to be refereed when any connection error comes up.

Watch SQL in Sixty Seconds video to Resolve Connection Error:

[转载]ASP.NET无法连接到SQL Server的问题 - 小黑混北京 - 博客园

mikel阅读(1029)

转载ASP.NET无法连接到SQL Server的问题 – 小黑混北京 – 博客园.

今天刚上班,一个同事找我,说我连不上数据库了,报错。此为背景

把错误贴出来先

A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: Named Pipes Provider, error: 40 – Could not open a connection to SQL Server)

大家看着很眼熟吧。一说到这个问题,大家首先想到的可能有几点:

1、SQL Server的服务全部启动

2、服务端设置为允许远程连接

3、启用SQL Server服务端的网络协议中的TCP/IP协议和Named Pipes协议

4、防火墙中设置1433端口例外

或许再将RemoteDacEnabled设置为true?

好吧,我能想到的就这么多了。

 

下面是连接字符串

Data Source=IP\实例名;Initial Catalog=DB_Name;Persist Security Info=True;User ID=UserID;Password=******

有错吗?没错吧?这个真没错。但为什么还连不上呢。

她在程序里直接声明了一个字符串,然后把上面一段赋给这个字符串,再创建连接。没错,流程也没错。但就是连不上。

 

我就把我所了解的这以上点都翻来覆去做了个遍,结果还是不行,要崩溃了……

1、SQL Server的服务全部启动

全部已启动

2、服务端设置为允许远程连接

已设置为允许

3、启用SQL Server服务端的网络协议中的TCP/IP协议和Named Pipes协议

全部开启

4、防火墙中设置1433端口例外

telnet通

 

中午吃完饭,在外面被太阳晒了一下,回来睡了一觉。醒了擦擦眼睛,看看新闻,诶,想起来了!!让我们再看看这个字符串啊

Data Source=IP\实例名;Initial Catalog=DB_Name;Persist Security Info=True;User ID=UserID;Password=******

 

她的写法:string conn = “Data Source=IP\实例名;Initial Catalog=DB_Name;Persist Security Info=True;User ID=UserID;Password=******”;

那个斜杠大家看到了吧,就是个转椅字符啊。。。泪奔了。。。

前面加了个at,连上了。。。

 

这个问题,有够弱智吧,但就是发生了。网上好多说这个也配了,那个也设了的同学,看看你是不是跟我遇到的问题一样呢?

[转载]iis6应用程序池被自动禁用问题 Service Unavailable 应用程序池 'DefaultAppPool' 被自动禁用,原因是为此应用程序池提供服务的进程中出现一系列错误。应用程序-特定 权限设置未将 COM 服务器应用程序(CLSID 为 - Simplicity is more complicated than you think - 博客频道 - CSDN.NET

mikel阅读(865)

[转载]iis6应用程序池被自动禁用问题 Service Unavailable 应用程序池 ‘DefaultAppPool’ 被自动禁用,原因是为此应用程序池提供服务的进程中出现一系列错误。应用程序-特定 权限设置未将 COM 服务器应用程序(CLSID 为 – Simplicity is more complicated than you think – 博客频道 – CSDN.NET.

郁闷了两天了,问题终于解决了。上个礼拜重装服务器(windows 2003)后,一切都配置完成。打开iis测试web,浏览默认站点,总是显示Service Unavailable.

1.首先是打开IIS管理器.检查应用程序池,果然"DefaultAppPool"出错了.而且不是平常的停止的图标.

2.试着重启"DefaultAppPool"应用程序池,一浏览页面马上就关闭.

3.到了查看事件日志的时候了.发现了以下这类的日志

事件类型: 警告
事件来源: W3SVC
事件种类: 无
事件 ID: 1009
日期:  2008-6-24
事件:  16:12:33
用户:  N/A
计算机: MAIL
描述:
为应用程序池 ‘DefaultAppPool’ 提供服务的进程意外终止。进程 ID 是 ‘3160’。进程退出代码是 ‘0xffffffff’。

有关更多信息,请参阅在 http://go.microsoft.com/fwlink/events.asp 的帮助和支持中心。

4.会不会是默认的程序池出问题了?于是,尝试新建一个新的程序池.将默认网站的程序池改成新的.但是问题依旧.出现相似的日志.

事件类型: 错误
事件来源: W3SVC
事件种类: 无
事件 ID: 1002
日期:  2008-6-25
事件:  14:17:04
用户:  N/A
计算机: MAIL
描述:
应用程序池 ‘AppPool #1’ 被自动禁用,原因是为此应用程序池提供服务的进程中出现一系列错误。

有关更多信息,请参阅在 http://go.microsoft.com/fwlink/events.asp 的帮助和支持中心。

5.再查找事件日志另一个日志引起了我的注意.如下:

事件类型: 错误
事件来源: DCOM
事件种类: 无
事件 ID: 10016
日期:  2008-6-24
事件:  16:12:33
用户:  NT AUTHORITY/NETWORK SERVICE
计算机: MAIL
描述:
应用程序-特定 权限设置未将 COM 服务器应用程序(CLSID 为
{A9E69610-B80D-11D0-B9B9-00A0C922E750}
)的 本地 激活 权限授予用户 NT AUTHORITY/NETWORK SERVICE SID (S-1-5-20)。可以使用组件服务管理工具修改此安全权限。

有关更多信息,请参阅在 http://go.microsoft.com/fwlink/events.asp 的帮助和支持中心。

6.有点戏了.看看CLSID 为 {A9E69610-B80D-11D0-B9B9-00A0C922E750} 是什么服务先.最后在下面的注册表项中找到它:

HKEY_CLASSES_ROOT/AppID/{A9E69610-B80D-11D0-B9B9-00A0C922E750}

7.名字刚好是"IIS Admin Service"

8.好了,找到是什么了.从"管理工具"中打开"组件服务",找到IIS Admin Service对比一下CLSID是否一致

9.确定是这个以后,接下来的就是为它增加NETWORK SERVICE权限了.
A启动和激活权限,点击”自定义”..

B.在用户列表中添加”NETWORK SERVICE”,

C.并给予本地启动和激活权限,保存退出.

到此问题解决.

解决ASP An error occurred on the server when processing the URL. Please contact the system administrator.

mikel阅读(704)

解决方法如下:

设置方法一:

以管理员身份运行CMD,将目录定位到%windir%\system32\inetsrv\,然后执行appcmd set config -section:asp -scriptErrorSentToBrowser:true。
%windir%\system32\inetsrv\appcmd set config -section:asp -scriptErrorSentToBrowser:true

设置方法二:

打开IIS7的asp设置,展开“调试属性”选项,“将错误发送到浏览器”这项默认的是False,改为True,然后点右侧的应用!如图所示:

通过以上设置后,再从浏览时打开出错ASP页面时就能看到页面出错的详细信息,方使调试。如果是公开的Web服务器建议不要打开此选项,以防出错信息被他人利用。

Tags:An error occurred on the server when processing the URL

[转载]移动变现模式:免费增值和插入广告,谁才是王道? | 36氪

mikel阅读(831)

[转载]移动变现模式:免费增值和插入广告,谁才是王道? | 36氪.

移动变现模式:免费增值和插入广告,谁才是王道?

移动分析公司App AnnieIDC最新一份报告的数据显示,去年一年移动应用通过免费增值服务获得了 211% 的营收增长。

看来“免费”总归是有用的。

在 Google Play 和苹果应用商店中,分别排名前 1000 的应用里有 83% 的应用使用免费增值模式,而这 2000 个应用总营收的 92% 来自免费增值。

在移动应用里, 免费增值包括多种应用内购买活动。例如升级,加速,购买额外功能或内容,延长应用的使用时间,付费去广告等等。以纽约时报的应用为例,免费用户可以阅读部分文章,而一些文章只对订阅用户开放。

在 App Annie 做的关于是否采用免费增值模式的问卷调查中,受访的 2000 名游戏开发工程师表示赞同这种变现模式。

对于靠免费增值创收的工程师来说,其主要目标是吸引到尽可能多的用户。并在建立起用户群后,促使尽可能多的免费用户购买。尽管数据显示,只有不到 5% 的工程师宣称,有超过三成的用户购买。

美国市场依然是移动应用营收的最大贡献者,去年的营业额增长 1.7 倍。虽然日本,韩国和印度的增幅分别高达 2.2,2.3 和 3 倍,但由于基数小,营收绝对值上仍无法和美国媲美。但印度的移动应用营收在 2017 年有望达到 2013 年 870%。

在调查中,仅有不到一半的开发者称他们在应用内插入了广告。通过插入广告盈利并非易事,普通应用能获得 1 万美元的月营收已是极少数。

只有那些极其受欢迎的应用,例如,Flappy Bird,才有可能达到每月 10 万美元的广告营收。

而就现在的研究数据看,移动应用的广告营收总额将在 2017 年超越 PC。IDC 的数据预测,截至 2017,每个主要移动市场的广告营收占其移动应用总营收的比例都将大幅增长,美国市场增长率将达到 60%。除日韩外,其他市场例如德国,法国,巴西等国的比例都将突破 50%。

[本文参考以下来源:venturebeat.com, fiercemobileit.com]

[转载]GoogleView - 好的网站设计:完全掌控用户的视线

mikel阅读(943)

[转载]GoogleView – 好的网站设计:完全掌控用户的视线.

了解如何通过图片和广告文案来引起用户的注意力

003


近来网站已经成为大多数企业最看重的一部分。是企业对外交流不可或缺的沟通方式,也为企业的权威性提供有力线索。同时,企业通过网站能够在订单完成过程中,迅速而直接地告知用户企业的价格底线。然而,人们通常都浪费掉了大多数能够最大化ROI(投资回报率)的机会。

来自可用性专家Jakob Nielsen 的研究发现,2013年有百分之五十二的屏幕空间被完全浪费掉,这个数值高于2001年。一些网站设计师信奉于极简主义做法,他们将信息量最小化后全部放 置于一个独立的网站页面。另外一些人则让网站变得更复杂。这两种方法可以说是既不对也不能算错。

 image004

我们正在掌控你的视线

很有可能,同大多数来到这个页面的用户一样,你正在读这一行的文字标题。而且,你很可能跳过开篇的第一段,直接到达这里。

为什么?

1 开篇首段含义隐晦生涩。
2 处在突出位置的图片主导了用户的视线范围。
3 同大多数人一样,你可能在读图片的题注。
4 图形元素和箭头,将用户的注意力牵引到图片的标题上。
5 标题的设计独特,出乎意料。

如果我是对的,你会完全跳过本文开篇的第一段。而这也恰恰证明了我的观点。

选择什么是重要的,并将其形象的表述出来

开发一个网页最难的是决定什么才是重要的。这个听起来有点不太直观。

通过学习网络营销方式(搜索引擎营销方式),我们一开始会尝试混合所有的东西放置入一个页面,很快,我们发现有些东西不能同时放在一起。

那些为SEO准备的文案经常会与一些说服力强的广告文案相冲突。而留给品牌推广的网站位置会占用那些切合用户需求的文案位置。

在2013年,Jakob Nielsen 就提到,超过一半的屏幕空间被浪费掉了。

image005
谁是罪魁祸首呢?

6 填满了整个网页的文案和图片
7 自我推销和广告
8 散落的空白区

移除自我推销和广告可能较难抉择,我们可以更合理的利用空白区和用于填满网页的文案。

测试A

根据 Jakob Nielsen的研究,你能告诉我,到达本文的这里,有多少屏幕空间是被浪费掉的?
A. 一半的屏幕空间
B. 52% 的屏幕空间
最准确的答案是B。如果你选择A,不要灰心,这是我们有意为之。

我骗了你

开头段-即无法顺畅阅读的开篇第一段,提到的“52%”这一统计数据。

亲爱的读者,尽管这个数据在开头段的显眼位置被提到,但实际上却被你们当中的很多人(或者一部分人)给忽略了。开头段长度有108个单词,包含6个句子。(译者备注:本文是从英文翻译而来,中英文断句有差异,这里的数字请不要较真。)

第一句甚至很明显的让人感到相当无趣。第二句的34个单词中有很多是多音节词语。(看看我在那里做了什么?)它充满了晦涩难懂的代名词,且没有一句比较新鲜或者有趣的话。

我把 52% 写成“百分之五十二”,因为我知道你的眼睛会被阿拉伯数字吸引。

100534gbmplmz5mrurmrjm

左侧是一张图,用于促使访问者做短暂停留和测试图片效果。人们不会想要看见一个女孩躺在热钢片的屋顶上。我还把一只形状看起来像猫的物体,当然那不是一个女孩,放在了图片最左边的地方。

图片题注会给出一个讯息,而且如果图片很有趣,图片上的题注也会更加频繁的被用户读取到。然后,我利用箭头将用户的注意力指向一个标题,这个标题则与图片题注给出的讯息相符。这是一个连续的信息传递。

通过使用粗体、项目符号和另一个标题,你会绕过开篇第一段,直接查阅本文的其他部分。

是的!我有意隐藏了更多具体的统计数据,而我也并没有就此停止。

我们都是“扫描仪”

利用我们的页面浏览习惯,我将一些不太精准的内容放在了用户一定能注意到的地方。

如果我成功的将用户的注意力从图片引到图片题注,然后到达某个页面,我会向用户展示一个更容易被浏览到的文案。这样的文案经常包含下列内容:

9  频繁的标题
10 短句
11 文本会话
12 项目列表
13 粗体

我把“一半的屏幕空间”放在两个让用户视线很难忽略的地方:一个再链接文本中,另一个在一个醒目的引文里。我使空白区环绕“醒目引文”来确保能够让用户注意到。

让我们看看你选择的答案是哪一个。

当你知道你想要什么的时候,事情就变得简单了

研究用户心理和使用诱导性的写作方式,这都不是我在 UX 举办的培训里得出的结论。我知道有一件事我期望你能看到,而其他的则不希望被看到。

开发网页过程中什么是最重要的?是你的电话号码?你提供的免费运货服务?你的退款保证?你很难抉择优先考虑哪条讯息,尤其是当我们在设计网站首页的时候。

你可能会首先考虑哪些是不合适的内容。

重新思考填料图片或者移除他们。考虑品牌图片是否需要如此之大。重新书写标题来告诉来访者你的网站里有些什么。删除长篇幅的段落,长句子和一些商业用语。

然后来看看你做的如何。通过测试,你的会计会告诉你,你的网站转化量神奇的提升了很多。

针对于任何一个网站页面,要知道什么才是重要的。然后设计一些小技巧来抓取用户的注意力,这是一个非常好方式,可以让你获得你想要的,帮助你的用户找到他们正在查找的内容。

 

 

来源: marketingland (原作者:Brian Massey 译者:垂柳社区 lilyalina)