Переопределение AuthorizeCore в пользовательском атрибуте Authorize приводит к ошибке "no found method found override"
Я пытаюсь создать пользовательский атрибут AuthorizeAttribute, поэтому в моем основном проекте (библиотеке классов) у меня есть этот код:
using System;
using System.Web;
using System.Web.Mvc;
using IVC.Core.Web;
using System.Linq;
namespace IVC.Core.Attributes
{
public class TimeShareAuthorizeAttribute : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
if(!httpContext.Request.IsAuthenticated)
return false;
var rolesProvider = System.Web.Security.Roles.Providers["TimeShareRoleProvider"];
string[] roles = rolesProvider.GetRolesForUser(httpContext.User.Identity.Name);
if(roles.Contains(Website.Roles.RegisteredClient, StringComparer.OrdinalIgnoreCase))
{
return true;
}
return false;
}
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
filterContext.Result = new RedirectResult("/TimeShare/Account/LogOn");
base.HandleUnauthorizedRequest(filterContext);
}
}
}
Когда я пытаюсь построить вещь, я получаю эту ошибку:
Ошибка 2 'IVC.Core.Attributes.TimeShareAuthorizeAttribute.AuthorizeCore(System.Web.HttpContextBase)': не найдено подходящего метода для переопределения...
Я что-то упустил? Я искал все, но каждый сайт, который я могу найти, просто говорит мне, что я делаю именно то, что я здесь сделал. Я использую mvc2 btw.
- Отредактировано для добавления: если я переведу класс в проект mvc в том же решении, ошибки компилятора не будут.
Ответы
Ответ 1
Да, я тоже поиграл с этим и понял это из обозревателя объектов. Это, конечно, НЕ ясно из документов MSDN, если вы не прокрутите весь путь до комментариев пользователя в классе HttpContextBase. И, конечно, множество примеров в Интернете, но никто никогда не показывает полный файл класса!:)
Попробуйте добавить ссылку на System.Web.Abstractions к вашему проекту.
UPDATE: только что замеченный из MSDN, что под v3.5, он находится под System.Web.Abstractions, но под v4, в System.Web.
Ответ 2
Вот авторизацияAttribute.cs
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* This software is subject to the Microsoft Public License (Ms-PL).
* A copy of the license can be found in the license.htm file included
* in this distribution.
*
* You must not remove this notice, or any other, from this software.
*
* ***************************************************************************/
namespace System.Web.Mvc {
using System;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Security.Principal;
using System.Web;
[SuppressMessage("Microsoft.Performance", "CA1813:AvoidUnsealedAttributes",
Justification = "Unsealed so that subclassed types can set properties in the default constructor or override our behavior.")]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class AuthorizeAttribute : FilterAttribute, IAuthorizationFilter {
private string _roles;
private string[] _rolesSplit = new string[0];
private string _users;
private string[] _usersSplit = new string[0];
public string Roles {
get {
return _roles ?? String.Empty;
}
set {
_roles = value;
_rolesSplit = SplitString(value);
}
}
public string Users {
get {
return _users ?? String.Empty;
}
set {
_users = value;
_usersSplit = SplitString(value);
}
}
// This method must be thread-safe since it is called by the thread-safe OnCacheAuthorization() method.
protected virtual bool AuthorizeCore(HttpContextBase httpContext) {
if (httpContext == null) {
throw new ArgumentNullException("httpContext");
}
IPrincipal user = httpContext.User;
if (!user.Identity.IsAuthenticated) {
return false;
}
if (_usersSplit.Length > 0 && !_usersSplit.Contains(user.Identity.Name, StringComparer.OrdinalIgnoreCase)) {
return false;
}
if (_rolesSplit.Length > 0 && !_rolesSplit.Any(user.IsInRole)) {
return false;
}
return true;
}
private void CacheValidateHandler(HttpContext context, object data, ref HttpValidationStatus validationStatus) {
validationStatus = OnCacheAuthorization(new HttpContextWrapper(context));
}
public virtual void OnAuthorization(AuthorizationContext filterContext) {
if (filterContext == null) {
throw new ArgumentNullException("filterContext");
}
if (AuthorizeCore(filterContext.HttpContext)) {
// ** IMPORTANT **
// Since we're performing authorization at the action level, the authorization code runs
// after the output caching module. In the worst case this could allow an authorized user
// to cause the page to be cached, then an unauthorized user would later be served the
// cached page. We work around this by telling proxies not to cache the sensitive page,
// then we hook our custom authorization code into the caching mechanism so that we have
// the final say on whether a page should be served from the cache.
HttpCachePolicyBase cachePolicy = filterContext.HttpContext.Response.Cache;
cachePolicy.SetProxyMaxAge(new TimeSpan(0));
cachePolicy.AddValidationCallback(CacheValidateHandler, null /* data */);
}
else {
// auth failed, redirect to login page
filterContext.Result = new HttpUnauthorizedResult();
}
}
// This method must be thread-safe since it is called by the caching module.
protected virtual HttpValidationStatus OnCacheAuthorization(HttpContextBase httpContext) {
if (httpContext == null) {
throw new ArgumentNullException("httpContext");
}
bool isAuthorized = AuthorizeCore(httpContext);
return (isAuthorized) ? HttpValidationStatus.Valid : HttpValidationStatus.IgnoreThisRequest;
}
internal static string[] SplitString(string original) {
if (String.IsNullOrEmpty(original)) {
return new string[0];
}
var split = from piece in original.Split(',')
let trimmed = piece.Trim()
where !String.IsNullOrEmpty(trimmed)
select trimmed;
return split.ToArray();
}
}
}
Ответ 3
Кроме того, поскольку я видел это раньше, будьте осторожны, позволяя автозагрузке Visual Studio автоматически добавлять для вас. Если вы не обращаете внимания, вы можете добавить System.Web.Http вместо System.Web.Mvc.
Ответ 4
Когда я скопировал свои старые коды в свой новый проект, возникла одна и та же проблема.
Оказалось, что есть 2 AuthrizeAttributes. Один находится в System.Web.Mvc, а другой - в System.Web.Http.
В Mvc есть AuthrizeCore, а Http - нет.
Вам может потребоваться добавить ссылку на System.Web.Mvc для доступа к правильному.
Ответ 5
У меня тоже была эта ошибка. Оказалось, что Visual Studio добавила в мой ActionFilter по умолчанию:
с использованием System.Web.Http;
Даже когда я добавил System.Web.Mvc, я все еще получил ошибку. Комментирование System.Web.Http и просто использование System.Web.Mvc, похоже, решают проблему для меня.
Надеясь, что это может помочь кому-то!
Ответ 6
В соответствии с fw v4.5 он теперь находится под System.Web.Mvc, видимо.
Ответ 7
Используйте пространство имен System.Web.Mvc
.
Пример кода:
using System.Web.Mvc;
public class CustomAuthorize : AuthorizeAttribute
{
protected override bool AuthorizeCore(System.Web.HttpContextBase httpContext)
{
var service = new AuthService();
return service.GetCurrentUser() != null;
}
public override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
}
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
base.HandleUnauthorizedRequest(filterContext);
}
}