【已解决】谁动了我的CurrentPrincipal?求助我在给Artech的wcf petshop增加授权机制的时候遇到的问题。
这个问题已解决,是绑定设置的问题,主要还是因为我自己没有深入理解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增加授权机制的时候遇到的问题。的更多相关文章
- 【已解决】[求助] 求虚拟机防检测代码-VM虚拟机防游戏检测(虚拟机躲避游戏检测工具)
[已解决][求助] 求虚拟机防检测代码 虚拟机如何躲过游戏等软件的检测,并能用vmware tools: 先把vmtools安装好后! 然后用这代码 monitor_control.restric ...
- WPF不明内存泄露已解决,白头发也没了
原文:WPF不明内存泄露已解决,白头发也没了 在使用OpenExpressApp进行WPF应用开发过程中遇到多个内存泄漏的地方,在上一篇中求助了一个内存泄露问题[WPF不明内存泄露原因,头发都白了几根 ...
- Microsoft.Office.Interop.Excel, Version=12.0.0.0版本高于引用的程序集(已解决)
Microsoft.Office.Interop.Excel, Version=12.0.0.0版本高于引用的程序集(已解决) 论坛里的帮助:http://bbs.csdn.net/topics/39 ...
- 使用Notepad++编码编译时报错(已解决?)
使用Notepad++编码编译时报错(已解决?) 使用Notepad++编码,编译的时候经常会报错,说什么GBK编码啥啥啥~~~但同样的编码用ECLIPSE就没有问题.再有,用记事本把他保存成ANSI ...
- 已解决】Sublime中运行带input或raw_input的Python代码出错:EOFError: EOF when reading a line(转)
[问题] 在折腾: [已解决]Sublime Text 2中运行Python程序出错:The system cannot find the file specified 的过程中,虽然解决了找不到py ...
- 【已解决】Android ADT中增大AVD内存后无法启动:emulator failed to allocate memory 8
[问题] 折腾: [已解决]Android ADT中增大AVD内存后无法启动:emulator failed to allocate memory 8 过程中,增大对应AVD的内存为2G后,结果无法启 ...
- 【已解决】BeautifulSoup已经获得了Unicode的Soup但是print出来却是乱码
[问题] 某人遇到的问题: 关于BeautifulSoup抓取表格及SAE数据库导入的问题(跪求大神帮忙) 简单说就是: 用如下代码: ? 1 2 3 4 5 6 7 import re,urllib ...
- Access中出现改变字段“自己主动编号”类型,不能再改回来!(已解决)
Access中出现改变字段"自己主动编号"类型,不能再改回来! (已解决) 一次把access中的自增字段改成了数值,再改回自增时,提示:在表中输入了数据之后,则不能将不论什么字段 ...
- sqlserver,执行生成脚本时“引发类型为“System.OutOfMemoryException”的异常”(已解决)
sqlserver,执行生成脚本时“引发类型为“System.OutOfMemoryException”的异常”(已解决) 出现此错误主要是因为.sql的脚本文件过大(一般都超过100M)造成内存无法 ...
随机推荐
- mina学习资料整合
最好的资料当然是官方文档:https://mina.apache.org/mina-project/userguide/user-guide-toc.html 官方文档,配合源码中的example例子 ...
- python一些模块的exe安装包在windows的64位系统里识别不到已安装Python目录的解决方法
在windows里安装python一些模块时候,有时候源码安装比较困难,pip install也各种报错,这时候最喜欢用别人编译好的exe或者whl文件来安装,但是在windows的64位系统里,如果 ...
- linux中的ps命令用法。
在linux中使用ps命令可以查看有哪些进程在运行和运行的状态.进程是否结束.进程有没有僵尸.哪些进程占用了过多的资源等等. ps命令最常用的是用于监控后台进程的工作情况. 名称:ps 使用权限:所有 ...
- CCNA实验(2) -- Static Route
1.静态路由R1:ip route 22.1.1.0 255.255.255.0 12.1.1.2 2.静态汇总路由R1:ip route 22.1.0.0 255.255.0.0 12.1.1.2 ...
- 宣布发布全新的 Windows Azure 缓存预览版
全新 Windows Azure 缓存的预览版现已发布.此托管服务可以提供闪电般的数据访问速度,以帮助您构建更具可伸缩性.响应更快的应用程序. 详情如下: · 托管式缓存:这一全新的托管服务为需 ...
- UVA-Matrix Chain Multiplication(栈)
Matrix Chain Multiplication Suppose you have to evaluate an expression like A*B*C*D*E where A,B,C, ...
- 7kb的javascript日期操作类库(XDate)
A Modern JavaScript Date Library XDate is a thin wrapper around JavaScript's native Date object that ...
- 在Sharepoint中批量删除大量条目
在Sharepoint开发中可能需要一次删除成百上千条记录,这时候如果轮询SPList.Items并直接调用该对象的删除方法来删除的话性能极差,会叫你崩溃. 下面介绍一个快速删除大量数据的方法: us ...
- eclipse自动生成的appcompat_v7出错
用eclipse新建Android工程时,自动生成的appcompat_v7出错,有个红色交叉,而且新建的Android工程有一个红色感叹号. 这时你去看看你新建的Android工程是不是没有生成R文 ...
- c#打包文件解压缩
首先要引用一下类库:using Ionic.Zip;这个类库可以到网上下载. 下面对类库使用的封装方法: /// <summary> /// 得到指定的输入流的ZIP ...