这个问题已解决,是绑定设置的问题,主要还是因为我自己没有深入理解WCF绑定的安全机制。在这篇博客里面我来说说怎么解决的。

下载了Artech的wcf petshop源码(博文链接)并调试运行成功后,打算在其之上增加授权功能,但是遇到了问题。

环境:windows8.1 企业版,VS2012, SQLExpress2008, IIS Express

首先我在原文中求助A大关于通过RoleManager获取角色是否可行,得到了A大的答复可行,于是我就在原来的项目的Common中增加了一个静态类用于获取角色并设置到当前线程的CurrentPrincipal,和还原CurrentPrincipal。代码如下:

 namespace Artech.PetShop.Common
{
/// <summary>
/// 根据当前用户名设置当前线程的Principal的类
/// </summary>
public static class SetThreadPrincipal
{
/// <summary>
/// 用于保存修改之前的Principal
/// </summary>
private static IPrincipal _oldPrincipal; /// <summary>
/// 设置当前线程的Principal,根据ApplicationContext里面的UserName是否存在来判断。
/// 通过Roles来获取对应UserName的角色。并将其设置到当前线程的CurrentPrincipal
/// </summary>
public static void SetThreadPrincipalToCurrentUser()
{
string username = ApplicationContext.Current.UserName;
if (!string.IsNullOrEmpty(username))
{
// 如果用户名为空,则说明不可能有用户信息,那就不用去取角色并放到线程中。
IIdentity identity;
identity = new GenericIdentity(username, Membership.Provider.Name); // TODO: Get Roles
string[] roles = Roles.GetRolesForUser(identity.Name);
IPrincipal principal = new GenericPrincipal(identity, roles); // Place user's principal on the thread
_oldPrincipal = Thread.CurrentPrincipal;
Thread.CurrentPrincipal = principal;
}
else
{// 如果用户名为空,则说明不可能有用户信息,那就不用去取角色并放到线程中。
// 这时候就不用设置oldPrincipal的值了。
_oldPrincipal = null;
}
} /// <summary>
/// 恢复线程的Principal
/// </summary>
public static void ResumeThreadPrincipal()
{
if (_oldPrincipal != null)
Thread.CurrentPrincipal = _oldPrincipal;
}
}
}

从代码中可以看到,如果取到上下文中的用户名之后就可以用户名对应的角色(关于Roles类的使用请微软搜索“角色提供”)。

然后我在ContextReceivalCallContextInitializer类的BeforeInvoke方法和AfterInvoke方法里面增加了对上面类的使用,代码如下:

ContextReceivalCallContextInitializer类在Infrastructure项目的WCF Extensions文件夹下。

     public class ContextReceivalCallContextInitializer : ICallContextInitializer
{
private IPrincipal _oldPrincipal;
#region ICallContextInitializer Members public void AfterInvoke(object correlationState)
{
// 恢复Principal
SetThreadPrincipal.ResumeThreadPrincipal();
} public object BeforeInvoke(InstanceContext instanceContext, IClientChannel channel, Message message)
{
ApplicationContext.Current = message.Headers.GetHeader<ApplicationContext>(
ApplicationContext.ContextHeaderLocalName,
ApplicationContext.ContextHeaderNamespace);
// 设置Principal
SetThreadPrincipal.SetThreadPrincipalToCurrentUser();
return null;
} #endregion
}

以上代码添加完成后,就可以见证奇迹了。点击启动调试(前提是已经配置成功可以运行)

登录、浏览pet信息、放入购物车略过,不用说了。看下面的图,已经放入购物车。

图:已经放入购物车

下一步,点击结账后,页面调用wcf,会进入ContextReceivalCallContextInitializer类的BeforeInvoke方法:

图:进入BeforeInvoke断点

按下F10,单步执行到return。

图:设置当前Principal结束

从监视窗口可以看到,线程的CurrentPrincipal已经成功设置。用户名和角色都OK的。

图:设置成功

这时,我们按下F5让程序继续进行,来到业务处理的断点处,奇迹就发生了:

图:来到业务处理

查看监视窗口,现成的当前Principal变了!

图:他竟然变成了我的windowsPrincipal!

然后继续执行,来到ContextReceivalCallContextInitializer的AfterInvoke方法时,又变回来了。

图:Principal回来了。

我反复尝试了多次都是这样!抓狂了。

如果我加上权限限制的代码,就会告诉我权限不对。

图:加上限制

再次执行就会在AuditCallHandler的Invoke方法里面看到异常:

图:异常

页面上也会告诉你,访问失败。

我无法理解这个问题到底是为什么,只好找个变通的方法来解决,把设置线程Principal的代码放到了OrderService里面:

        [OperationBehavior(TransactionScopeRequired= true)]
[AuditCallHandler("提交订单")]
public void Submit(Order order)
{
// 设置Principal
SetThreadPrincipal.SetThreadPrincipalToCurrentUser();
this.BusinessComponent.Submit(order);
// 恢复Principal
SetThreadPrincipal.ResumeThreadPrincipal();
}

并将限制代码放到BusinessComponent的Submit里面:

        // 限制权限
[PrincipalPermission(SecurityAction.Demand, Role = "User")]
public void Submit(Order order)
{
this.ValidateInventory(order);
this.DataAccess.Submit(order);
}

这样,再次进行订单结账操作就能成功了。

这个问题到底是为什么呢。我真的百思不得其解啊。

