ASP.NET2.0下中定制安全凭证的履篇

import
java.util.concurrent.ArrayBlockingQueue;

同、方案架构

import
java.util.concurrent.BlockingQueue;

  本方案架构很粗略——它之所以一个Web服务来包装ASP.NET
2.0提供者并且为远程客户暴露该证据管理,你甚至还会当该架构中加上一些错过的机能。然后,在供一个长的用户接口及周凭证管理更的以,使用一个Windows表单应用程序来花该Web服务。该Web服务配置文件拿包含特定于该证据存储的命。然而,这确意味着有由该Web服务管理之应用程序都将可共享这些指令。

import
java.util.concurrent.ExecutorService;

  尽管你能够起到尾地构建该Web服务,也就是说,首先用静态方法Roles和Membership来包装它们并定义该Web服务,我倒再爱好同种植契约驱动之不二法门:首先设计执行各种操作的极好接口将凡什么,并且直到需要经常才考虑怎样实现它。这样做足保由Web服务暴露的接口支持具有要求的军事管制功能以还将精减该客户应用程序与其它实现细节(例如包装提供者)之间的耦合。

import
java.util.concurrent.Executors;

   ASP.NET
2.0底一个双重好之特点是它支持Web服务接口,你可定义并且给该Web服务暴露逻辑接口,就象类的显现一样。为这,你用为此
WebServiceBinding属性修饰你的接口并且由WebMethod属性来暴露单个的接口方法。然后,你拿生一个派生于这个接口的好像并实现该接口,而且编译器将要求您支持该接口的装有术。

 

  为了管住和互相于凭证存储和Web服务配置,我定义了5独接口-IApplicationManager,IMembershipManager,IPasswordManager,IroleManager和IUserManager。

/**

  (一) IApplicationManager

   
本例介绍一个奇特之班:BlockingQueue,如果BlockQueue是空的,从BlockingQueue取东西的操作将会见于堵嘴进入等状态,直到BlockingQueue进了事物才会受传唤醒.同样,如果BlockingQueue是满的,任何准备为里抱东西的操作为会见让堵嘴进入等状态,直到BlockingQueue里有空间才会吃唤起继续操作.

  该IApplicationManager接口显示为所附源码中的列表2,允许管理员删除一指定的应用程序-也就是说,从数据库被去所有到它们的参考并且删除其的具有用户和角色。IApplicationManager允许从存储着剔除所有的应用程序,并且其会回去在拖欠存储着之具备应用程序的一个列表。注意,这个接口作为一个中的接口被定义-public或internal可见性修饰词对Web服务接口都是空虚的。该接口及之每个方法用
WebMethod属性加以修饰并出一个欠办法的简练描述。此外,存取凭证存储的有术都让装也利用事务处理。这样的话,两种植操作-如去一使程序与开创同用户将当交互了切断的景下实行,从而保证了一旦去所有用户等繁杂操作的原子性。.NET
2.0中的Web服务只能启动一个初业务,而且它们是出于WebMethod属性的TransactionOption属性来控制的。最后一点凡是将
WebServiceBinding属性应用被接口及。这便指定该接口是一个客户及劳务都能够绑定到的Web服务接口。为了将该接口以一个WSDL契约方式暴露被外界,你得采取一个shim类。这个shim类的统筹是不可或缺的,因为若无可知将一个接口作为一Web劳动暴露,而且你吗未克以该及用
WebService属性。这个shim类还以经WebService属性为该接口命名空间定义。下面的代码显示了
IApplicationManagerShim抽象类的定义。

   
本例再次兑现11.4线程—-条件Condition中介绍的提篮程序,不过这篮子中极其多能加大的苹果数不是1,可以轻易指定.当篮子满时,生产者进入待状态,当篮子空时,消费者等待.

[WebService(Name=”IApplicationManager”,
Namespace=”http://CredentialsServices”,
Description=”IApplicationManager is used to manage
applications. This web service is only
the definition of the interface. You
cannot invoke method calls on it.”)]
abstract class IApplicationManagerShim : IApplicationManager{
 public abstract void DeleteApplication(string application);
 public abstract string[] GetApplications();
 public abstract void DeleteAllApplications();
}

 */

  因为IApplicationManagerShim是一个类,所以您得将她暴露也一个Web服务。因为其是均等华而不实类都具有办法给定义为架空方法,所以未需(也非可知)实现其他方法。为了要该拘禁起就象该接口,IapplicationManagerShim把WebService属性的特性名设置为
