MVC ASP.NET, как определить, может ли пользователь получить доступ к URL?

Таким образом, я читал другой вопрос относительно цикла входа в систему, когда Вы имеете пользователя, входящего в систему, устанавливаете для возврата к URL, к которому у них не могло бы быть доступа после входа в систему (т.е. администраторская страница, и пользователь входит в систему с нормальной учетной записью).

Решение под WebForms, кажется, для использования UrlAuthorizationModule.CheckUrlAccessForPrincipal метод. Однако это не работает на URL, идущие в Методы действия, защищенные с Авторизовать Атрибутом. Я полагал, что мог удаться, на какой метод URL указывал, и отразитесь по нему для решения моей проблемы - но я, может казаться, не разрабатываю, как я вытаскиваю эту информацию из таблицы маршрутизации.

Кто-либо когда-нибудь работал с этим, или имейте решение для этого? Если я могу просто овладеть маршрутной информацией от URL, я думаю, что мог бы разработать остальных, но если у кого-либо есть универсальное решение - т.е. некоторый скрытый метод, сродни, прежде чем упомянуто один для MVC, то это было бы полностью потрясающим также.

Я не спрашиваю, как проверить, есть ли у Пользователя доступ к указанной паре Контроллера/Действия. Я прежде всего должен разработать, как получить пару Контроллера/Действия от RouteTable, базирующегося от URL. Причина всей фоновой истории, то, в случае, если это там действительно существует эквивалент UrlAuthorizationModule.CheckUrlAccessForPrincipal для MVC.

16
задан kastermester 4 February 2010 в 13:37
поделиться

5 ответов

Какую проблему вы пытаетесь решить? Похоже, что вы идете по пути сложного решения, вместо которого можно было бы использовать простое решение.

Если у пользователя нет прав доступа к странице после входа, вы хотите, чтобы незарегистрированные пользователи переходили на одну страницу, а зарегистрированные пользователи - на другую?

Если это так, то у меня может возникнуть желание создать еще один контроллер для подобных сценариев и перенаправлять на него все места, где у пользователя нет доступа. Или, если вы используете свой собственный базовый контроллер, я бы поместил функциональность туда.

Затем контроллер может представить желаемое представление. Например, если пользователь, не вошедший в систему, пытается получить доступ к странице, он может быть перенаправлен на общую страницу ошибки. Если пользователь вошел в систему, он может быть перенаправлен на страницу неавторизованного пользователя.

Это очень похоже на ответ Роберта.

Вот основной скелет базового контроллера.

public BaseController: Controller
{

... // Some code

    public ActionResult DisplayErrorPage()
    {
        // Assumes you have a User object with a IsLoggedIn property
        if (User.IsLoggedIn())    
            return View("NotAuthorized");

        // Redirect user to login page
        return RedirectToAction("Logon", "Account");
    }

}

Затем в, скажем, AdminController (который наследуется от BaseController) действие

public ActionResult HighlyRestrictedAction()
{
    // Assumes there is a User object with a HasAccess property
    if (User.HasAccess("HighlyRestrictedAction") == false)
        return DisplayErrorPage();

    // At this point the user is logged in and has permissions
    ...
}
1
ответ дан 30 November 2019 в 22:31
поделиться

Это, вероятно, будет казаться спорным, но я проверить безопасность в начале каждого метода контроллера, внутри метода:

public class ProductController : Controller
{
    IProductRepository _repository

    public ActionResult Details(int id)
    {
        if(!_repository.UserHasAccess(id))
            return View("NotAuthorized");

        var item = _repository.GetProduct(id);

        if (item == null)
            return View("NotFound");

        return View(item);
    }
}

Почему я не использовать [Авторизоваться] атрибуты для этого заключается в том, что вы не можете передать идентификатор или любую другую идентифицирующую информацию атрибуту во время выполнения.

1
ответ дан 30 November 2019 в 22:31
поделиться

Я портировал и взломал этот код из MvcSitemap:

public static class SecurityTrimmingExtensions 
{

    /// <summary>
    /// Returns true if a specific controller action exists and
    /// the user has the ability to access it.
    /// </summary>
    /// <param name="htmlHelper"></param>
    /// <param name="actionName"></param>
    /// <param name="controllerName"></param>
    /// <returns></returns>
    public static bool HasActionPermission( this HtmlHelper htmlHelper, string actionName, string controllerName )
    {
        //if the controller name is empty the ASP.NET convention is:
        //"we are linking to a different controller
        ControllerBase controllerToLinkTo = string.IsNullOrEmpty(controllerName) 
                                                ? htmlHelper.ViewContext.Controller
                                                : GetControllerByName(htmlHelper, controllerName);

        var controllerContext = new ControllerContext(htmlHelper.ViewContext.RequestContext, controllerToLinkTo);

        var controllerDescriptor = new ReflectedControllerDescriptor(controllerToLinkTo.GetType());

        var actionDescriptor = controllerDescriptor.FindAction(controllerContext, actionName);

        return ActionIsAuthorized(controllerContext, actionDescriptor);
    }


    private static bool ActionIsAuthorized(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
    {
        if (actionDescriptor == null)
            return false; // action does not exist so say yes - should we authorise this?!

        AuthorizationContext authContext = new AuthorizationContext(controllerContext);

        // run each auth filter until on fails
        // performance could be improved by some caching
        foreach (IAuthorizationFilter authFilter in actionDescriptor.GetFilters().AuthorizationFilters)
        {
            authFilter.OnAuthorization(authContext);

            if (authContext.Result != null)
                return false;
        }

        return true;
    }

    private static ControllerBase GetControllerByName(HtmlHelper helper, string controllerName)
    {
        // Instantiate the controller and call Execute
        IControllerFactory factory = ControllerBuilder.Current.GetControllerFactory();

        IController controller = factory.CreateController(helper.ViewContext.RequestContext, controllerName);

        if (controller == null)
        {
            throw new InvalidOperationException(

                String.Format(
                    CultureInfo.CurrentUICulture,
                    "Controller factory {0} controller {1} returned null",
                    factory.GetType(),
                    controllerName));

        }

        return (ControllerBase)controller;
    }

Он мог использовать некоторое кеширование, но в моем случае это была преждевременная оптимизация.

6
ответ дан 30 November 2019 в 22:31
поделиться

Почему бы не отнести методы вашего контроллера к требованиям безопасности.

Я написал атрибут, чтобы сделать это следующим образом:

  public class RequiresRoleAttribute : ActionFilterAttribute
        {
            public string Role { get; set; }

            public override void OnActionExecuting(ActionExecutingContext filterContext)
            {
                if (string.IsNullOrEmpty(Role))
                {
                    throw new InvalidOperationException("No role specified.");
                }


                if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
                {
                    filterContext.HttpContext.Response.Redirect(loginUrl, true);
                }
                else
                {
                    bool isAuthorised = filterContext.HttpContext.User.IsInRole(this.Role);

                    << Complete Logic Here >>



                }  
            }      
        }
0
ответ дан 30 November 2019 в 22:31
поделиться

В своем приложении я создал настраиваемый фильтр, производный от AuthorizeAttribute, поэтому любой несанкционированный доступ просто перейдет на страницу AccessDenied. Для ссылок я заменяю Html.ActionLink настраиваемым помощником Html.SecureLink. В этом вспомогательном расширении я проверяю доступ ролей этого пользователя к контроллеру / действию с базой данных. Если у него / нее есть разрешение, верните ссылку, в противном случае верните текст ссылки со специальными примечаниями (может быть изображение / раскраска / js)

1
ответ дан 30 November 2019 в 22:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: