Улучшение производительности и расширяемости моего модуля пользовательской авторизации
У меня есть требование авторизации, чтобы мои роли безопасности основывались на методах действий, чего нельзя достичь с помощью стандартной авторизации asp.net mvc. поэтому я создал следующий фильтр действий для реализации моих пользовательских требований авторизации:-
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class CheckUserPermissionsAttribute : ActionFilterAttribute
{
Repository repository = new Repository();
public string Model { get; set; }
public string Action { get; set; }
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// var user = User.Identity.Name; // or get from DB
string ADusername = filterContext.HttpContext.User.Identity.Name.Substring(filterContext.HttpContext.User.Identity.Name.IndexOf("\\") + 1);
if (!repository.can(ADusername,Model,Action)) // implement this method based on your tables and logic
{
filterContext.Result = new HttpUnauthorizedResult("You cannot access this page");
}
base.OnActionExecuting(filterContext);
}
}
который вызывает следующий метод репозитория:
public bool can(string user, string Model, string Action)
{
bool result;
bool result2;
int size = tms.PermisionLevels.Where(a5 => a5.Name == Action).SingleOrDefault().PermisionSize;
var securityrole = tms.SecurityroleTypePermisions.Where(a => a.PermisionLevel.PermisionSize >= size && a.TechnologyType.Name == Model).Select(a => a.SecurityRole).Include(w=>w.Groups).Include(w2=>w2.SecurityRoleUsers).ToList();//.Any(a=> a.SecurityRoleUsers.Where(a2=>a2.UserName.ToLower() == user.ToLower()));
foreach (var item in securityrole)
{
result = item.SecurityRoleUsers.Any(a => a.UserName.ToLower() == user.ToLower());
var no = item.Groups.Select(a=>a.TMSUserGroups.Where(a2=>a2.UserName.ToLower() == user.ToLower()));
result2 = no.Count() == 1;
if (result || result2)
{
return true;
}}
return false;
я вызываю фильтр действия внутри моего класса контроллера следующим образом:
[CheckUserPermissions(Action = "Read", Model = "Server")]
но у меня есть следующие проблемы:-
внутри моего репозитория я буду извлекать всех пользователей и группы (при вызове.Tolist()), а затем проверять, находится ли текущий логин в этих значениях. что не будет очень расширяемым при работе с огромным количеством пользователей?
каждый раз, когда пользователь вызывает метод действия, запускается один и тот же код безопасности (конечно, в идеале разрешение пользователя может измениться во время сеанса пользователя), что может вызвать проблемы с производительностью?
Так может кто-нибудь подсказать, как я могу улучшить свою текущую реализацию, принимая во внимание две проблемы? Спасибо
1 ответ
Я бы изменил ваш подход и использовал бы проверку подлинности на основе утверждений.
Таким образом, вы получаете гораздо более детальный контроль над авторизацией (это может быть обусловлено ресурсами и действиями).
Вы можете использовать ClaimsAuthorizationManager для проверки доступа на каждом уровне в центральном месте.
В этой статье объясняется, как реализовать это, а также использовать безопасные билеты сеанса, чтобы каждый раз сохранять доступ к базе данных.