IApplicationManager(代替缺省之类名)。现在,你得下IApplicationManager.asmx文件来暴露该接口。

/**

<%@ WebService Language=”C#”
CodeBehind=”~/App_Code/IApplicationManagerShim.cs”
Class=”IApplicationManagerShim”%>

   
使用BlockingQueue的关键技术点如下:

  现在,如果您浏览到IApplicationManager.asmx页面,你便会见看出该接口定义。你可行使WSDL.exe的serverInterface选项来管接口定义输入到客户端或任何其它想绑定到拖欠接口定义上的劳务。

   
1.BlockingQueue定义的常用方法如下:

  (二) IMembershipManager

   
    1)add(anObject):把anObject加至BlockingQueue里,即如果BlockingQueue可以容纳,则回true,否则招聘异常

  IMembershipManager接口(见所附源码中之列表3)允许而管理用户帐户的装有方面-创建与去用户帐户,更新用户帐户,检索用户帐户细节以及查找在同等利用程序中之拥有用户。

   
    2)offer(anObject):表示如果可能的话,将anObject加至BlockingQueue里,即如BlockingQueue可以容纳,则赶回true,否则回false.

  (三) IRoleManager

   
    3)put(anObject):把anObject加至BlockingQueue里,如果BlockQueue没有空间,则调用此方法的线程被阻断直到BlockingQueue里面有空间重继续.

  IRoleManager接口允许而管理逻辑角色的有地方-创建及去角色,从角色中长和去用户和查找在平等施用程序中之具有角色。

   
    4)poll(time):取走BlockingQueue里排在首各之靶子,若未可知马上取出,则好当time参数规定之岁月,取不顶常返回null

[WebServiceBinding(“IRoleManager”)]
interface IRoleManager{
[WebMethod(…)]
void CreateRole(string application,string role);
[WebMethod(…)]
bool DeleteRole(string application,string role,bool
throwOnPopulatedRole);
[WebMethod(…)]
void AddUserToRole(string application,string userName, string role);
[WebMethod(…)]
void DeleteAllRoles(string application,bool throwOnPopulatedRole);
[WebMethod(…)]
string[] GetAllRoles(string application);
[WebMethod(…)]
string[] GetRolesForUser(string application,string userName);
[WebMethod(…)]
string[] GetUsersInRole(string application, string role);
[WebMethod(…)]
void RemoveUserFromRole(string application,string userName, string
roleName);
//更多成员
}

   
    5)take():取走BlockingQueue里排在首各项的对象,若BlockingQueue为空,阻断进入等状态直到Blocking有新的目标为在了

  (四) IPasswordManager

   
2.BlockingQueue发出四个实际的实现类似,根据不同需求,选择不同之兑现类似

  这个IPasswordManager接口主要提供与应用程序口令策略相关的单读信息。

       
1)ArrayBlockingQueue:规定大小的BlockingQueue,其构造函数必须带来一个int参数来指明其大小.其所富含的对象是坐FIFO(先入先出)顺序排序的.

[WebServiceBinding(“IPasswordManager”)]
interface IPasswordManager{
[WebMethod(…)]
bool EnablePasswordReset(string application);
[WebMethod(…)]
bool EnablePasswordRetrieval(string application);
[WebMethod(…)]
string GeneratePassword(string application,int length,
int numberOfNonAlphanumericCharacters);
[WebMethod(…)]
bool RequiresQuestionAndAnswer(string application);
[WebMethod(…)]
string ResetPassword(string application,string userName);
[WebMethod(…)]
string GetPassword(string application,string userName,string
passwordAnswer);
[WebMethod(…)]
void ChangePassword(string application,string userName,string
newPassword);
//更多成员
}

       
2)LinkedBlockingQueue:大小不定的BlockingQueue,若该构造函数带一个规定大小的参数,生成的BlockingQueue有大小限制,若未带来大小参数,所好成的BlockingQueue的大小由Integer.MAX_VALUE来决定.其所含有的靶子是坐FIFO(先入先出)顺序排序的

  典型地,该政策存储于应用程序的部署文件被。该策略包括是否启动口令重置和查找,口令强度和口令回答策略等。你呢得以用
IpasswordManager来生成一遥相呼应被该口令强度策略的新口令。另外,IpasswordManager可用于重置、改变或者找一点名用户的口令。

       
3)PriorityBlockingQueue:类似于LinkedBlockQueue,但彼所蕴涵对象的排序不是FIFO,而是因对象的自排序依次或者是构造函数的Comparator决定的顺序.

  (五) IUserManager

       
4)SynchronousQueue:特殊的BlockingQueue,对其的操作必须是推广以及取交替完成的.

  IUserManager接口允许校验用户凭证,检索角色地位与取得指定用户是彼成员之一之享有角色。该接口用于测试和剖析目的。

   
3.LinkedBlockingQueue和ArrayBlockingQueue于起,它们背后所用之数据结构不等同,导致LinkedBlockingQueue的多少吞吐量要逾ArrayBlockingQueue,但以线程数量非常怪时其性的可预见性低于ArrayBlockingQueue.   
     

[WebServiceBinding(“IUserManager”)]
public interface IUserManager{
[WebMethod(…)]
bool Authenticate(string applicationName,string userName, string
password);
[WebMethod(…)]
bool IsInRole(string applicationName,string userName, string role);
[WebMethod(…)]
string[] GetRoles(string applicationName,string userName);
}
二、AspNetSqlProviderService Web服务

 */

  显示在所附源码中的列表4蒙受之
