【已解决】谁动了我的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例子 ...
- 搭建单节点Hadoop应用环境
虚拟机: VirtualBox 5 Server操作系统: Ubuntu Server 14.04.3 LTS 如果对虚拟机空间和性能不做考虑, 且不习惯用Linux命令, 你也可以使用Ubuntu ...
- hadoop搭建杂记:Linux下不同linux主机之间文件copy的scp命令
不同的Linux之间copy文件常用有3种方法: 不同的Linux之间copy文件常用有3种方法: ①ftp 就是其中一台Linux安装ftp Server,这样可以另外一台使用ftp的程序来进行文件 ...
- (转)《JAVA与模式》之模板方法模式
该文章转自:http://www.cnblogs.com/java-my-life/archive/2012/05/14/2495235.html 在阎宏博士的<JAVA与模式>一书中开头 ...
- 成为 Linux 内核高手的四个方法
(之前我在 CUSEC 网站发表了关于内核并不可怕的一篇文章,本文是后续.) 我曾经问别人如何开始内核编程的学习,他们基本上都说:1. 如果你不需要了解内核是如何为你工作的,你为何要尝试呢?2. 你应 ...
- Delphi2010的RTTI增强
Delphi编译的文件体积增大了很多.很大一部分原因是因为Delphi2010默认提供了全信息的RTTI. 每一个数据类型都有全部运行时信息.例如可以在运行时获得结构体的成员以及成员类型等. 这个功能 ...
- 快速学习使用 Windows Azure 上的 SharePoint Server 2013
为了在当今的企业环境中占据一席之地,您需要能够迅速顺应变化和应对挑战.有时,需要及时调整您的SharePoint 基础结构以保持竞争优势. 基础结构即服务可通过随时使用.即付即用的解决方案应对这 ...
- Android Animation动画(很详细)
Android Animation Contents: Animations Tween Animations AnimationSet Interpolator Frame-By-Frame A ...
- [学习笔记]HTML5之canvas
虐了一下午的canvas 先撸了一个七巧板 <!doctype html> <html> <head> <meta charset="utf-8&q ...
- $timeout, $interval
$timeout, $interval layout: posttitle: Angular@1.4.3 中文 API 服务篇 $timeout & $intervaldesc: '$ti ...