参考了蒋金楠老师08年的文章。好吧,那时候我才大二、大三,大神果然是大神。 http://www.cnblogs.com/artech/archive/2008/09/01/1280939.html
在使用AX2012 AIF服务的时候,有一个问题一直困扰着我,那就是访问权限的认证。
众所周知AX2012的权限认证是基于AD的,但有些客户端机器的AD账户,并没有AX2012的访问权限,甚至没有加入AD中(如PDA客户端)。
按照微软的最佳实践,应该使用声明账户和可信中介这样两样技术,来实现客户端-》WCF中间层(可信中介)-》AIF服务。这样做好处,是客户端不用加入AD中,并且可以将客户端登陆账户权限的管理,纳入到AX中。
如果使用AX2012的自定义服务,会在AOS中有多个数据契约和服务操作,如果一个一个再在WCF中间层去重复造*,有些麻烦。能不能将中间层进行简化成,只是将客户端请求转发给AIF,将AIF的响应返回给客户端呢?
答案肯定是可以的咯,不然我也不会写这篇文章。具体可以参考上面蒋金楠老师博文的链接。
1新建一个WCF类库程序,代码如下:
namespace MessageInterceptor { [ServiceContract] public interface IIntercept { [OperationContract(Action ="*", ReplyAction="*")] Message Intercept(Message request); } [ServiceBehavior(UseSynchronizationContext = false, AddressFilterMode = AddressFilterMode.Any)] public class InterceptService : IIntercept { public System.ServiceModel.Channels.Message Intercept(System.ServiceModel.Channels.Message request) {
{ IIntercept interceptor = channelFactory.CreateChannel(); using (interceptor as IDisposable) { MessageBuffer requstBuffer = request.CreateBufferedCopy(int.MaxValue); Message response = interceptor.Intercept(requstBuffer.CreateMessage()); MessageBuffer responseBuffer = response.CreateBufferedCopy(int.MaxValue); Console.WriteLine(string.Format("Request:{0}{1}{0}", Environment.NewLine, request)); Console.WriteLine(string.Format("Response:{0}{1}{0}", Environment.NewLine, response)); return responseBuffer.CreateMessage(); } } } } } |
该数据契约有以下两个特点:
- Intercept的参数和返回值都是Message对象。
- Operation的Action和ReplyAction为*。
无论参数的个数,类型,次序是怎样的,但WCF的调用最终是基于Message的,也就是参数或返回值最终都会呈现为Message对象。
Operation Selection的匹配规则是:Contract Namespace(default:http://tempuri.org)/Contract Name(default:Interface name)/Action(default:method name)= action in SOAP header。如果将Action设为"*",则意味着该服务的调用,无路SOAP Header中action是什么,都将交付Intercept来处理。
ChannelFactory构造函数的参数,是配置中,Client节点的endpoint的name值。
AddressFilterMode = AddressFilterMode.Any:在上面我们提到过,ChannelDispatcher在选择EndpointDispacher的时候是基于两个Message Filter:Address Filter和Contract Filter。也就是说,ChannelDispatcher通过这两个Filter选择合适Endpoint。在默认的情况下,Address Filter是根据SOAP的To Message Header的URI来进行栓选的,所以需要Endpoint的Address和To Header中的Addres完全匹配。但是在我们CalculateService的例子中,由于Client最终是访问的时CalculateService,所以生成的SOAP的To Headler的地址是CalculateService的地址:http://127.0.0.1:9999/calculateservice,而我们需要是用InterceptService 来处理该请求,Address Filtering肯定是不能通过的。好在我们可以在ServiceBehavior设置AddressFilterMode 来改变Address Filtering的方式。AddressFilterMode = AddressFilterMode.Any意味着,Address Filtering会被忽略。
CreateBufferedCopy:可能有人会奇怪,为什么不对request message和response message进行直接操作(将他们显示在TextBox上)?这是应为Message在WCF有一个特殊的处理机制:只有Message的State为Created的时候,才能获取MessageBody的内容,否则会抛出异常。而我们在对Message进行相应操作的时候,会改变Message 的State(Read,Written,Copied,Closed)。所以对response message来讲,对message的显示实际上将Sate改为Read,如何将response message直接返回到client,对该message的读取操作将是不允许的,所以先调用CreateBufferedCopy创建该message的一个memory buffer,最有返回的时通过该buffer重新创建的Message。
2新建Windows服务,作为上面WCF服务的宿主程序。
代码如下:
namespace MiddleTierWcfWindowsService { public partial class Service : ServiceBase { ServiceHost host; public Service() { InitializeComponent(); } protected override void OnStart(string[] args) { host = new ServiceHost(typeof(MessageInterceptor.InterceptService)); host.Open(); } protected override void OnStop() { host.Close(); } } } |
3为Windows服务添加应用程序配置App.config
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.serviceModel> <bindings> <netTcpBinding> <binding name="aaaaaaaaa" /> </netTcpBinding> </bindings> <client> <endpoint address="net.tcp://bbbbbbbbb" binding="netTcpBinding" bindingConfiguration="aaaaaaaaa" contract="eeeeeeeee" name="ccccccccc"> </endpoint> </client> <services> <service name="HHHHHHHHH"> <endpoint binding="netTcpBinding" bindingConfiguration="aaaaaaaaa" contract="eeeeeeeee" address="net.tcp://ddddddddd"/> </service> </services> </system.serviceModel> </configuration> |
AAAAAAAAA:这里我使用了NetTcpBinding,作为客户端-》WCF中间层(可信中介)-》AIF服务端的终结点的binding,你也可以选择适合自己的。
BBBBBBBBB:这里是AIF中,服务的URI。
CCCCCCCCC:这里是上面WCF中间层类库接口的实现中,ChannelFactory构造函数的参数,本例中是calculateService。
DDDDDDDDD:这里是WCF中间层的终结点地址。
EEEEEEEEE:是client和service的contract契约,都使用的是WCF中间层类库中的接口的"命名空间+接口名"。本例子中是MessageInterceptor.IIntercept。
HHHHHHHHH:是接口的实现。本例中是MessageInterceptor.InterceptService 。
4设置Windows服务的Service设计视图的ServiceName,用于在日志中显示。
5在Windows服务的Service设计视图上点右键,添加安装程序。
6在新添加的安装程序中,将serviceProcessInstaller1的Account设为LocalService。即,启动时,以本地服务方式登录。
7将serviceInstaller1的Description,DisplayName,ServiceName,都设置下,用于在系统服务中显示。
8安装生成的服务。
9在系统服务中,找到该服务,右键,属性,登录,登录为AX中的系统服务账户,如BC账户,密码为BC账户的密码。
10客户端的配置文件里,新增一个终结点行为。
<system.serviceModel> <behaviors> <endpointBehaviors> <behavior name="FFFFFFFFF"> <clientVia viaUri="net.tcp://DDDDDDDDD" /> </behavior> </endpointBehaviors> </behaviors> <bindings> <netTcpBinding> <binding name="AAAAAAAAA" /> </netTcpBinding> </bindings> <client> <endpoint address="net.tcp://BBBBBBBBB" behaviorConfiguration="FFFFFFFFF" binding="netTcpBinding" bindingConfiguration="AAAAAAAAA" contract="GGGGGGGGG" name="CCCCCCCCC"> </endpoint> </client> </system.serviceModel> |
A、B、C、D、如上面所述。
FFFFFFFFF:终结点行为的名称。
GGGGGGGGG:AIF服务中,"命名空间+数据契约"的名字。本例为,MessageInterceptor.ICalculate
11结束
至此,WCF中间层的转发,已经设置好了。
在客户端,可以以context.LogonAsUser=aaa@bbb.com;的方法,用AX中的账户进行操作,系统会检查该账户的数据权限。在表中,记录的createdBy等系统字段,会显示为该AD用户的别名。
如果使用客户端的人员为一线工人,可能没有AX账户,所以此处建议不设置。表中的createdBy等系统字段,记录是BC账户的别名,使用的是BC的数据权限。
Dynamics AX 2012 R2 Service Middle Tier WCF WCF转发的更多相关文章
-
Dynamics AX 2012 R2 电子邮件广播错误 0x80040213
Dynamics AX 2012 R2 电子邮件广播错误 0x80040213 今天Reinhard在新环境做邮件广播测试时,发现无法发送邮件,并报以下错误: 类"CDO.Message&q ...
-
Dynamics AX 2012 R2 安装Reporting Services 扩展
今天Reinhard在VS中部署SSRS报表时,接到以下错误: 部署因错误而被取消.在报表服务器上,验证:-SQL Server Reporting Services 服务是否正在运行. 接着,Rei ...
-
Dynamics AX 2012 R2 如何处理运行时间较长的报表
当处理的数据量较多,逻辑比较复杂时,报表可能会超时.为了解决这个问题,Reinhard一直使用SrsReportDataProviderPreProcess来做预处理报表.它会在调用SSRS前,在AX ...
-
Dynamics AX 2012 R2 安装额外的AOS
众所周知,AX系统分为三层:Client,Application Server,Database Server. 我们添加额外的Application Server主要是出于以下两个原因: 使用多台服 ...
-
Dynamics AX 2012 R2 业务系列-销售业务流程
在博文Dynamics AX R2 业务系列中,Reinhard对这个系列做了一个规划,下面我们就按照规划开始说业务吧. 1.销售的主要职责 其实这里说的职责主要是针对销售文员,并非整天外面满世界跑业 ...
-
Dynamics AX 2012 R2 业务系列-采购业务流程
在博文Dynamics AX R2 业务系列中,Reinhard对这个系列做了一个规划,下面我们就按照规划开始说业务吧. 国际惯例,从采购开始. 1.采购的主要职责 简单点说,采购的主要职责,是从供应 ...
-
Dynamics AX 2012 R2 安装 AIF IIS上的Web服务
1.为什么使用IIS上的WEB服务 组件? 如果你要在Dynamics AX Service中使用HTTP Adapter,那么你就要安装IIS上的WEB服务 组件.HTTP Adapter会在IIS ...
-
Dynamics AX 2012 R2 业务系列
在之前的一系列博文里,Reinhard介绍了Dynamics AX Demo的安装与配置.相信同学们看完后,都已经成功拥有了一个测试环境. 众所周知的是,ERP作为一个特殊的软件系统,他有着背后的业务 ...
-
[译]Dynamics AX 2012 R2 BI系列-规划分析的注意事项
https://msdn.microsoft.com/en-us/library/gg731898.aspx 在开始实施AX的分析特性前,有很多事情要考虑.本文描述了你必须考虑的事情,和在 ...
随机推荐
-
JSP连接数据库
1.将c3p0-0.9.5.2.jar/mchange-commons-java-0.2.11.jar/ojdbc6.jar三个包放在WEB-INF的lib文件夹下,将web.xml文件放到WEB-I ...
-
从Hadoop Summit 2016看大数据行业与Hadoop的发展
前言: 好吧我承认已经有四年多没有更新博客了.... 在这四年中发生了很多事情,换了工作,换了工作的方向.在工作的第一年的时候接触机器学习,从那之后的一年非常*的学习机器学习的相关技术,也写了一些自 ...
-
gnuplot conditional plotting: plot col A:col B if col C == x
http://*.com/questions/6564561/gnuplot-conditional-plotting-plot-col-acol-b-if-col-c-x H ...
-
【风马一族_Android】造作app的效果图
一.墨刀 官网:https://modao.cc
-
DEV GridControl表格数据源为空在表格中间显示提醒字符
private static void gv_CustomDrawEmptyForeground(object sender, DevExpress.XtraGrid.Views.Base.Custo ...
-
NEON简单介绍
个128位四字寄存器Q0-Q15,32个64位双字寄存器D0-D31,两个寄存器是重叠的,在使用的时候须要特别注意,不小心就会被覆盖掉. NEON的数据类型:无符号整数.有符号整数.未指定类型的整数. ...
-
HDFS Architecture
http://hadoop.apache.org/docs/r2.9.0/hadoop-project-dist/hadoop-hdfs/HdfsDesign.html Introduction Ha ...
-
django(权限、认证)系统——自定义UserProfile储存User额外信息
上篇文章我们引出了Django内置的权限控制系统,讲了安装,和最核心和基本的User模型的API和其Manager的API. 接下来我们继续深入下去,使用User对象做一些事情,首先当然就是创建一个U ...
-
最小生成树(kruskal算法)
首先明确三个概念: 1.最小生成树的特点? 答:假设某个连通网络由n个顶点组成,则其生成树必含n个顶点和n-1条边,而最小生成树的n-1条有个要求:总和最小. 2.并查集的运用? 答:在该问题中,首先 ...
-
VS发布网站时,报错提示:“未能将文件xxx复制到xxx,未能找到文件xx”三种解决方案!
发布网站时候大家可能会遇到这样的情况,就是报错提示说:“未能将文件xxx复制到xxx,未能找到文件xx”,这个问题一般来说有三种解决方案,个人倾向第三种,如图: 解决方案如下: 方案一.把系统提示缺失 ...