WCF的安全审核——记录谁在敲打你的门

WCF所谓的安全审核就是针对认证和授权所做的针对EventLog的日志记录。我们不但可以设置进行审核的事件(认证成功/失败,授权成功或失败),还可以选择记录信息被写入的EventLog类型,即应用程序日志(Application)还是安全日志(Security)。WCF的安全审核是通过ServiceSecurityAuditBehavior服务行为实现的。

一、ServiceSecurityAuditBehavior服务行为

针对WCF安全审核的编程只涉及ServiceSecurityAuditBehavior服务行为。下面给出了定义在ServiceSecurityAuditBehavior中具体审核行为进行控制的三个可读写的属性。

   1: public sealed class ServiceSecurityAuditBehavior : IServiceBehavior
   2: {
   3:     //其他成员
   4:     public AuditLogLocation AuditLogLocation { get; set; }
   5:     public AuditLevel MessageAuthenticationAuditLevel { get; set; }
   6:     public AuditLevel ServiceAuthorizationAuditLevel { get; set; }
   7:     public bool SuppressAuditFailure { get; set; }
   8: }

属性AuditLogLocation代表的是日志信息被写入的EventLog类型,该属性的类型是一个具有如下定义的AuditLogLocation枚举。其中Application和Security分别代表应用程序日志和安全日志。如果选择Default,则最终日志被写入的位置决定于当前的操作系统。如果支持写入安全日志,则选择安全日志类型,否则选择应用程序日志类型。Default是默认选项。

   1: public enum AuditLogLocation
   2: {
   3:     Default,
   4:     Application,
   5:     Security
   6: }

MessageAuthenticationAuditLevel和ServiceAuthorizationAuditLevel两个属性分别代表针对认证和授权审核的级别。所谓审核的级别在这里指的应该在审核事件(认证和授权)在成功或者失败的情况下进行日志记录。审核级别通过具有如下定义的AuditLevel枚举表示。Success和Failure代表分别针对认证/授权成功和失败进行审核日志。SuccessOrFailure则意味着不管认证/授权是成功还是失败,都会进行审核日志。None为默认值,表示不进行审核日记记录。

   1: public enum AuditLevel
   2: {
   3:     None,
   4:     Success,
   5:     Failure,
   6:     SuccessOrFailure
   7: }

布尔类型的SuppressAuditFailure属性表示审核日志失败是否会影响应用本身。在默认的情况下该属性值为True,意味着为认证和授权进行审核日志的时候出现的异常不会对应用(服务)本身造成任何影响。

既然是服务行为,我们就可以通过将创建的ServiceSecurityAuditBehavior添加到服务的行为列表的方式来进行安全审核的控制。当然我们还是推荐采用配置的方式来进行安全什么的相关设置。服务行为ServiceSecurityAuditBehavior对应的配置节是<serviceSecurityAudit>。在下面的配置中,我定义了一个包含了ServiceSecurityAuditBehavior的服务行为,并对其四个属性进行了显式设置。

   1: <configuration>
   2:   <system.serviceModel>     
   3:     <behaviors>
   4:       <serviceBehaviors>
   5:         <behavior ...>
   6:           <serviceSecurityAudit auditLogLocation ="Application" 
   7:                                 messageAuthenticationAuditLevel ="Failure"
   8:                                 serviceAuthorizationAuditLevel="SuccessOrFailure"
   9:                                 suppressAuditFailure="true"/>
  10:         </behavior>
  11:       </serviceBehaviors>
  12:     </behaviors>
  13:   </system.serviceModel>
  14: </configuration>

二、安全审核的实现

WCF最终进行安全审核的控制信息是从基于某个终结点的分发上下文中获取的。如下面的代码片段所示,对于定义在ServiceSecurityAuditBehavior中的四个属性,在DispatchRuntime中具有相应的定义。WCF在认证和授权成功或者失败的时候,会根据该运行时这四个属性进行相应安全审核日志。

   1: public sealed class DispatchRuntime
   2: {
   3:     //其他成员
   4:     public AuditLogLocation SecurityAuditLogLocation { get; set; }
   5:     public AuditLevel MessageAuthenticationAuditLevel { get; set; }
   6:     public AuditLevel ServiceAuthorizationAuditLevel { get; set; }
   7:     public bool SuppressAuditFailure { get; set; }
   8: }