【已解决】谁动了我的CurrentPrincipal?求助我在给Artech的wcf petshop增加授权机制的时候遇到的问题。的更多相关文章

  1. 【已解决】[求助] 求虚拟机防检测代码-VM虚拟机防游戏检测(虚拟机躲避游戏检测工具)

    [已解决][求助] 求虚拟机防检测代码 虚拟机如何躲过游戏等软件的检测,并能用vmware tools: 先把vmtools安装好后!   然后用这代码 monitor_control.restric ...

  2. WPF不明内存泄露已解决,白头发也没了

    原文:WPF不明内存泄露已解决,白头发也没了 在使用OpenExpressApp进行WPF应用开发过程中遇到多个内存泄漏的地方,在上一篇中求助了一个内存泄露问题[WPF不明内存泄露原因,头发都白了几根 ...

  3. Microsoft.Office.Interop.Excel, Version=12.0.0.0版本高于引用的程序集(已解决)

    Microsoft.Office.Interop.Excel, Version=12.0.0.0版本高于引用的程序集(已解决) 论坛里的帮助:http://bbs.csdn.net/topics/39 ...

  4. 使用Notepad++编码编译时报错(已解决?)

    使用Notepad++编码编译时报错(已解决?) 使用Notepad++编码,编译的时候经常会报错,说什么GBK编码啥啥啥~~~但同样的编码用ECLIPSE就没有问题.再有,用记事本把他保存成ANSI ...

  5. 已解决】Sublime中运行带input或raw_input的Python代码出错:EOFError: EOF when reading a line(转)

    [问题] 在折腾: [已解决]Sublime Text 2中运行Python程序出错:The system cannot find the file specified 的过程中,虽然解决了找不到py ...

  6. 【已解决】Android ADT中增大AVD内存后无法启动:emulator failed to allocate memory 8

    [问题] 折腾: [已解决]Android ADT中增大AVD内存后无法启动:emulator failed to allocate memory 8 过程中,增大对应AVD的内存为2G后,结果无法启 ...

  7. 【已解决】BeautifulSoup已经获得了Unicode的Soup但是print出来却是乱码

    [问题] 某人遇到的问题: 关于BeautifulSoup抓取表格及SAE数据库导入的问题(跪求大神帮忙) 简单说就是: 用如下代码: ? 1 2 3 4 5 6 7 import re,urllib ...

  8. Access中出现改变字段“自己主动编号”类型,不能再改回来!(已解决)

    Access中出现改变字段"自己主动编号"类型,不能再改回来! (已解决) 一次把access中的自增字段改成了数值,再改回自增时,提示:在表中输入了数据之后,则不能将不论什么字段 ...

  9. sqlserver,执行生成脚本时“引发类型为“System.OutOfMemoryException”的异常”(已解决)

    sqlserver,执行生成脚本时“引发类型为“System.OutOfMemoryException”的异常”(已解决) 出现此错误主要是因为.sql的脚本文件过大(一般都超过100M)造成内存无法 ...

随机推荐

  1. Asp.Net请求处理机制中IsApiRuntime解析

    今天看了web请求的生命周期,看完了还有些不懂,就是用反编译工具,查看封装内库的内部实现. 从计算机内部查到web.dll,使用反编译工具打开 打开后 public int ProcessReques ...

  2. day5_python学习笔记_chapter6_字符串列表元组

    1. 序列:seq[n], seq[x:y], seq * n序列重复n次,切片, 序列翻转 s=”abcde", s[::-1]="edcba" 内建函数:1. 类型转 ...

  3. [互联网面试笔试汇总C/C++-9] 实现赋值运算符函数-剑指offer

    题目:如下为类型CMyString的声明,请为该类型添加赋值运算符函数. class CMyString { public: CMyString(char* pData = NULL); CMyStr ...

  4. Windows系统下远程Linux系统

    Windows系统下远程Linux系统 工具:Xmanager 启动界面: 配置保存路径(win7): C:\Users\Administrator\AppData\Roaming\NetSarang ...

  5. PHP中的一个很好用的文件上传类

    <?php    class FileUpload{      private $filepath; //设置上传文件的路径   private $allowtype=array('jpg',' ...

  6. js 定义类对象

    //定义类     //方式一     function A_class(arg1,arg2){         this.arg1=arg1;         this.arg2=arg2;     ...

  7. C#编写的windows服务安装后启动提示“服务启动后又停止了”

    使用C#编写的windows服务安装到服务器上行后进行启动时,总是提示“服务启动后又停止了”. 检查了服务逻辑是没问题,安装在开发本地也是正常,网上查了资料说是可能是服务没有注册,我检查了服务是正常注 ...

  8. 【转载】Qt中的QString,QByteArray,Qchar, char*

    先要说的是QString.         之所以把QString单独拿出来,是因为string是很常用的一个数据结构,甚至在很多语言中,比如JavaScript,都是把string作为一种同int等 ...

  9. POJ 1840 Brainman(逆序对数)

    题目链接:http://poj.org/problem?id=1804 题意:给定一个序列a[],每次只允许交换相邻两个数,最少要交换多少次才能把它变成非递降序列. 思路:题目就是要求逆序对数,我们知 ...

  10. centos6.5 升级python 到 python 2.7.11 安装 pip

    1.首先官方下载源码,然后安装(./configure,make all,make install,make clean,make distclean) 注意:需要先安装zlib-devel,open ...