6

无论如何,我都不是 SharePoint 专家,而且我一直很难找到这方面的正确信息。请帮忙!

我需要一种方法来通过调用来建立声明令牌,SPFederationAuthenticationModule.SetPrincipalAndWriteSessionToken以重新计算令牌上的声明,而无需注销当前用户。有没有办法做到这一点?

关于我为什么要问这个的一些背景:

我们在自定义 SharePoint 2010 Web 应用程序上为 authN/Z 使用自定义角色和成员资格提供程序。无需详细说明原因(这很复杂),角色提供者会根据用户在主应用程序数据库中的状态为用户创建动态生成的角色名称;这些角色代表用户的权限,并在 SharePoint 内部用于确定用户对应用程序中网站和网站集的访问权限。

在我们的应用程序中,用户可以通过多种方式更改其权限,通过角色提供程序有效地添加新角色,授予用户在应用程序内的额外访问权限。我们遇到的问题是,我们被迫在 SP2010 中使用的基于声明的身份验证会在登录时预先计算权限并将这些权限编码到会话令牌中——有效地迫使我们要求用户在他们之前注销并重新登录可以获得他们的新权限。这会产生各种可用性问题,因此是我的问题。

是否有某种方法可以在不注销用户的情况下以编程方式重新计算会话令牌?

还是我们找错了树?在我正常快乐的 ASP.NET 领域中,我会使用 Forms Auth,它会在每个请求而不是登录时计算授权。不幸的是,这似乎不是 SP2010 中的一个选项,我现在相当坚持使用 SharePoint。我们可以采取其他行动吗?

4

2 回答 2

5

好的,经过@Yahia 链接的大量研究,我在一篇博文中找到了我的问题的答案。像魅力一样工作。我将在下面给出一个概述,以防链接中断:

SessionAuthenticationModule用作 SharePoint 2010 身份验证框架的 Windows identify Foundation有一个漂亮的小事件,您可以将其挂钩,称为SessionSecurityTokenReceived,在每个请求开始时调用。通过挂钩此事件,我可以强制 SharePoint 请求更新授权,而无需强制用户重新输入凭据。

代码简单明了:

var sam = sender as SessionAuthenticationModule;
var logonWindow = SPSecurityTokenServiceManager.Local.LogonTokenCacheExpirationWindow;
var newValidTo = DateTime.UtcNow.Add(logonWindow);
e.SessionToken = sam.CreateSessionSecurityToken(
    e.SessionToken.ClaimsPrincipal,
    e.SessionToken.Context,
    e.SessionToken.ValidFrom,
    newValidTo,
    e.SessionToken.IsPersistent);
e.ReissueCookie = true;

我已经对其进行了测试,该方法确实有效,但也有缺点:

  1. 调用CreateSessionToken需要来自当前会话令牌的现有数据,看来我只能从事件中获取。这意味着这种方法只能在新请求的上下文中完成。由于每个请求都会触发该事件,并且我只想在某些情况下刷新身份验证,因此我不得不测试每个请求以提示刷新身份验证。最简单的方法是创建一个魔术 URL,例如您在事件处理程序中测试的“/refreshToken?redirectUrl={url}”。更新身份验证并且需要刷新令牌后,只需重定向到此 URL。
  2. 挂钩事件是有问题的——你不能静态地这样做,因为在构建静态构造函数时模块不存在。最终,您最好在自定义中执行此操作,HttpModule或者global.asax- 两者都需要更新无法通过.WSP文件部署(web.configglobal.asax文件)访问的资源,因此任何一种方法都会导致部署问题,至少在第一次部署时是这样。我选择了走这global.asax条路。

总之,一个令人满意的黑客。用最少的解决方法完成了工作。

于 2011-11-18T16:30:37.307 回答
2

我看到了几种可能性:

  • 尝试分别使用和SPRoleAssignment动态添加组/角色SPGroupCollectionSPUser

  • 使用RenewToken后跟 这是否真的符合您的要求取决于缓存的实现方式(即更新/验证是否反过来使缓存的声明无效)ValidateToken

  • 将密码保存在内存中,发出一个新令牌(使用相同的用户/密码,但新 ID!)然后调用ValidateToken
    我认为这是最简单的选择,但同时也是安全噩梦(即不好的做法)!

  • Authenticate每当您想检查索赔时致电
    这是否有效取决于您的自定义提供程序...如果有效,它将降低性能...

  • 实现您的自定义 SecurityToken(和提供者 ......)
    这将做你想要的,但意味着很多工作

其他有用的资源包括:

于 2011-11-16T08:24:46.390 回答