使用Shibboleth的asp.net MVC身份验证 [英] asp.net MVC authentication with Shibboleth

查看:93
本文介绍了使用Shibboleth的asp.net MVC身份验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Shibboleth是作为插件"添加到IIS的SSO身份验证. 用户完成登录后,将出现显示Shibboleth会话的标题: ShibSessionID ShibIdentityProvider eppn 联系 权利 不受限制的隶属关系 ...更多

Shibboleth is a SSO Authentication that is added to IIS as a "plugin". After a user has done a Login there are Headers showing the Shibboleth Session: ShibSessionID ShibIdentityProvider eppn affiliation entitlement unscopedaffiliation ...more

所以我可以从标题中提取用户名和角色. 到目前为止一切顺利.

So i can extract username and roles from the Headers. so far so fine.

问题: 如何实现不读取标头并设置用户已授权状态的处理程序? 想法是使用 [授权] 属性和方法 Roles.IsUserInRole. 全部来自标题,没有数据库,没有用户管理.

Question: How can I implement a handler that does read the headers and set the status that a user is authorized? Idea is to use the [Authorize] Attribute and the Method Roles.IsUserInRole. All from the Headers, no Database, no User Management.

在此更新中,没有新内容,仅是复制和粘贴朋友的帮助. 当然,您必须根据Shibboleth设置来调整属性和标头字段名.

In this Update there is nothing new, just a help for the copy&past friends. Of course you have to adjust the properties and Header fieldnames according to your Shibboleth Setup.

文件:ShibbolethPrincipal.cs

File: 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

File: 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

File: 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
        {

  


    if(User.IsInRole("staff"))
    {

推荐答案

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

You'll want to create a method in Global.asax.cs that has the following signature

protected void Application_PostAuthenticateRequest()
{
    //Your code here.
}

在几乎完成任何其他操作之前,它将自动被调用(如果存在,MVC会调用此方法,您不必在任何地方打开"该方法),这是设置Principal的地方.例如,假设您有一个名为RolesHeader的标头,该标头具有逗号分隔的角色值,另一个标为UserId的标头具有(duh)用户ID.

This will be called automatically before almost anything else is done (MVC will call this method if it exists, you don't have to "turn it on" anywhere), and this is where you need to set the Principal. For instance, let's assume you have a header called RolesHeader that has a comma separated value of roles and another header called UserId that has (duh) the user ID.

您的代码没有任何错误处理,可能类似于:

Your code, without any error handling, might look something like:

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]属性将正常工作.

It's the Principal/Identity that the [Authorize] attribute uses, so setting it here at the beginning of the request lifecycle means the [Authorize] attribute will work correctly.

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

我喜欢创建自己的实现IPrincipal和IIdentity的自定义类,而不是使用GenericPrincipal和GenericIdentity,因此可以在其中填充更多用户信息.这样,我自定义的Principal和Identity对象将获得更多信息,例如分支机构号或电子邮件地址或其他任何信息.

I like to create my own custom classes that implement IPrincipal and IIdentity instead of using the GenericPrincipal and GenericIdentity, so I can stuff more user information in it. My custom Principal and Identity objects then have much more rich information, such as branch numbers or email addresses or whatever.

然后,我创建一个名为BaseController的控制器,该控制器具有以下内容

Then, I create a Controller called BaseController that has the following

protected new CustomPrincipal User
{
    get
    {
        return (base.User as CustomPrincipal) ?? CustomPrincipal.GetUnauthorizedPrincipal();
    }
}

这使我可以访问所有丰富的自定义主体数据,而不仅仅是IPrincipal中定义的数据.然后,我所有的真实控制器都从BaseController继承,而不是直接从Controller继承.

This allows me to access all my rich, custom Principal data instead of just what's defined in IPrincipal. All of my real controllers then inherit from BaseController instead of directly from Controller.

很明显,当使用这样的自定义主体时,可以在Application_PostAuthenticateRequest()方法中将Context.User设置为您的CustomPrincipal而不是GenericPrincipal.

Obviously, when using a custom Principal like this, in the Application_PostAuthenticateRequest() method, you'd set the Context.User to be your CustomPrincipal instead of a GenericPrincipal.

这篇关于使用Shibboleth的asp.net MVC身份验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