简体   繁体   English

从Active Directory进行身份验证,但在MVC中从SQL数据库授权角色

[英]Authenticate from Active Directory but Authorize Roles from SQL Database in MVC

I am new to MVC. 我是MVC的新手。 I searched and found no solution that fits for my requirements. 我搜索并找不到符合我要求的解决方案。

I am developing a web portal for our team's internal use which uses Windows AD authentication for login. 我正在为我们团队的内部使用开发一个Web门户,它使用Windows AD身份验证进行登录。 However, for role based access I have created a local database which can return the Role details for the user. 但是,对于基于角色的访问,我创建了一个本地数据库,可以返回用户的角色详细信息。 I have created a custom Authorization filter that allows me to handle authorization based on the user's role. 我创建了一个自定义授权过滤器,允许我根据用户的角色处理授权。 This filter is querying details from the DB however the issue with this approach is, it will try to get details from DB for every request to the controller which makes it expensive. 此过滤器正在从DB查询详细信息,但是这种方法的问题是,它将尝试从DB获取有关控制器的每个请求的详细信息,这使得它变得昂贵。

How can I save the user details fetched from the DB in a Token such that I don't have to query DB for every request and use the Token values inside the Authorization filter. 如何在令牌中保存从数据库中提取的用户详细信息,这样我就不必为每个请求查询数据库并使用授权过滤器内的令牌值。 Also, I can use the values retrieved for the user from the database, anywhere else in the app. 此外,我可以在应用程序的任何其他位置使用从数据库中为用户检索的值。 (There are some other details for the user we have in the Database). (我们在数据库中有用户的其他一些细节)。

If someone can suggest a better way to achieve this, please help. 如果有人可以建议更好的方法来实现这一目标,请帮助。

Here is the code that I am currently using inside Authorization filter: 以下是我目前在授权过滤器中使用的代码:

public class AuthorizeRole : AuthorizeAttribute
{
    private bool _authenticated;
    private bool _authorized;

    public string InRoles { get; set; }

    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        base.HandleUnauthorizedRequest(filterContext);

        if (_authenticated && !_authorized)
        {
            filterContext.Result = new RedirectResult("/account/error");
        }
    }

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        _authenticated = base.AuthorizeCore(httpContext);

        if (_authenticated)
        {
            if (string.IsNullOrEmpty(InRoles))
            {
                _authorized = true;
                return _authorized;
            }

            if (!string.IsNullOrEmpty(httpContext.User.Identity.Name))
            {
                string NTID = httpContext.User.Identity.Name.Split('\\')[1];
                var roles = InRoles.Split(',');

                using (Models.UserAuthEntities userAuthEntities = new Models.UserAuthEntities())
                {
                    try
                    {
                        ObjectResult<Models.Validate_User_Login_Result> userResults = userAuthEntities.Validate_User_Login(NTID);
                        var user = userResults.FirstOrDefault(all => all.NTID == NTID);

                        if (user == null)
                        {
                            _authorized = false;
                            return _authorized;
                        }
                        else
                        {
                            if (roles.Contains(user.Role))
                            {
                                return _authorized;
                            }
                        }
                    }
                    catch (Exception)
                    {
                        _authorized = false;
                        return _authorized;
                    }
                }
            }
            else
            {
                _authorized = false;
                return _authorized;
            }
        }

        _authorized = false;
        return _authorized;
    }
}

Please suggest at which section to use the code you will be suggesting (like, inside controller, inside filter or somewhere else.) 请建议在哪个部分使用您建议的代码(例如,内部控制器,内部过滤器或其他地方。)

I found this solution at: this site but there it is used for AD groups. 我在以下网站找到了这个解决方案,但它用于AD组。

First off, you might want to look at using AD Security Groups to manage access. 首先,您可能希望使用AD安全组来管理访问。 That way OPS can continue to maintain access in a familiar time-tested platform and you dont have to write your own security definition interface. 这样,OPS可以继续在熟悉的经过时间考验的平台上维护访问,而您不必编写自己的安全定义界面。

As for the MVC security persistence All you have to do is add a manual log in to perform your above logic and then you use the built-in Membership Provider (for whatever version of MVC you are using) to log the user in. MVC will handle maintaining the logged in state and tokenising for you and you can specify things like timeout in the web.config (or settings.json in Core). 至于MVC安全持久性你要做的就是添加一个手动登录来执行上面的逻辑,然后你使用内置的Membership Provider(对于你正在使用的任何版本的MVC)来记录用户.MVC将处理维护登录状态并为您进行标记,您可以在web.config(或Core中的settings.json)中指定诸如超时之类的内容。

Sorry i dont have any sample code at hand for illustration. 对不起,我手边没有任何示例代码可供说明。

I have checked the cookie in override version of method AuthorizeCore it is working now: 我已经在方法AuthorizeCore覆盖版本中检查了它现在正在运行的cookie:

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        string cookieName = FormsAuthentication.FormsCookieName;
        HttpCookie authCookie = httpContext.Request.Cookies[cookieName];
        _authenticated = base.AuthorizeCore(httpContext);
        string authToken = httpContext.Request.Headers["Auth-Token"];

        if (_authenticated)
        {
            if (authCookie == null)
            {
                if (string.IsNullOrEmpty(InRoles))
                {
                    _authorized = true;
                    return _authorized;
                }

                if (!string.IsNullOrEmpty(httpContext.User.Identity.Name))
                {
                    string NTID = httpContext.User.Identity.Name.Split('\\')[1];
                    var roles = InRoles.Split(',');

                    using (Models.UserAuthEntities userAuthEntities = new Models.UserAuthEntities())
                    {
                        try
                        {
                            ObjectResult<Models.Validate_User_Login_Result> userResults = userAuthEntities.Validate_User_Login(NTID);
                            var user = userResults.FirstOrDefault(all => all.NTID == NTID);

                            if (user == null)
                            {
                                _authorized = false;
                                return _authorized;
                            }
                            else
                            {
                                if (roles.Contains(user.Role))
                                {
                                    _authorized = true;
                                    return _authorized;
                                }
                            }
                        }
                        catch (Exception)
                        {
                            _authorized = false;
                            return _authorized;
                        }
                    }
                }
                else
                {
                    _authorized = false;
                    return _authorized;
                }
            }
        }

        _authorized = false;
        return _authorized;
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM