[WCF权限控制]基于Windows用户组的授权方式[下篇]
为了让读者对基于Windows用户组的授权具有深刻的认识,接下来我们通过一个简单的事例来讲解在真正的应用中该授权模式如何使用。对于接下来演示的事例,我们将采用Windows认证和授权。至于授权的最终实现,我们采用的是在服务方法上面应用PrincipalPermissionAttribute特性方式的声明式授权。[源代码从这里下载]
目录: 步骤一、创建测试帐号 步骤二、创建服务契约和服务 步骤三、寄宿服务 步骤四、创建客户端程序
步骤一、创建测试帐号
在创建事例解决方案之前我们先完成相应的准备工作,创建两个测试用的Windows帐号。假设两个帐号的名称分别为Foo和Bar,密码为Password。然后将帐号Foo添加到管理员(Administrators)用户组中。
步骤二、创建服务契约和服务
我们依然沿用我们再熟悉不过的计算服务的例子,解决方案依然按照如下图所示的结构来设计。整个解决方式包括四个项目:Contracts、Services、Hosting和Client。对于这样的结构我们已经了解得够多了,在这里没有必要再赘言叙述了。
在实例解决方案的整个结构建立之后,我们分别在Contracts和Services项目中定义服务契约接口和服务类型。下面是契约接口ICalculator和服务CalculatorService的定义。而在CalculatorService类的Add方法中应用了PrincipalPermissionAttribute特性,并将Roles属性设置成了Adminstrators,意味着该服务操作只能被管理员用户组中的用户调用。
ICalculator:
1: using System.ServiceModel;
2: namespace Artech.WcfServices.Contracts
3: {
4: [ServiceContract(Namespace = "http://www.artech.com/")]
5: public interface ICalculator
6: {
7: [OperationContract]
8: double Add(double x, double y);
9: }
10: }
CalculatorService:
1: using System.Security.Permissions;
2: using Artech.WcfServices.Contracts;
3: namespace Artech.WcfServices.Services
4: {
5: public class CalculatorService : ICalculator
6: {
7: [PrincipalPermission(SecurityAction.Demand, Role = "Administrators")]
8: public double Add(double x, double y)
9: {
10: return x + y;
11: }
12: }
13: }
步骤三、寄宿服务
现在通过Hosting这个控制台程序对上面创建的服务进行寄宿。下面给出的是整个寄宿程序的配置。从该配置我们可以看到,服务唯一的终结点采用的绑定类型为WS2007HttpBinding。而在默认的情况下,WS2007HttpBinding采用Message安全模式和Windows认证方式。此外,基于UseWindowsGroups安全主体权限模式的ServiceAuthorization服务行为被应用到了该服务上。
1: <?xml version="1.0"?>
2: <configuration>
3: <system.serviceModel>
4: <services>
5: <service name="Artech.WcfServices.Services.CalculatorService" behaviorConfiguration="useWindowsGroupsAuthorization">
6: <endpoint address="http://127.0.0.1/calculatorservice" binding="ws2007HttpBinding"
7: contract="Artech.WcfServices.Contracts.ICalculator"/>
8: </service>
9: </services>
10: <behaviors>
11: <serviceBehaviors>
12: <behavior name="useWindowsGroupsAuthorization">
13: <serviceAuthorization principalPermissionMode="UseWindowsGroups"/>
14: </behavior>
15: </serviceBehaviors>
16: </behaviors>
17: </system.serviceModel>
18: </configuration>
而服务寄宿的程序依然简洁如故,仅仅包括正对寄宿服务类型的ServiceHost的创建和开启而已。
1: using System.ServiceModel;
2: using Artech.WcfServices.Services;
3: using System;
4: namespace Artech.WcfServices.Hosting
5: {
6: public class Program
7: {
8: static void Main(string[] args)
9: {
10: using (ServiceHost host = new ServiceHost(typeof(CalculatorService)))
11: {
12: host.Open();
13: Console.Read();
14: }
15: }
16: }
17: }
步骤四、创建客户端程序
来到整个实例的最后一个步骤,我们将服务调用的客户程序定义在Client项目中。整个实例演示的目的在于确认针对服务操作Add的授权根据Windows用户组进行的,我们只需要关注被授权的服务操作是否被成功调用。为此,我写了如下一个简单的辅助性的方法Invoke。如果服务操作被成功执行,输出“服务调用成功”,如果抛出异常则输出“服务调用失败”。
1: static void Invoke(ICalculator calculator)
2: {
3: try
4: {
5: calculator.Add(1,2);
6: Console.WriteLine("服务调用成功...");
7: }
8: catch (Exception ex)
9: {
10: Console.WriteLine("服务调用失败...");
11: }
12: }
下面演示了完整的客户端程序和响应的配置。整个程序体现了两次针对相同服务操作的调用,而两次服务调用采用的客户端凭证分别是基于之前创建的两个Windows帐号Foo和Bar。
客户端程序:
1: using System.Net;
2: using System.ServiceModel;
3: using Artech.WcfServices.Contracts;
4: namespace Artech.WcfServices.Clients
5: {
6: class Program
7: {
8: static void Main(string[] args)
9: {
10:
11: ChannelFactory<ICalculator> channelFactory = new ChannelFactory<ICalculator>("calculatorService");
12: NetworkCredential credential = channelFactory.Credentials.Windows.ClientCredential;
13: credential.UserName = "Foo";
14: credential.Password = "Password";
15: ICalculator calculator = channelFactory.CreateChannel();
16: Invoke(calculator);
17:
18: channelFactory = new ChannelFactory<ICalculator>("calculatorService");
19: credential = channelFactory.Credentials.Windows.ClientCredential;
20: credential.UserName = "Bar";
21: credential.Password = "Password";
22: calculator = channelFactory.CreateChannel();
23: Invoke(calculator);
24:
25: Console.Read();
26: }
27:
28: }
29: }
配置:
1: <?xml version="1.0"?>
2: <configuration>
3: <system.serviceModel>
4: <client>
5: <endpoint name="calculatorService" address="http://127.0.0.1/calculatorservice" binding="ws2007HttpBinding"
6: contract="Artech.WcfServices.Contracts.ICalculator"/>
7: </client>
8: </system.serviceModel>
9: </configuration>
由于调用的服务操作需要具有管理员权限采用调用,所以以Foo名义进行调用是没有为题的,但是对于帐号Bar,由于权限不足将会调用失败。而客户端输出的结果反映了这一点。
1: 服务调用成功...
2: 服务调用失败...
注: 对于这个事例演示来说,服务操作只有具有管理员权限方能被正常调用。虽然我们创建的Windows帐号Foo在管理员用户组中,但是如果你使用Vista、Windows Server 2008和Windows 7这三种操作系统,在UAC开启的情况下,即使你以管理员运行我们的演示程序,Foo也不具有管理员权限。所以,你需要关闭UAC采用得到正确的执行结果,否则两次调用都是输出“服务调用失败...”。
- hbase源码系列(二)HTable 探秘
- hbase源码系列(三)Client如何找到正确的Region Server
- hbase源码系列(五)Trie单词查找树
- 如何在特定的渗透测试中使用正确的Burp扩展插件
- hbase源码系列(十一)Put、Delete在服务端是如何处理?
- 大数据如何帮飞机节油?
- hbase源码系列(十二)Get、Scan在服务端是如何处理?
- OpenStack:建立虚拟的渗透测试实验环境 – 网络篇
- Kettle 添加对应hadoop版本的支持
- Layui常用方法
- 使用Identity Server 4建立Authorization Server (4)
- 使用Identity Server 4建立Authorization Server (3)
- 使用Identity Server 4建立Authorization Server (2)
- 使用Identity Server 4建立Authorization Server (1)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Chrome终于上线这项重磅功能,中国用户苦等多年!
- YOLO 算法最全综述:从 YOLOv1 到 YOLOv5
- 《JavaScript ES6 函数式编程入门经典》读书笔记
- Java9-Reactive Stream API响应式编程
- mybatis-plus增删改查以及前后端分离模式下的项目应用
- docker(常用软件安装)
- PyTorch版:集成注意力和MobileNet的YOLOv4
- 从源代码级别看懂MinIO对象存储网关的实现
- 4种主流超参数调优技术
- 一分钟学Python| 面向对象(上)
- Python 为什么不支持 switch 语句?
- 你还在认为 count(1) 比 count(*) 效率高?
- 一分钟学Python| 面向对象(中)
- uni-app自定义打包目录package.json命令配置
- 在Zeppelin中如何使用Hive