0

我有基于声明的身份、身份验证和授权。

在我的 ClaimsAuthenticationManager 中,我转换用户联合令牌声明并将我的应用程序特定声明添加到 ClaimsPrincipal.Identity 的 ClaimsIdentity。

如果联合用户未在应用程序中本地注册,我会生成一个 "http://xml/claims/newUser"声明,其值为“true”。

现在,在我的应用程序中,如果用户在其声明集中有此特定声明,我需要重定向到“帐户”控制器中的“注册用户”操作。

这可能很简单,但我只是没有找到这种情况的合乎逻辑的解决方案。任何人都可以帮忙吗?

4

3 回答 3

3

我为我的问题找到的解决方案是用这个简单的 IFilterAttribute 解决的。

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple=true)]
public class RedirectOnClaimFilter : ActionFilterAttribute, IActionFilter
{

    public string ClaimType { get; set; }
    public string ClaimValue { get; set; }
    public string Controller { get; set; }
    public string Action { get; set; }

    #region IActionFilter Members

    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        ClaimsIdentity id = (ClaimsIdentity)filterContext.HttpContext.User.Identity;

        if (id.HasClaim(p => p.Type == ClaimType && string.Compare(p.Value, ClaimValue, true) == 0))
            filterContext.Result = RedirectToAction(Controller, Action);

        base.OnResultExecuting(filterContext);
    }

    public void OnActionExecuted(ActionExecutedContext filterContext)
    {
        //throw new NotImplementedException();
    }

    public void OnActionExecuting(ActionExecutingContext filterContext)
    {
        ClaimsIdentity id = (ClaimsIdentity)filterContext.HttpContext.User.Identity;

        if (id.HasClaim(p => p.Type == ClaimType && string.Compare(p.Value, ClaimValue, true) == 0))
            filterContext.Result = RedirectToAction(Controller, Action);


    }


    private ActionResult RedirectToAction(string Controller, string Action)
    {
        return new RedirectToRouteResult(new System.Web.Routing.RouteValueDictionary()
                                                {
                                                    {"Controller", Controller},
                                                    { "Action", Action}
                                                });
    }
    #endregion
}

然后我可以选择一个特定的声明来验证 Controller 调用,如下所示:

[RedirectOnClaimFilter(Action="WaitForApproval",
    Controller="Account",
    ClaimType = "http://solution/claims/pendinguser",
    ClaimValue="true")]
[RedirectOnClaimFilter(Action = "RegisterFederated",
    Controller = "Account",
    ClaimType = "http://solution/claims/newuser",
    ClaimValue = "true")]
[HandleError(ExceptionType = typeof(SecurityException), View = "Error")]
public class OrganizationController : BaseController
{
    public ActionResult OrganizationAction()
    {
         return View();
    }
}

它将检查委托人的声明集中的特定声明,如果找到,用户将被重定向到特定的控制器和操作。

于 2013-03-27T10:45:41.453 回答
1

Wifi 风格的方法是使用 ClaimsAuthorizationManager (感谢@leastprivilege文章):

try
{
    ClaimsPrincipalPermission.CheckAccess(“User”, “Newbie”);
}
catch (SecurityException ex)
{
    RedirectToAction("RegisterUser", "Account");
}

CheckAccess 称为 ClaimsAuthorizationManager.CheckAccess() ,您将在其中为这组操作、资源和主体实施具体的声明检查:

var principal = (ClaimsPrincipal)Thread.CurrentPrincipal;
if (principal != null)
{
     var newUserClaim =  principal.Claims.SingleOrDefault(c => string.Compare(c.Type, "http://xml/claims/newUser", StringComparison.InvariantCultureIgnoreCase) == 0)
}

更新最简单的方法是 Principal 的 HasClaim() 方法:

var principal = (ClaimsPrincipal)Thread.CurrentPrincipal;
If (principal.HasClaim("http://xml/claims/newUser", "true")) 
{
    RedirectToAction("RegisterUser", "Account");
}
于 2013-03-26T19:26:34.733 回答
0

您可以使用具有名为ClaimsAuthorize的属性的Thinktecture.IdentityModel,它将自动将用户重定向到登录页面。为了使用 Thinktecture.IdentityModel 您需要使用 Nuget 将包添加到您的 MVC 应用程序

Install-Package Thinktecture.IdentityModel

如果您已经在使用 ClaimsPrincipalPermission,那么您已经拥有 ClaimsAuthorizationManager 类来检查/授权应用程序中的声明,在这种情况下,您无需执行任何其他操作。现在您可以按如下方式装饰您的 MVC 操作方法:

[ClaimsAuthorize("View", "About")]
public ActionResult About(int id=0)
{

    return View();
}

如果当前登录的用户没有对“关于”资源的“查看”操作的声明,他/她将被重定向到登录页面。

于 2014-04-05T19:08:28.207 回答