而作为服务行为的ServiceSecurityAuditBehavior,最终的目的就是将定义在自身的这四个属性赋值给分发上下文。而具体操作定义在ApplyDispatchBehavior方法上,整个逻辑大体上如下面的代码所示。

   1: public sealed class ServiceSecurityAuditBehavior : IServiceBehavior
   2: {
   3:     //其他成员
   4:     public void ApplyDispatchBehavior(ServiceDescription serviceDescription, 
   5:     ServiceHostBase serviceHostBase)
   6:     {
   7:         foreach (ChannelDispatcher channelDispatcher in 
   8:            serviceHostBase.ChannelDispatchers)
   9:         {
  10:             foreach (EndpointDispatcher endpointDispatcher in channelDispatcher.Endpoints)
  11:             {
  12:                 DispatchRuntime dispatchRuntime = endpointDispatcher.DispatchRuntime;
  13:                 dispatchRuntime.SecurityAuditLogLocation = this.AuditLogLocation;
  14:                 dispatchRuntime.MessageAuthenticationAuditLevel = this.MessageAuthenticationAuditLevel;
  15:                 dispatchRuntime.ServiceAuthorizationAuditLevel = this.ServiceAuthorizationAuditLevel;
  16:                 dispatchRuntime.SuppressAuditFailure = this.SuppressAuditFailure;
  17:             }
  18:         }
  19:     }
  20: }

三、实例演示:如何实施安全审核

接下来我们通过一个简单的实例来演示如何进行针对认证和授权的安全审核,并且看看在认证或者授权成功或者失败的情况下,会有怎样的日志信息被记录下来。

基于认证的安全审核

先来演示针对认证的安全审核。我们还是直接使用一直在使用的计算服务的例子,服务契约和服务的定义我们已经很熟悉了,我们现在只来介绍采用的服务端的配置。从下面的配置可以看出,被寄宿的服务具有为一个基于WS2007HttpBinding的终结点,该绑定采用默认的Windows认证。通过服务行为,我们将安全审核的AuditLogLocation和MessageAuthenticationAuditLevel分别设置为Application和SuccessOrFailure。

   1: <configuration>
   2:   <system.serviceModel>    
   3:     <services>
   4:       <service name="Artech.WcfServices.Service.CalculatorService" 
   5:                behaviorConfiguration="authenticationAudit">
   6:         <endpoint address="http://127.0.0.1:3721/calculatorservice" 
   7:                   binding="ws2007HttpBinding" 
   8:                   contract="Artech.WcfServices.Service.Interface.ICalculator"/>
   9:       </service>
  10:     </services>
  11:     <behaviors>
  12:       <serviceBehaviors>
  13:         <behavior  name="authenticationAudit">
  14:           <serviceSecurityAudit auditLogLocation ="Application" 
  15:                                 messageAuthenticationAuditLevel ="SuccessOrFailure"/>
  16:         </behavior>
  17:       </serviceBehaviors>
  18:     </behaviors>
  19:   </system.serviceModel>
  20: </configuration>

客户端利用如下的代码进行服务的调用,两次服务调分别采用Foo和Bar两个本地Windows帐号进行,其中基于帐号Foo给定的密码是正确的,而基于帐号Bar给定的密码是错误的。而辅助方法Invoke旨在避免避免认证失败导致的异常是程序终止。

   1: ChannelFactory<ICalculator> channelFactory = new ChannelFactory<ICalculator>("calculatorService");
   2: NetworkCredential credential = channelFactory.Credentials.Windows.ClientCredential;
   3: credential.UserName = "Foo";
   4: credential.Password = "Password";
   5: ICalculator calculator = channelFactory.CreateChannel();
   6: Invoke(calculator);
   7:  
   8: channelFactory = new ChannelFactory<ICalculator>("calculatorService");
   9: credential = channelFactory.Credentials.Windows.ClientCredential;
  10: credential.UserName = "Bar";
  11: credential.Password = "InvalidPass";
  12: calculator = channelFactory.CreateChannel();
  13: Invoke(calculator);

由于我们通过配置将应用在服务上的ServiceSecurityAuditBehavior服务行为的AuditLogLocation和MessageAuthenticationAuditLevel分别设置为Application和SuccessOrFailure,意味着不论是认证成功或者失败都会进行安全审核日志。而审核日志最终会被写入EventLog的应用程序日志。当程序执行后,在事件查看器的应用程序节点,你会发现具有如下图所示的4条新的日志(之前的日志在程序运行前被清空)。

