首页 文章

ClaimsPrincipal没有得到妥善保存

提问于
浏览
1

我有一个ASP.NET MVC 4应用程序,我正在尝试实现基于声明的身份验证和授权 . 我们有一个SSO代理,在标头中插入有关用户的某些信息(例如用户名) . 我已经实现了自己的ClaimsAuthenticationManager,我想要做的是从头文件中获取用户名,创建一个包含UserName声明的ClaimsPrinsipal,将其传递给我的ClaimsAuthenticationManager,它将命中数据库以确定用户应该拥有的角色,并使用角色声明填充主体 . 然后我想在用户会话的其余部分使用转换后的声明 .

到目前为止我所拥有的:

Web.config:

<配置>
...
在<system.web>
...

<authentication mode =“Forms”> <forms loginUrl =“〜/ Account / Authorize”timeout =“20”/> </认证> </system.web> </配置>

MyClaimsTransformer.cs

public class MyClaimsTransformer : ClaimsAuthenticationManager
{
    private readonly IAuthenticationUow _authenticationUow;
    private readonly IWebServiceUrls _webServiceUrls;

    public MyClaimsTransformer(IAuthenticationUow authenticationUow, IWebServiceUrls webServiceUrls)
    {
        _authenticationUow = authenticationUow;
        _webServiceUrls = webServiceUrls;
    }

    public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal)
    {
        if (incomingPrincipal == null || incomingPrincipal.Identity == null || !incomingPrincipal.Identity.IsAuthenticated)
            throw new SecurityException("No claims principal or not authenticated");

        var userName = incomingPrincipal.Identity.Name;

        if (string.IsNullOrWhiteSpace(userName))
            throw new SecurityException("No user name found");

        // Add role claims

        return incomingPrincipal;
    }
}

Global.asax.cs

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        WebApiConfig.Register(GlobalConfiguration.Configuration);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);

        FederatedAuthentication.FederationConfigurationCreated += FederatedAuthentication_FederationConfigurationCreated;
    }

    private void FederatedAuthentication_FederationConfigurationCreated(object sender, System.IdentityModel.Services.Configuration.FederationConfigurationCreatedEventArgs e)
    {
        WebServiceUrls serviceUrls = new WebServiceUrls();
        AppProperties appProperties = new AppProperties();
        serviceUrls.UserNameWebServiceUrl = appProperties.UserNameWebServiceUrl;
        serviceUrls.PointOfContactWebServiceUrl = appProperties.PointOfContactWebServiceUrl;
        e.FederationConfiguration.IdentityConfiguration.ClaimsAuthenticationManager =
            ObjectFactory.With<IWebServiceUrls>(serviceUrls).GetInstance<MyClaimsTransformer>();
    }
}

AccountController.cs

[Authorize]
public class AccountController : BaseController
{
    [AllowAnonymous]
    public ActionResult Authorize(string returnUrl)
    {
        string userId = Request.Headers["userid"];

        if (Url.IsLocalUrl(returnUrl))
        {
            var claims = new List<Claim>
            {
                new Claim(ClaimTypes.Name, userId)
            };

            var id = new ClaimsIdentity(claims, "Custom", ClaimTypes.Name, ClaimTypes.Role);
            var principal = new ClaimsPrincipal(id);

            // call out to registered ClaimsAuthenticationManager
            var claimsAuthManager = FederatedAuthentication.FederationConfiguration.IdentityConfiguration.ClaimsAuthenticationManager;

            // set the transformed principal
            var url = Request.Url;
            if (url != null)
            {
                var newPrincipal = claimsAuthManager.Authenticate(url.AbsolutePath, principal);
                SetSessionCookie(newPrincipal);
                Thread.CurrentPrincipal = newPrincipal;
            }

            return Redirect(returnUrl);
        }
        throw new InvalidDataException("BAD URL");
    }

    private void SetSessionCookie(ClaimsPrincipal incomingPrincipal)
    {
        SessionSecurityToken token = new SessionSecurityToken(incomingPrincipal);
        FederatedAuthentication.SessionAuthenticationModule.WriteSessionTokenToCookie(token);
    }
}

此代码运行正常,当执行 Thread.CurrentPrincipal = newPrincipal; 行时,所有正确的声明都在主体中 . 但是,当我使用我的自定义ClaimsAuthorizationManager检查声明时,它们都不存在(同样,Principal不再经过身份验证) . 它只是重新指向AccountController再次进行身份验证 .

我错过了什么?

1 回答

  • 0

    在Authenticate覆盖中,您应该将incomingPrincipal路由到基本的ClaimsAuthenticationManager:

    return base.Authenticate(resourceName, incomingPrincipal);
    

相关问题