AspNetSqlProviderService类实现了五独Web接口。其过程就象实现任何其它接口一样-你得隐式或显式地派生并实现方式(见列表
4)。我是通过把这些实现简单地代理及提供者的适宜的方来落实该Web接口上的绝大多数计的。在每一样破采取角色要么位置之前,你必须也底作好准备-通过安装要使用的应用程序名。例如,为了落实IRoleManager.CreateRole(),你用用建立:

public
class
BlockingQueueTest {

void IRoleManager.CreateRole(string application,string role){
Roles.ApplicationName = application;
Roles.CreateRole(role);
}

      
/**概念装苹果之篮子*/

  其中的部分智在调用该提供者前后还求一点干活。例如,如果开行口令检索,你只能寻找用户口令,而AspNetSqlProviderService则用来判定其。

      
public
static
class
Basket{

string IPasswordManager.GetPassword(string application,string
userName,
string passwordAnswer){
Membership.ApplicationName = application;
Debug.Assert(Membership.EnablePasswordRetrieval);
MembershipUser membershipUser =Membership.GetUser(userName);
return membershipUser.GetPassword(passwordAnswer);
}

      
       //篮子,能够容纳3个苹果

  然而,还有部分智并没有获得提供者的一直支持。有零星栽或的解决办法-第一种植是尝试并运用提供者的别样措施来形成所愿意之操作。第二栽是直执行
aspnetdb数据库。两种植方法还在利弊。例如,可以考虑实现MembershipManager.DeleteAllUsers()方法。你可本着该应用程序中之每个用户调用身份提供者的DeleteUser()方法,如列表4所显示。首先你而调用
IMembershipManager.GetAllUsers()方法来获得应用程序中的具有用户。这就是是公通过落实该接口的接近来使用该接口方法的显式实现方式。然后,你得定义一个匿名方式来删除用户,把该匿名方式赋值到一个Action<string>代理,并且采取Array类的静态方法
ForEach<T>()删除每个用户。

      
       BlockingQueue<String> basket =
new
ArrayBlockingQueue<String>(3);

public delegate void Action<T>(T obj);
public abstract class Array : …
{
public static void ForEach<T>(T[] array,Action<T> action);
}

      
       //生产苹果,放入篮子

  第一种植艺术的优点是其余与删除一个用户相关的里活动(如为抹所有的角色身份)仍旧为执行。其不足是,你得针对拖欠数据库做重新多之调用。

      
       public
void
produce() throws
InterruptedException{

  正使刚提到的,第二栽方法是直接针对aspnetdb数据库编程。当提供者没有提供其他措施来完成这任务时,这是最好可行的。例如,提供者并无支持删除一采取程序,更无说去所有的应用程序了。尽管你可以编制一个囤过程来开就起业务,但自之另一个靶是休下aspnetdb,而是采用原始SQL命令来促成IApplicationManager.DeleteApplication()和
IApplicationManager.DeleteAllApplications()。我已经因此一个AspNetDbTablesAdapter助理类(在这并未显得)包装了这些命令。直接访问数据库的亮点是公一味执行一个命;不足之处是,如果假定改变数据库模式,你用需变更而的代码。假定如删减所有的用户或一致下程序等操作是形似不关乎的还要超级用户之多少经常坏有点,那么自己思念最好尽可能让AspNetSqlProviderService使用
ASP.NET 2.0提供者。

      
              //put方法放入一个苹果,若basket满了,等到basket有职位

  (一) 设置服务

      
              basket.put(“An
apple”);

  由AspNetSqlProviderService
Web服务用的Web.Config文件被之安影响她管理之持有应用程序。特别地,如口令策略这样的安装适用于拥有的应用程序。该服务应用默认提供者
(SQL
SERVER),因此只要缺失省之接连字符串(在文件machine.config中保护)已经够的话,就非欲指定一个提供者甚至一个连接字符串。如果您要一个不同之连天字符串,你用包括一个connectionStrings标签(见所附源码中之列表5)。另外,为了采取Roles类,你必须透过下列指令来启动基于角色的安全。

      
       }

<roleManager enabled=”true” />

      
       //消费苹果,从篮子中获得走

  (二) 保护服务

      
       public
String consume() throws
InterruptedException{

  尽管该据由AspNetSqlProviderService
Web服务来保管的应用程序可能是因互联网或基于内部网的,但是服务本身是给设计由一个大班通过本地内部网来存取的。你该辨证与授权到拖欠服务的调用。另外,你还应经过加密通讯来供秘密服务。这是讲求的,因为拖欠服务要处理要用户称及口令等敏感信息。保证机密的尽轻的道是下HTTPS。
AspNetSqlProviderService在她的构造器中由静态VerifySecureConnection()助理方法来进展认证是否以了一个康宁连接。VerifySecureConnection()使用时要的IsSecureConnection属性。为了支持开发要该服务的其他种类的非生产性发布,VerifySecureConnection()方法用Conditional属性加以修饰。只有定义编译符号HTTPS时欠法才会打作用。关于认证该服务的用户,既然Web服务是一律本地内部网服务,那么用Windows认证就不见面来其它不当了。我选了利用并的
Windows认证-这将节省了用户须明确地登录的分神。集成的征的另外一个独到之处是,它因此同样种植专利方式来散列化发送过去的凭据。

      
              //take方法取出一个苹果,若basket为空,等到basket有苹果了

  为了安排并的Windows认证,转至在IIS下的AspNetSqlProviderService
Web服务特性,选择目录安全选项卡,并且点击”Edit…”按钮。不选”Anonymous
access”复选框并且保证选中”Integrated Windows
authentication”复选框。AspNetSqlProviderService类被安排为要求验证(见列表4)-它以
PrincipalPermission属性并把吃验证的性能设计也罢true。

      
              return
basket.take();

[PrincipalPermission(SecurityAction.Demand,…,Authenticated=true)]

      
       }

  一旦调用者通过IIS被验证,该服务少省地将以IIS中坐安排的地位还是运行。我思坐调用者身份运行该服务。为这个,Web.Config文件(见列表5)包含了一个identity标签-它把impersonate属性设置为true。

      
}

<identity impersonate=”true”/>

      
//测试方法

  然后,你要运用SQL
SERVER管理工具来允许Web服务的调用者从aspnetdb数据库中开展读与描绘。

      
public
static
void
testBasket(){

  保护该Web服务的外一个根本地方是授权。我思使验证只有Windows超级用户组的分子才会存取这同样劳务。为是,AspNetSqlProviderService类上之PrincipalPermission属性要求只有超级用户角色的积极分子才受允许以该服务。

      
       final
Basket basket = new
Basket();//建立一个佯装苹果之篮子

[PrincipalPermission(SecurityAction.Demand,
Role = “Administrators”,…)]

      
       //定义苹果生产者

  你可用外其它组(该服务的骨子里用户应是里面的平等员)来替换”Administrators”。

      
       class
Producer implements
Runnable{

  PrincipalPermission属性使用配属于该线程的安主管(principal)来验证调用者是否真的是指定角色被的一样号。在指让NT组(如超级用户)时,这将挟持你下一个WindowsPrincipal的实例。

      
              public
void
run(){

public class WindowsPrincipal : IPrincipal{
 public WindowsPrincipal(WindowsIdentity ntIdentity);
 public virtual bool IsInRole(string role);
 //其它成员有
}

      
                     try{

  问题在于,为了采取Roles类,AspNetSqlProviderService
Web.Config文件要启动基于角色的安全策略。

      
                            while(true){

<roleManager enabled=”true” />

      
                                   //生产苹果

  这反过来使得ASP.NET
2.0管同见仁见智之principal依附到HttpContext和线程上,当然还有RolePrincipal类。

      
                                   System.out.println(“生产者准备生苹果:
” +
System.currentTimeMillis());

public sealed class RolePrincipal : IPrincipal{…}

      
                                   basket.produce();

  以NT超级用户角色中试图使用RolePrincipal和过于要求的地位用见面失败,因为它将存取aspnetdb而不是Windows组来查找它。为上这一点,你得手工地交换这些企业主又以每次要时拿WindowsPrincipal的一个实例依附到拖欠线程上。为者,最爱之措施是拿一个
Global.asax文件上加到该Web服务工程-通过点名在Global.cs文件中之Global类为接近后的代码。

      
                                   System.out.println(“生产者生产苹果了:
” +
System.currentTimeMillis());

<%@ Application Language=”C#” CodeBehind =”Global.cs” Inherits =
“Global”%>

      
                                   //休眠300ms

  这个Global类为应用程序授权请求提供一个计算机。

      
                                   Thread.sleep(300);

public class Global : HttpApplication{
 protected void Application_AuthorizeRequest(object sender, EventArgs
e){
  if(HttpContext.Current.User.Identity.IsAuthenticated){
   WindowsIdentity identity = HttpContext.Current.User.Identity as
WindowsIdentity;
   Debug.Assert(identity != null);
   WindowsPrincipal principal;
   principal = new WindowsPrincipal(identity);
   Thread.CurrentPrincipal = principal;
  }
 } 
}

      
                            }

  如果调用者被证实,那么你用实例化一新的WindowsPrincipal对象又将它们依附于时线程。WindowsPrincipal构造器需要一个WindowsIdentity的实例。幸好,因为拖欠服务在以Windows集成的证实,在功成名就验证后,与眼前HTTP上下文相沟通的身份已是
WindowsIdentity类型了,因此而得就得到是实例。
**三、凭证管理器应用程序

      
                     }catch(InterruptedException
ex){

**  本文相应的源代码包含了是证管理器应用程序-一个怀有丰富的用户接口的Windows表单应用程序,它采取以直达亦然步描述的Web服务接口来吗其它数的应用程序管理安全凭证存储。

      
                     }

  该应用程序导入五单Web接口定义,并且她独占地使用那些接口。该应用程序有一个称为AspNetSqlProviderService的Web服务代办类-它用来固定该服务。你待打导入的接口手工地将她上加至拖欠服务达。

      
              }

图片 1
图4.Applications选项卡:这个选项卡让您选要配备的应用程序。

      
       }

partial class AspNetSqlProviderService :
SoapHttpClientProtocol,IMembershipManager,
IUserManager,IPasswordManager,
IApplicationManager,IRoleManager
{
 public AspNetSqlProviderService (){
  Credentials = CredentialCache.DefaultCredentials;
  Url = Settings.Default.AspNetSqlProviderService ;
 }
 //其它的行
}

      
       //定义苹果消费者

  为了支持并的Windows认证,这个代理类的构造器使用CredentialCache的静态属性DefaultCredentials设置凭证属性-它只是简短地念博时线程的安全标志。另外,这个构造器还以设计器生成的Settings类从应用程序配置类似吃读取Web服务地方。

      
       class
Consumer implements
Runnable{

图片 2
祈求5.Users选项卡:该选项卡列出当选定的应用程序中之装有用户。

      
              public
void
run(){

  这个应用程序的应用一定直观,所以我就介绍一下重点屏幕与甄选。Applications选项卡(见图4)允许而挑要配备的应用程序。

      
                     try{

  于这个,选择一样动程序将震慑有其他的挑三拣四项卡。你得创造同去一个应用程序或去所有应用程序。Users选项卡列举出在挑的应用程序中之有着用户。

      
                            while(true){

  你可创建或者删除一用户。如果您去一用户可非选”All
Data”复选框的语句,它将去该用户可保持其的角色地位信息。你得更新一用户帐户或去所有用户。根据从
AspNetSqlProviderService
Web服务返回的口令策略的不比,你可知或不克改变或重置口令,而且得要非可以要应该口令。在Users选项卡的按钮和它所显示的对话框也相应地开行或禁止。

      
                                   //消费苹果

  于Users选项卡的右边是统计信息,如当前用户的在线数。Roles选项卡允许你拿角色添加到应用程序。

      
                                   System.out.println(“消费者准备消费苹果:
” +
System.currentTimeMillis());

图片 3
希冀6:Roles选项卡:这个选项卡让你管角色添加到应用程序。

      
                                   basket.consume();

  当去一个角色时,如果你选择了”Fail if
populated”复选框,那么要她有外成员来说,就无见面让你删掉该角色。左边的列表视图显示在该应用程序中的有用户。你得由一个角色添加或去一用户,或从有着角色中删去一用户。在脚,”Users
in role”列表框显示了当上头选定的角色被之具备用户,而”Roles for
User”列表框显示了于方选定的用户被的有所角色。

      
                                   System.out.println(“消费者花苹果了:
” +
System.currentTimeMillis());

  Passwords选项卡显示在图7中,它列有曾经部署的口令策略并且同意你生成一跟指定的口令强度策略相兼容的新口令。

      
                                   //休眠1000ms

图片 4
图7.Passwords选项卡:你得以这个选项卡生成一人叫。

      
                                   Thread.sleep(1000);

图片 5
贪图8.Credentials Service选项卡:使用此选项卡来抉择以的Web服务。

      
                            }

  该选项卡让您拣而运的Web服务。一旦启动,凭证管理器应用程序即由应用程序配置文件中读取这个地方。这个选项卡显示为挑的Web服务。如果地方是不行的,也就是说,该服务不支持具有要求的效果,那么以应用程序中的备控件都以为空且是禁的。你得供一个例外的地方,而脚的Web浏览器控件将会晤显这等同服务。然而,如果该服务支撑要求的Web方法(一中的Web服务)的话,你可以只有选一个Web服务地方(通过点击Select按钮)。如果该服务是杯水车薪的,那么以禁Select按钮。

      
                     }catch(InterruptedException
ex){

  不幸的凡,在.NET
2.0饱受从未供校验某服务是否支持一特地绑定或Web接口的坐支持,因此自只好手工实现。所附源码中的列表6出示出
RefreshSelectButton()和ContainsInterface()助理方法。RefreshSelectButton()首先禁止
Select按钮和彼此配合的菜单项。然后,验证指定的地方是一个.NET
Web服务之地点。然后,它存取显示在Web浏览器控件被的页面的情节又认证其涵盖支持所有的接口的章程。为这个,它若调用
ContainsInterface()方法并将页面的内容及而证明的接口类型提供被她。ContainsInterface()验证该档是一个接口的类别又赢得一个MethodInfo对象数组-标记在该接口及的每个方法。然后,它定义一个收受单个实例MethodInfo的匿名方式而用字符串类的Contains()方法来说明该内容包含那个方式。ContainsInterface()使用该数组类的静态TrueForAll<T>()方法。

      
                     }

public delegate bool Predicate<T>(T obj);
public abstract class Array : …
{
 public static bool TrueForAll<
 T>(T[] array,Predicate<
 T> match);
}

      
              }

  ContainsInterface()提供给TrueForAll()一个MethodInfo对象数组和匿名方式形式之Predicate。只有当该内容被找到有的法时,TrueForAll<T>()才回到true。
http://www.7dspace.com/doc/24/0512/2005123006395536935_1.htm

      
       }

      
       ExecutorService service =
Executors.newCachedThreadPool();

      
       Producer producer = new
Producer();

      
       Consumer consumer = new
Consumer();

      
       service.submit(producer);

      
       service.submit(consumer);

      
       //程序运行5s后,所有任务已

      
       try{

      
              Thread.sleep(5000);

      
       }catch(InterruptedException
ex){

      
       }

      
       service.shutdownNow();

      
}

      
public
static
void
main(String[] args){

      
       BlockingQueueTest.testBasket();

      
}

}