下面列出了这4条日志的内容。其中前3条基于认证成功的信息(Information)日志,最后一条是基于认证失败的错误(Error)日志。[源代码从这里下载]

   1: Security negotiation succeeded.
   2:  Service: http://127.0.0.1:3721/calculatorservice
   3:  Action: http://docs.oasis-open.org/ws-sx/ws-trust/200512/RSTR/Issue
   4:  ClientIdentity: Jinnan-PC\Foo; S-1-5-21-3534336654-2901585401-846244909-1006
   5:  ActivityId: <null>
   6:  Negotiation: SpnegoTokenAuthenticator
   7:  
   8: Message authentication succeeded.
   9:  Service: http://127.0.0.1:3721/calculatorservice
  10:  Action: http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/SCT
  11:  ClientIdentity: Jinnan-PC\Foo; S-1-5-21-3534336654-2901585401-846244909-1006
  12:  ActivityId: <null>
  13:  
  14: Message authentication succeeded.
  15:  Service: http://127.0.0.1:3721/calculatorservice
  16:  Action: http://www.artech.com/ICalculator/Add
  17:  ClientIdentity: Jinnan-PC\Foo; S-1-5-21-3534336654-2901585401-846244909-1006
  18:  ActivityId: <null>
  19:  
  20: Security negotiation failed.
  21:  Service: http://127.0.0.1:3721/calculatorservice
  22:  Action: http://docs.oasis-open.org/ws-sx/ws-trust/200512/RSTR/Issue
  23:  ClientIdentity: 
  24:  ActivityId: <null>
  25:  Negotiation: SpnegoTokenAuthenticator
  26:  Win32Exception: The Security Support Provider Interface (SSPI) negotiation failed.

基于授权的安全审核

接下来我们演示授权的安全审核,并查看分别在授权成功和失败的情况下分别由怎样的日志被写入到EventLog中。我们首先按照如下的方式在服务类型CalculatorService的Add方法上应用PrincipalPermissionAttribute特性使该方法只有在管理员才有权限调用。

   1: public class CalculatorService : ICalculator
   2: {
   3:     [PrincipalPermission(SecurityAction.Demand,Role="Administrators")]
   4:     public double Add(double x, double y)
   5:     {
   6:         return x + y;
   7:     }
   8: }

然后我们将服务端配置中关于安全审核的相关配置进行了如下的修改。我们只关心授权相关的安全审核,所以将messageAuthenticationAuditLevel属性替换成serviceAuthorizationAuditLevel。

   1: <configuration>
   2:   <system.serviceModel>   
   3:    ... 
   4:     <behaviors>
   5:       <serviceBehaviors>
   6:         <behavior  name="authenticationAudit">
   7:           <serviceSecurityAudit auditLogLocation ="Application" 
   8:                                 serviceAuthorizationAuditLevel ="SuccessOrFailure"/>
   9:         </behavior>
  10:       </serviceBehaviors>
  11:     </behaviors>
  12:   </system.serviceModel>
  13: </configuration>

客户端在进行服务调用的时候需要为帐号Bar指定正确的密码。和前面一样,这里的帐号Foo被预先添加到管理员用户组中,而Bar则没有,所以只有第一次服务调用才是被成功授权的。

   1: ChannelFactory<ICalculator> channelFactory = new ChannelFactory<ICalculator>("calculatorService");
   2: NetworkCredential credential = channelFactory.Credentials.Windows.ClientCredential;
   3: credential.UserName = "Foo";
   4: credential.Password = "Password";
   5: ICalculator calculator = channelFactory.CreateChannel();
   6: Invoke(calculator);
   7:  
   8: channelFactory = new ChannelFactory<ICalculator>("calculatorService");
   9: credential = channelFactory.Credentials.Windows.ClientCredential;
  10: credential.UserName = "Bar";
  11: credential.Password = "Password";
  12: calculator = channelFactory.CreateChannel();
  13: Invoke(calculator);

当客户端完成两次服务调用后,如下两条基于授权的审核日志被写入应用程序日志。虽然只有第一次服务调用才是真正被授权的操作,但是从日志的内容我们却发现两条均是“授权成功”的审核日志。[源代码从这里下载]

   1: Service authorization succeeded.
   2:  Service: http://127.0.0.1:3721/calculatorservice
   3:  Action: http://www.artech.com/ICalculator/Add
   4:  ClientIdentity: Jinnan-PC\Foo; S-1-5-21-3534336654-2901585401-846244909-1006
   5:  AuthorizationContext: uuid-528e86ce-a4f4-48b3-9a2e-b713e1dea539-1
   6:  ActivityId: <null>
   7:  ServiceAuthorizationManager: <default>
   8:  
   9: Service authorization succeeded.
  10:  Service: http://127.0.0.1:3721/calculatorservice
  11:  Action: http://www.artech.com/ICalculator/Add
  12:  ClientIdentity: Jinnan-PC\Bar; S-1-5-21-3534336654-2901585401-846244909-1007
  13:  AuthorizationContext: uuid-528e86ce-a4f4-48b3-9a2e-b713e1dea539-2
  14:  ActivityId: <null>
  15:  ServiceAuthorizationManager: <default>

