asp.net mvc, несколько провайдеров ролей CustomAuthorize
Я пытаюсь заблокировать свое приложение для каждого метода, где пользователи и администраторы могут видеть весь контроллер, но только администраторы могут создавать, удалять и редактировать.
Я создал класс CustomAuthorize, который содержит метод:
public class CustomAuthorize : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
Debug.WriteLine("Show me the filterContext " + filterContext);
if (filterContext.Result is HttpUnauthorizedResult)
{
Debug.WriteLine("Why is this going to the redirect to AccessDenied?");
filterContext.Result = new RedirectResult("~/AccessDenied/Index");
}
}
}
Мой класс RoleProvider:
namespace Office.WebUI.Security {
public class OfficeRoleProvider : RoleProvider
{
public override void AddUsersToRoles(string[] usernames, string[] roleNames)
{
throw new NotImplementedException();
}
public override string ApplicationName
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
public override void CreateRole(string roleName)
{
throw new NotImplementedException();
}
public override bool DeleteRole(string roleName, bool throwOnPopulatedRole)
{
throw new NotImplementedException();
}
public override string[] FindUsersInRole(string roleName, string usernameToMatch)
{
throw new NotImplementedException();
}
public override string[] GetAllRoles()
{
throw new NotImplementedException();
}
public override string[] GetRolesForUser(string username)
{
Debug.WriteLine("Get the username" + username);
using (EFDbContext db = new EFDbContext()) >
{
User user = db.Users.FirstOrDefault(u => u.UserName.Equals(username, >stringComparison.CurrentCultureIgnoreCase) || u.Email.Equals(username, StringComparison.CurrentCultureIgnoreCase));
//User user = db.TaskPrivilege.FirstOrDefault(u => >u.UserName.Equals(username, StringComparison.CurrentCultureIgnoreCase) || u.Email.Equals(username, StringComparison.CurrentCultureIgnoreCase));
if (user != null)
{
var roles = from ur in user.UserRoles
from r in db.Roles
where user.role.RoleID == r.RoleID
//where ur.RoleID == r.RoleID
select r.Name;
if (roles != null)
return roles.ToArray();
else
return new string[] { }; ;
}
else
{
return new string[] { }; ;
}
}
}
public override string[] GetUsersInRole(string roleName)
{
throw new NotImplementedException();
}
public override bool IsUserInRole(string username, string roleName)
{
Debug.WriteLine("The username is " + username + " And the Role it is using is >" + roleName);
using (EFDbContext db = new EFDbContext())
{
User user = db.Users.FirstOrDefault(u => u.UserName.Equals(username, StringComparison.CurrentCultureIgnoreCase) || u.Email.Equals(username, StringComparison.CurrentCultureIgnoreCase));
if (user != null)
{
var roles = from ur in user.UserRoles
from r in db.Roles
where user.role.RoleID == r.RoleID
//where ur.RoleID == r.RoleID
select r.Name;
if (user != null)
return roles.Any(r => r.Equals(roleName, >StringComparison.CurrentCultureIgnoreCase));
else
return false;
}
else
{
return false;
}
}
}
public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames)
{
throw new NotImplementedException();
}
public override bool RoleExists(string roleName)
{
throw new NotImplementedException();
}
}
}
В моей базе данных у меня есть таблица ролей, в которой в качестве столбцов содержатся Role и RoleID, с двумя значениями "Администратор" и "Пользователь" в качестве ролей с ролью ID в качестве PK, 1 = "Администратор" и 2 = "Пользователь". Другая таблица с именем Users, которая содержит UserID, Username и role_RoleID
Когда я назначаю пользователя для role_RoleID как 1 (администратор) и блокирую контроллер, используя
[CustomAuthorize(Roles = "Администратор"]
Это работает.
Когда я назначаю role_RoldID = 2 и блокируюсь, используя:
[CustomAuthorize(Roles = "Пользователь"]
Это не работает?
Еще один вопрос: как мне назначить 2 роли контроллеру? Затем я хочу заблокировать каждый метод для 1 роли пользователя.
Надеюсь, что это имеет смысл, и я надеюсь, что кто-то может мне помочь, пожалуйста.
Спасибо
Стивен
В основном у меня есть контроллер, который я поставил [CustomAuthorize(Roles = "Administrators, Support")]
чтобы заблокировать его, чтобы обе роли могли видеть контроллер.
Затем у меня есть методы создания / удаления и редактирования:
[CustomAuthorize(Roles = "Administrators")]
так что в основном я хочу показать весь контроллер обеим ролям, но только администраторы могут создавать / редактировать / удалять.
Когда я назначаю roleID в таблице user = 2(User), все приложение разрывается для этого пользователя. Назначение RoldID = 1 (администраторы) работает для всех людей, которым назначен roldID 1.
В настоящее время у меня есть методы
public override string[] GetRolesForUser(string username)
{
using (EFDbContext db = new EFDbContext())
{
User user = db.Users.FirstOrDefault(u => u.UserName.Equals(username, StringComparison.CurrentCultureIgnoreCase) || u.Email.Equals(username, StringComparison.CurrentCultureIgnoreCase));
if (user != null)
{
var roles = from ur in user.UserRoles
from r in db.Roles
where user.role.RoleID == r.RoleID
select r.Name;
if (roles != null)
return roles.ToArray();
else
return new string[] { }; ;
}
else
{
return new string[] { }; ;
}
}
}
> public override bool IsUserInRole(string username, string roleName)
> {
>
> using (EFDbContext db = new EFDbContext())
> {
> User user = db.Users.FirstOrDefault(u => u.UserName.Equals(username, StringComparison.CurrentCultureIgnoreCase)
> || u.Email.Equals(username,
> StringComparison.CurrentCultureIgnoreCase));
>
> if (user != null)
> {
> var roles = from ur in user.UserRoles
> from r in db.Roles
> where user.role.RoleID == r.RoleID
> //where ur.RoleID == r.RoleID
> select r.Name;
> if (user != null)
> return roles.Any(r => r.Equals(roleName, >StringComparison.CurrentCultureIgnoreCase));
> else
> return false;
> }
> else
> {
> return false;
> }
> }
> }
Я знаю, что мне нужно изменить метод IsUserInRole, чтобы он обрабатывал параметр массива следующим образом: public override bool IsUserInRole(string username, string[] roleName)
Но не знаю, как справиться с этим в linq и главным образом в методе IsUserInRole:
return roles.Any(r => r.Equals(roleName, >StringComparison.CurrentCultureIgnoreCase));
В настоящее время происходит сбой в методе GetRolesForUser, в предложении, где я считаю,
где user.role.RoleID == r.RoleID
сообщение об ошибке отображается ниже:
Уже есть открытый DataReader, связанный с этой Командой, который должен быть закрыт первым. Описание: во время выполнения текущего веб-запроса произошло необработанное исключение. Пожалуйста, просмотрите трассировку стека для получения дополнительной информации об ошибке и о том, где она возникла в коде.
Сведения об исключении: System.InvalidOperationException: уже существует открытый DataReader, связанный с этой командой, который должен быть закрыт первым.
Ошибка источника:
Строка 66: var role = от ur в user.UserRoles Строка 67: от r в db.Roles Строка 68: где user.role.RoleID == r.RoleID
Спасибо
1 ответ
Несколько ролей могут быть выполнены как таковые: [CustomAuthorize(Roles = "Administrator, User")]
Но, увидев, что вы написали этот код, я думаю, вы уже знаете это?
Если все, что вы хотите сделать, это сохранить Users
от получения в ваших функциях создания / редактирования / удаления, почему бы не использовать функции авторизации по умолчанию? смысл положить [CustomAuthorize(Roles = "Administrator")]
выше редактировать / создавать / удалять и [CustomAuthorize(Roles = "Administrator, User")]
превыше всего...
Я угадываю IsUserInRole
вызывается при авторизации? Этот метод должен принимать массив string[] roleName, а не просто строку.
Изменить: изменить
var roles = from ur in user.UserRoles
from r in db.Roles
where user.role.RoleID == r.RoleID
//where ur.RoleID == r.RoleID
select r.Name;
в
var roles = user.UserRoles.select(q=>q.Roles.Name);