Таким образом, я читал другой вопрос относительно цикла входа в систему, когда Вы имеете пользователя, входящего в систему, устанавливаете для возврата к URL, к которому у них не могло бы быть доступа после входа в систему (т.е. администраторская страница, и пользователь входит в систему с нормальной учетной записью).
Решение под WebForms, кажется, для использования UrlAuthorizationModule.CheckUrlAccessForPrincipal
метод. Однако это не работает на URL, идущие в Методы действия, защищенные с Авторизовать Атрибутом. Я полагал, что мог удаться, на какой метод URL указывал, и отразитесь по нему для решения моей проблемы - но я, может казаться, не разрабатываю, как я вытаскиваю эту информацию из таблицы маршрутизации.
Кто-либо когда-нибудь работал с этим, или имейте решение для этого? Если я могу просто овладеть маршрутной информацией от URL, я думаю, что мог бы разработать остальных, но если у кого-либо есть универсальное решение - т.е. некоторый скрытый метод, сродни, прежде чем упомянуто один для MVC, то это было бы полностью потрясающим также.
Я не спрашиваю, как проверить, есть ли у Пользователя доступ к указанной паре Контроллера/Действия. Я прежде всего должен разработать, как получить пару Контроллера/Действия от RouteTable, базирующегося от URL. Причина всей фоновой истории, то, в случае, если это там действительно существует эквивалент UrlAuthorizationModule.CheckUrlAccessForPrincipal
для MVC.
Какую проблему вы пытаетесь решить? Похоже, что вы идете по пути сложного решения, вместо которого можно было бы использовать простое решение.
Если у пользователя нет прав доступа к странице после входа, вы хотите, чтобы незарегистрированные пользователи переходили на одну страницу, а зарегистрированные пользователи - на другую?
Если это так, то у меня может возникнуть желание создать еще один контроллер для подобных сценариев и перенаправлять на него все места, где у пользователя нет доступа. Или, если вы используете свой собственный базовый контроллер, я бы поместил функциональность туда.
Затем контроллер может представить желаемое представление. Например, если пользователь, не вошедший в систему, пытается получить доступ к странице, он может быть перенаправлен на общую страницу ошибки. Если пользователь вошел в систему, он может быть перенаправлен на страницу неавторизованного пользователя.
Это очень похоже на ответ Роберта.
Вот основной скелет базового контроллера.
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
...
}
Это, вероятно, будет казаться спорным, но я проверить безопасность в начале каждого метода контроллера, внутри метода:
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);
}
}
Почему я не использовать [Авторизоваться]
атрибуты для этого заключается в том, что вы не можете передать идентификатор или любую другую идентифицирующую информацию атрибуту во время выполнения.
Я портировал и взломал этот код из 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;
}
Он мог использовать некоторое кеширование, но в моем случае это была преждевременная оптимизация.
Почему бы не отнести методы вашего контроллера к требованиям безопасности.
Я написал атрибут, чтобы сделать это следующим образом:
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 >>
}
}
}
В своем приложении я создал настраиваемый фильтр, производный от AuthorizeAttribute, поэтому любой несанкционированный доступ просто перейдет на страницу AccessDenied. Для ссылок я заменяю Html.ActionLink настраиваемым помощником Html.SecureLink. В этом вспомогательном расширении я проверяю доступ ролей этого пользователя к контроллеру / действию с базой данных. Если у него / нее есть разрешение, верните ссылку, в противном случае верните текст ссылки со специальными примечаниями (может быть изображение / раскраска / js)