实际对于安全审核中所谓的授权失败指的是调用ServiceAuthorizationManager的CheckAccess方法返回False的情况。在默认的情况下,ServiceAuthorizationManager的CheckAccess方法总是返回True,所以授权总是会“成功”。

为了迎合安全审核对“授权失败”的判断,我在Service项目中创建了如下一个简单的自定ServiceAuthorizationManager。在重写的CheckAccessCore方法中,如果当前用户是Foo(Jinnan-PC\Jinnan)就发返回True,否则返回False。

   1: using System.ServiceModel;
   2: namespace Artech.WcfServices.Service
   3: {
   4:     public class MyServiceAuthorizationManager : ServiceAuthorizationManager
   5:     {
   6:         protected override bool CheckAccessCore(OperationContext operationContext)
   7:         {
   8:             string userName = operationContext.ServiceSecurityContext.PrimaryIdentity.Name;
   9:             return  string.Compare(userName, @"Jinnan-PC\Foo",true) == 0;
  10:         }
  11:     }
  12: }

然后通过如下的配置将这个自定义的MyServiceAuthorizationManager应用到ServiceAuthorizationBehavior服务行为上。再次运行我们的程序,将会得到分别代表授权成功和失败的两条审核日志,并且在日志中还包含了我们自定的ServiceAuthorizationManager类型(ServiceAuthorizationManager:
MyServiceAuthorizationManager)。[源代码从这里下载]

   1: <configuration>
   2:   <system.serviceModel>    
   3:     ...
   4:     <behaviors>
   5:       <serviceBehaviors>
   6:         <behavior  name="authenticationAudit">
   7:           <serviceAuthorization serviceAuthorizationManagerType="Artech.WcfServices.Service.MyServiceAuthorizationManager, Artech.WcfServices.Service">
   8:           </serviceAuthorization>
   9:           <serviceSecurityAudit auditLogLocation ="Application" 
  10:                                 serviceAuthorizationAuditLevel ="SuccessOrFailure"/>
  11:         </behavior>
  12:       </serviceBehaviors>
  13:     </behaviors>
  14:   </system.serviceModel>
  15: </configuration>

授权成功/失败审核日志:

   1: Service authorization succeeded.
   2:  Service: http://127.0.0.1:3721/calculatorservice
   3:  Action: http://www.artech.com/ICalculator/Add
   4:  ClientIdentity: Jinnan-PC\Foo; S-1-5-21-3534336654-2901585401-846244909-1006
   5:  AuthorizationContext: uuid-91ff29c8-84cb-4c1a-837c-0913c12c0be5-1
   6:  ActivityId: <null>
   7:  ServiceAuthorizationManager: MyServiceAuthorizationManager
   8:  
   9: Service authorization failed.
  10:  Service: http://127.0.0.1:3721/calculatorservice
  11:  Action: http://www.artech.com/ICalculator/Add
  12:  ClientIdentity: Jinnan-PC\Bar; S-1-5-21-3534336654-2901585401-846244909-1007
  13:  AuthorizationContext: uuid-91ff29c8-84cb-4c1a-837c-0913c12c0be5-2
  14:  ActivityId: <null>
  15:  ServiceAuthorizationManager: MyServiceAuthorizationManager
  16:  FaultException: Access is denied.

作者:蒋金楠
微信公众账号:大内老A
微博:www.weibo.com/artech
如果你想及时得到个人撰写文章以及著作的消息推送,或者想看看个人推荐的技术资料,可以扫描左边二维码(或者长按识别二维码)关注个人公众号(原来公众帐号蒋金楠的自媒体将会停用)。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

原文链接

时间: 2024-10-29 03:05:39

WCF的安全审核——记录谁在敲打你的门的相关文章

WCF传输安全(Transfer Security)的基本概念和原理:认证(Authentication)[上篇]

