Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/323.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用Shibboleth进行asp.net MVC身份验证_C#_Asp.net Mvc_Shibboleth - Fatal编程技术网

C# 使用Shibboleth进行asp.net MVC身份验证

C# 使用Shibboleth进行asp.net MVC身份验证,c#,asp.net-mvc,shibboleth,C#,Asp.net Mvc,Shibboleth,Shibboleth是一种SSO身份验证,作为“插件”添加到IIS中。 用户登录后,会出现显示Shibboleth会话的标题: ShibSessionID ShibIdentityProvider eppn 附属 权利 非范围附属机构 ……更多 所以我可以从标题中提取用户名和角色。 到目前为止还不错 问题: 我如何实现一个读取头并设置用户授权状态的处理程序? 我们的想法是使用 [授权] 属性与方法 Roles.IsUserInRole。 所有这些都来自标题,没有数据库,没有用户管理 更新 根据@

Shibboleth是一种SSO身份验证,作为“插件”添加到IIS中。 用户登录后,会出现显示Shibboleth会话的标题: ShibSessionID ShibIdentityProvider eppn 附属 权利 非范围附属机构 ……更多

所以我可以从标题中提取用户名和角色。 到目前为止还不错

问题: 我如何实现一个读取头并设置用户授权状态的处理程序? 我们的想法是使用 [授权] 属性与方法 Roles.IsUserInRole。 所有这些都来自标题,没有数据库,没有用户管理

更新 根据@Pharylon的答案实施 在这个更新中没有什么新的东西,只是一个副本和过去的朋友的帮助。 当然,您必须根据Shibboleth设置调整属性和标题字段名

文件:ShibbolethPrincipal.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Security.Principal; //GenericPrincipal

namespace Shibboleth
{
    public class ShibbolethPrincipal : GenericPrincipal
    {
        public string username
        {
            get { return this.Identity.Name.Replace("@ksz.ch", ""); }
        }

        public string firstname
        {
            get { return HttpContext.Current.Request.Headers["givenName"]; }
        }

        public string lastname
        {
            get { return HttpContext.Current.Request.Headers["surname"]; }
        }

        public string phone
        {
            get { return HttpContext.Current.Request.Headers["telephoneNumber"]; }
        }

        public string mobile
        {
            get { return HttpContext.Current.Request.Headers["mobile"]; }
        }

        public string entitlement
        {
            get { return HttpContext.Current.Request.Headers["eduzgEntitlement"]; }            
        }

        public string homeOrganization
        {
            get { return HttpContext.Current.Request.Headers["homeOrganization"]; }            
        }

        public DateTime birthday
        {
            get
            {
                DateTime dtHappy = DateTime.MinValue;
                try
                {
                    dtHappy = DateTime.Parse(HttpContext.Current.Request.Headers["dateOfBirth"]);
                }
                finally
                {                    
                    
                }

                return dtHappy;
            }
            set {}
        }
        
        public ShibbolethPrincipal()
            : base(new GenericIdentity(GetUserIdentityFromHeaders()), GetRolesFromHeader())
        {
        }

        public static string GetUserIdentityFromHeaders()
        {            
            //return HttpContext.Current.Request.Headers["eppn"];            
            return HttpContext.Current.Request.Headers["principalName"];                        
        }

        public static string[] GetRolesFromHeader()
        {
            string[] roles = null;
            //string rolesheader = HttpContext.Current.Request.Headers["affiliation"];
            string rolesheader = HttpContext.Current.Request.Headers["eduzgEntitlement"];
            if (rolesheader != null)
            {
                roles = rolesheader.Split(';');
            }
            return roles; 
        }
    }
}
文件:ShibbolethController.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace Shibboleth
{
    public class ShibbolethController : Controller
    {
        protected new ShibbolethPrincipal User
        {
            get
            {
                return (base.User as ShibbolethPrincipal) ?? null; //CustomPrincipal.GetUnauthorizedPrincipal();
            }
        }
    }
}
文件:Global.asax

void Application_PostAuthenticateRequest(object sender, EventArgs e)
        {
            var ctx = HttpContext.Current;

            var principal = new ShibbolethPrincipal();
            HttpContext.Current.User = principal;            
        }
举例说明:

 namespace itservices.Controllers
    {
        [Authorize] //examples : [Authorize(Roles="Administrators")], [Authorize(Users="Alice,Bob")]
        public class PasswordMailController : ShibbolethController
        {

  


您需要在Global.asax.cs中创建一个具有以下签名的方法

protected void Application_PostAuthenticateRequest()
{
    //Your code here.
}
这将在几乎完成任何其他操作之前自动调用(如果该方法存在,MVC将调用它,您不必在任何地方“打开它”),这就是您需要设置主体的地方。例如,假设您有一个名为
RolesHeader
的头,该头具有逗号分隔的角色值,另一个名为
UserId
的头具有(duh)用户ID

在没有任何错误处理的情况下,您的代码可能看起来像:

protected void Application_PostAuthenticateRequest()
{
    var rolesheader = Context.Request.Headers["RolesHeader"];
    var userId = Context.Request.Headers["UserId"];
    var roles = rolesheader.Split(',');
    var principal = new GenericPrincipal(new GenericIdentity(userId), roles);
    Context.User = principal;
}
这是
[Authorize]
属性使用的主体/标识,因此在请求生命周期开始时将其设置在此处意味着
[Authorize]
属性将正常工作

其余部分是可选的,但我建议:

我喜欢创建自己的自定义类来实现IPrincipal和IIdentity,而不是使用GenericPrincipal和GenericEntity,这样我就可以在其中填充更多的用户信息。然后,我的自定义主体和标识对象具有更丰富的信息,如分支机构编号或电子邮件地址等

然后,我创建一个名为
BaseController
的控制器,它具有以下特性

protected new CustomPrincipal User
{
    get
    {
        return (base.User as CustomPrincipal) ?? CustomPrincipal.GetUnauthorizedPrincipal();
    }
}
这允许我访问所有丰富的自定义主体数据,而不仅仅是IPrincipal中定义的数据。然后,我的所有实际控制器都从
BaseController
继承,而不是直接从
Controller
继承


显然,当使用这样的自定义主体时,在应用程序\u PostAuthenticateRequest()方法中,您将Context.User设置为您的
CustomPrincipal
,而不是
GenericPrincipal

您是否尝试创建操作筛选器并在OnActionExecuting方法中执行此处理?我认为最好在处理请求开始时设置主体/标识,以便正常的授权筛选器和方法能够工作。@RazvanDumitru-ActionFilters在授权筛选器之后执行,如果我能提供帮助,它们将毫无用处。不过,我建议ShibbolethController的用户永远不要返回空对象。您不希望User.Identity.IsAuthenticated引发异常-这应该是检查用户是否有效的可靠方法。此外,您应该在实例化时设置主体的值(我喜欢将其设置为不可变对象)。否则,如果让单元测试不断地调用HttpContext.Current.Hello Pharylon,那么单元测试就会很糟糕。朱普,这是有道理的。我也在换未经授权的主治医生。谢谢你!这比我想象的要容易得多。我担心我必须实现ExtendeMembershibProvider和RoleProvider。非常感谢你
protected new CustomPrincipal User
{
    get
    {
        return (base.User as CustomPrincipal) ?? CustomPrincipal.GetUnauthorizedPrincipal();
    }
}