مرجع تخصصی برنامه نویسان

بزرگترین انجمن برنامه نویسان فارسی زبان

IAsyncAuthorizationFilter در Asp.net Core

شنبه, 29 دی 1397 22:08

IAsyncAuthorizationFilter در Asp.net Core

سلام 
در پروژه ای از این فیلتر احراز هویت استفاده کردم 

    public class DynamicAuthorizationFilter : IAsyncAuthorizationFilter
    {
        private readonly ApplicationDbContext _dbContext;

        public DynamicAuthorizationFilter(ApplicationDbContext dbContext)
        {
            _dbContext = dbContext;
        }

        public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
        {
            if (!IsProtectedAction(context))
                return;

            if (!IsUserAuthenticated(context))
            {
                context.Result = new UnauthorizedResult();
                return;
            }

            var actionId = GetActionId(context);
            var userName = context.HttpContext.User.Identity.Name;

            var roles = await (
                from user in _dbContext.Users
                join userRole in _dbContext.UserRoles on user.Id equals userRole.UserId
                join role in _dbContext.Roles on userRole.RoleId equals role.Id
                where user.UserName == userName
                select role
            ).ToListAsync();

            foreach (var role in roles)
            {
                if(role.Access == null)
                    continue;
                    
                var accessList = JsonConvert.DeserializeObject<IEnumerable<MvcControllerInfo>>(role.Access);
                if (accessList.SelectMany(c => c.Actions).Any(a => a.Id == actionId))
                    return;
            }

            context.Result = new ForbidResult();
        }

        private bool IsProtectedAction(AuthorizationFilterContext context)
        {
            if (context.Filters.Any(item => item is IAllowAnonymousFilter))
                return false;

            var controllerActionDescriptor = (ControllerActionDescriptor)context.ActionDescriptor;
            var controllerTypeInfo = controllerActionDescriptor.ControllerTypeInfo;
            var actionMethodInfo = controllerActionDescriptor.MethodInfo;

            var authorizeAttribute = controllerTypeInfo.GetCustomAttribute<AuthorizeAttribute>();
            if (authorizeAttribute != null)
                return true;

            authorizeAttribute = actionMethodInfo.GetCustomAttribute<AuthorizeAttribute>();
            if (authorizeAttribute != null)
                return true;

            return false;
        }

        private bool IsUserAuthenticated(AuthorizationFilterContext context)
        {
            return context.HttpContext.User.Identity.IsAuthenticated;
        }

        private string GetActionId(AuthorizationFilterContext context)
        {
            var controllerActionDescriptor = (ControllerActionDescriptor)context.ActionDescriptor;
            var area = controllerActionDescriptor.ControllerTypeInfo.GetCustomAttribute<AreaAttribute>()?.RouteValue;
            var controller = controllerActionDescriptor.ControllerName;
            var action = controllerActionDescriptor.ActionName;

            return $"{area}:{controller}:{action}";
        }
    }

و برای کنترلر ها از [Authorize] استفاده کردم تا این فیلتر اعمال بشه بر روی کنترلر ها

ولی 
چون هم در پروژه یک طرف Cms سایت هست و یک طرف خود سایت هست 
Cms که در Area  ادمین قرار داره و کلا این دو (سایت و Cms )کنترلر ها و ویو هاش از هم جدا هستند 
 ولی من میخواهم این فیلتر فقط بر روی کنترلر های Cms اعمال بشه 
ولی وقتی در کنترلر ها سایت یا کنترلر های Cms از [Authorize] استفاده میکنم فیلتر بالا روی هر دو اعمال میشه 
چه طور میتونم یه فیلتر جدا برای بخش سایت نوشت و از هم جدا و به کنترلرهاش اعمال کرد ؟
در کل چه طور میشه  چند authorization filter نوشت روی هر کنترلی که خواستی اعمال کنی 
م

پنج شنبه, 25 بهمن 1397 11:29

با سلام خدمت شما

میتونین از فیلتر زیر استفاده کنین

public class PermissionCheckerAttribute : AuthorizeAttribute, IAuthorizationFilter
    {
        private IRoleService _roleService;

        private string _permission;

        public PermissionCheckerAttribute(string permissionName)
        {
            _permission = permissionName;
        }

        public void OnAuthorization(AuthorizationFilterContext context)
        {
            _roleService = (IRoleService)context.HttpContext.RequestServices.GetService(typeof(IRoleService));

            if (context.HttpContext.User.Identity.IsAuthenticated)
            {
                string userName = context.HttpContext.User.Identity.Name;

                if (!_roleService.CheckUserPermission(userName, _permission))
                {
                    context.Result = new RedirectResult("/Login");
                }
            }
            else
            {
                context.Result = new RedirectResult("/Login");
            }
        }
    }

بالای هر کنترلر و یا حتی اکشن میتونین از این فیلتر به صورت زیر استفاده کنین 

[PermissionChecker("ManageUsers")]
    public class UsersController : BaseController
    

متد CheckUserPermission وضعیت نقش های کاربر رو بررسی میکنه بدین صورت :

public bool CheckUserPermission(string userName, string permission)
        {
            var user = _context.Users
                .Include(s => s.UserRole)
                .SingleOrDefault(s => s.UserName == userName && !s.IsDelete && !s.IsBan);

            if (user != null)
            {
                var result = _context.UserRoles
                    .Include(s => s.User)
                    .Include(s => s.Role)
                    .Include(s => s.Role.RolePermissions)
                    .Any(u => u.User.UserName == userName && u.Role.RolePermissions.Any(p => p.Permission.Name == permission));

                return result;
            }

            return false;
        }

ارسال پاسخ برای این تاپیک

ارسال پاسخ مخصوص اعضا سایت می باشد ! میتوانید با حساب کاربری خود وارد سایت شده یا ثبت نام کنید