对于任何一个企业级应用来说,安全(Security)都是一个不可回避的话题.如何识别用户的身份?如何将用户可执行的操作和可访问的资源限制在其允许的权限范围之内?如何记录用户行为,让相应的操作都有据可查?这些都是应用的安全机制或者安全框架需要考虑的典型问题,它们分别对应着三个安全行为:认证(Authentication).授权(Authorization)和审核(Auditing). 除了这些典型的安全问题,对于一个以消息作为通信手段的分布式应用,还需要考虑消息的保护(Message Protec

有关审核表设计上面的,求方案【在线等】

问题描述 有关审核表设计上面的,求方案[在线等] 业务是"资料审核",审核会出现多次不通过的情况:现在有两张表,一张company_info(公司信息)一张check_company_log(审核日志)如果审核不通过的情况下,要给用户看到不通过的原因: 目前的设计是check_company_log表里面有"原因"字段,company_info表里冗余一个"原因"(用于展示,当然这里面存的是最后一次不通过的原因) 每次不通过的时候,要做两个操作,

Win2000安全审核让入侵者无处遁形

作为一个网管员,你是否知道在你的主机或服务器上发生的事情--谁来访问过?他们都做过些什么?目的是什么?什么?你不知道!其实Windows 2000给我们提供了一项安全审核功能,我们做管理员这行的,最需要熟悉的就是这一功能了,否则你怎么管呢?安全审核可以用日志的形式记录好几种与安全相关的事件,你可以使用其中的信息来生成一个有规律活动的概要文件,发现和跟踪可疑事件,并留下关于某一侵入者活动的有效法律证据.打开审核策略Windows 2000的默认安装没有打开任何安全审核,所以需要进入[我的电脑]→[

Windows Server 2008中的审核和符合性

概览: 日益重要的符合性 了解环境中所发生的变更 审核安全事件所面临的挑战 审核的技术方面问题 在信息技术世界里,变更是永恒的.如果您的 IT 组织与大多数其他 IT 组织并无二致,那么了解在您的环境中所发生的变更就会成为您不得不面对的压力,而且这种压力与日俱增.IT 环境的复杂性和规模不断变大, 由于管理错误和意外数据泄漏所带来的影响也越来越严重.当今的社会要求组织对此类事件负责,因此组织现在担负着法律责任来保护它们所管理的信息. 这样一来,审核环境中所发生的变更也就变得至关重要.为什么呢?通

追踪记录每笔业务操作数据改变的利器——SQLCDC

对于大部分企业应用来用,有一个基本的功能必不可少,那就是Audit Trail或者Audit Log,中文翻译为追踪检查.审核检查或者审核记录.我们采用Audit Trail记录每一笔业务操作的基本信息,比如操作的基本描述.操作时间.操作者等.对于一些安全级别比较高的应用,或者操作一些比较敏感的数据,我们甚至需要记录该笔业务操作引起的数据的改变.具体来说,这里的"数据改变"指的是每一条影响的记录在操作执行前后的变化.对于添加的记录,需要记录下新插入的记录:对于删除的记录,需要记录下原来

SQLSERVER2008新增的审核/审计功能

原文:SQLSERVER2008新增的审核/审计功能 SQLSERVER2008新增的审核/审计功能 很多时候我们都需要对数据库或者数据库服务器实例进行审核/审计 例如对失败的登录次数进行审计,某个数据库上的DDL语句进行审计,某个数据库表里面的delete语句进行审计 事实上,我们这些审计的需求基本上都是为了一个目的:防黑客   上面的这些审计需求无非就是看一下有哪些人试图入侵数据库服务器,入侵了之后是否有drop表,是否有delete数据 在SQLSERVER2008及以前版本可以选择的方案

签核流程设计

在OA等一些系统中往往要签核,其实签核工作流分好几种,下面的只是一种. 下面是关于模拟签核WF的表的设计以及实现签核过程思路.             一.指明状态      1:新增 2:修改 3:核准 6:驳回 7:提交             二.签核表结构设计(CheckProgram )                1.签核程序表(一个程序一般只有一个签核路线)                      签核程序编号   签核路线编号   签核程序名称                

Windows系统安全设置方法--中级安全篇

1.利用win2000的安全配置工具来配置策略 微软提供了一套的基于MMC(管理控制台)安全配置和分析工具,利用他们你可以很方便的配置你的服务器以满足你的要求.具体内容请参考微软主页:http://www.microsoft.com/windows2000/techi...y/sctoolset.asp 2.关闭不必要的服务 windows 2000 的 Terminal Services(终端服务),IIS ,和RAS都可能给你的系统带来安全漏洞.为了能够在远程方便的管理服务器,很多机器的终端

Windows 2000 安全检查清单-中级篇

1.利用win2000的安全配置工具来配置策略 微软提供了一套的基于MMC(管理控制台)安全配置和分析工具,利用他们你可以很方便的配置你的服务器以满足你的要求.具体内容请参考微软主页: http://www.microsoft.com/windows2000/techinfo/howitworks/security/sctoolset.asp 2.关闭不必要的服务 Windows 2000的Terminal Services(终端服务),IIS和RAS都可能给你的系统带来安全漏洞.为了能够在远程