Html js событие выбор пункта select. Обработчик события onChange объекта Select

Скажем, что у вас есть.net web api с действием GetResource (int resourceId). Это действие (с указанным идентификатором) должно быть разрешено только для пользователя, связанного с этим идентификатором (например, ресурс может быть блогером, написанным пользователем).

Это можно решить разными способами, но ниже приведен пример.

Public Resource GetResource(int id) { string name = Thread.CurrentPrincipal.Identity.Name; var user = userRepository.SingleOrDefault(x => x.UserName == name); var resource = resourceRepository.Find(id); if (resource.UserId != user.UserId) { throw new HttpResponseException(HttpStatusCode.Unauthorized); } return resource; }

где пользователь был аутентифицирован каким-то механиком.

Теперь скажем, что я также хочу, чтобы пользователь, например, типа администратора, имел право потреблять конечную точку (с тем же идентификатором). Этот пользователь не имеет прямого отношения к ресурсу, но имеет авторизацию из-за его типа (или роли). Это можно решить, просто проверив, имеет ли пользователь тип администратора и возвращает ресурс.

Есть ли способ централизовать это таким образом, чтобы мне не приходилось писать код авторизации в каждом действии?

Edit Основываясь на ответах, я думаю, что должен уточнить свой вопрос.

То, что я действительно делаю, - это механизм, который позволяет иметь авторизацию на основе ресурсов, но в то же время позволяет некоторым пользователям также использовать одну и ту же конечную точку и тот же ресурс. Ниже приведенное действие разрешит это для этой конкретной конечной точки и для этой конкретной роли (Admin).

Public Resource GetResource(int id) { string name = Thread.CurrentPrincipal.Identity.Name; var user = userRepository.SingleOrDefault(x => x.UserName == name); var resource = resourceRepository.Find(id); if (!user.Roles.Any(x => x.RoleName == "Admin" || resource.UserId != user.UserId) { throw new HttpResponseException(HttpStatusCode.Unauthorized); } return resource; }

То, что я получаю, - это общий способ решить эту проблему, так что мне не нужно писать две разные конечные точки с той же целью или писать код, специфичный для ресурсов на каждой конечной точке.

4 ответов

Для авторизации на основе ресурсов я бы предложил использовать идентификатор, основанный на требованиях , и вставить идентификатор пользователя в качестве претензии. Напишите метод расширения, чтобы прочитать заявку от личности. Таким образом, пример кода будет выглядеть следующим образом:

Public Resource GetResource(int id) { var resource = resourceRepository.Find(id); if (resource.UserId != User.Identity.GetUserId()) { throw new HttpResponseException(HttpStatusCode.Unauthorized); } return resource; }

Если вы хотите еще больше упростить код, вы можете написать UserRepository, который знает данные пользователя и репозиторий ресурсов для централизации кода. Код будет выглядеть так:

Public Resource GetResource(int id) { return User.Identity.GetUserRepository().FindResource(id); }

Для авторизации на основе роли AuthorizeAttribute будет лучшим местом для ее обработки, и вам лучше использовать отдельное действие или контроллер для этого.

Public Resource GetResourceByAdmin(int id) { return resourceRepository.Find(id); }

[Изменить] Если OP хочет использовать одно действие для работы с разными типами пользователей, я лично предпочитаю использовать репозиторий пользователя factory. Код действия:

Public Resource GetResource(int id) { return User.GetUserRepository().FindResource(id); }

Метод расширения будет:

Public static IUserRepository GetUserRepository(this IPrincipal principal) { var resourceRepository = new ResourceRepository(); bool isAdmin = principal.IsInRole("Admin"); if (isAdmin) { return new AdminRespository(resourceRepository); } else { return new UserRepository(principal.Identity, resourceRepository); } }

Причина, по которой я не хочу использовать AuthorizeAttribute для проверки подлинности каждого ресурса, заключается в том, что у разных ресурсов может быть другой код для проверки права собственности, трудно централизовать код в одном атрибуте, и для этого требуются дополнительные операции с БД, что на самом деле не является необходимо. Еще одна проблема заключается в том, что AuthroizeAttribute происходит до привязки параметров, поэтому вам нужно убедиться, что параметр действия поступает из данных маршрута. В противном случае, например, из тела сообщения вы не сможете получить значение параметра.

Вам необходимо выполнить экстернализацию своей авторизации. Вы хотите переместить всю логику авторизации на отдельный уровень или службу.

Существует несколько рамок - на разных языках - которые позволяют вам это делать. В мире.NET, как предложено в других ответах, у вас есть авторизация на основе требований. У Microsoft есть отличная статья о .

  • стандартная архитектура с понятием точки принятия решения о политике (PDP - это ваша служба авторизации), которая может служить да/нет решений
  • стандартный язык для выражения логики авторизации с использованием любого количества параметров/атрибутов, включая атрибуты пользователя и информацию о ресурсе.
  • схема запроса/ответа для отправки ваших вопросов авторизации в PDP.

Если мы перейдем к вашему примеру, у вас будет что-то по строкам:

Public Resource GetResource(int id) { var resource = resourceRepository.Find(id); if (isAuthorized(User.Identity,resource)) { throw new HttpResponseException(HttpStatusCode.Unauthorized); } return resource; } public bool isAuthorized(User u, Resource r){ // Create XACML request here // Call out to PDP // return boolean decision }

Ваш PDP будет содержать следующие правила:

  • пользователь может выполнить действие == представление на ресурсе тогда и только тогда, когда resource.owner == user.id
  • пользователь с ролью == administrator может выполнить действие == на ресурсе.

Преимущество XACML заключается в том, что вы можете вырабатывать свои правила/логику авторизации независимо от вашего кода. Это означает, что вам не нужно касаться вашего кода приложения всякий раз, когда изменяется логика. XACML также может обслуживать больше параметров/атрибутов - например, идентификатор устройства, IP-адрес, время суток... Наконец, XACML не относится к.NET. Он работает для разных рамок.

Я бы посмотрел на реализацию пользовательского System.Web.Http.AuthorizeAttribute , который вы могли бы применить к действиям, которые нуждаются в этом конкретном правиле авторизации. В пользовательской авторизации вы можете разрешить доступ, если пользователь является членом группы "Админы", или если он является автором ресурса.

ИЗМЕНИТЬ:

Основываясь на редактировании OP, позвольте мне расширить то, что я говорю. Если вы переопределите AuthorizeAttribute, вы можете добавить логику, например:

Public class AuthorizeAdminsAndAuthors: System.Web.Http.AuthorizeAttribute { protected override bool IsAuthorized(HttpActionContext actionContext) { return currentUser.IsInRole("Admins") || IsCurrentUserAuthorOfPost(actionContext); } private bool IsCurrentUserAuthorOfPost(HttpActionContext actionContext) { // Get id for resource from actionContext // look up if user is author of this post return true; }

Это псевдокод, но должен передать идею. Если у вас есть один атрибут AuthorizeAttribute, который определяет авторизацию на основе ваших требований: текущий запрос - либо от автора сообщения, либо от администратора, то вы можете применить атрибут AuthorizeAdminsAndAuthors к любому ресурсу, где требуется этот уровень авторизации. Таким образом, ваш ресурс будет выглядеть так:

Public Resource GetResource(int id) { var resource = resourceRepository.Find(id); return resource; }

Устанавливает обработчик выделения текста внутри элемента или, либо, запускает это событие. Данное событие может происходить только в элементах и . Метод имеет три варианта использования:

handler(eventObject) — функция, которая будет установлена в качестве обработчика. При вызове она будет получать объект события eventObject .

handler(eventObject) — см. выше.
eventData — дополнительные данные, передаваемые в обработчик. Они должны быть представлены объектом в формате: {fName1:value1, fName2:value2, ...} .

Убрать установленный обработчик можно с помощью метода unbind() .

Все три варианта использования метода, являются аналогами других методов (см. выше), поэтому все подробности использования select() , можно найти в описании этих методов.

В случае выделения текста с помощью мыши, браузеры вызывают событие select при завершении выделения. Если выделение происходит с помощью нажатия клавиш ← → ↓ при зажатом shift"е, то событие будет происходить при каждом отпускании клавиши со стрелкой.

Для того, чтобы получить выделенную часть текста в разных браузерах требуются разные средства. В FireFox и Google Chrome выделенную часть даст метод window.getSelection() или document.getSelection() , в то время как IE и Opera предоставят нужный текст при вызове метода document.selection.createRange() . Кроссбраузерный вариант будет выглядеть так:

function selectedText() { if (window.getSelection ) txt = window.getSelection () .toString () ; else if (document.getSelection ) txt = document.getSelection () ; else if (document.selection ) txt = document.selection .createRange () .text ; return txt; }

Отметим, что функция selectedText() будет работать не только для и , она будет возвращать выделенный текст, в каком бы элементе (элементах) он не находился.

Пример

// установим обработчик события select, элементу с идентификатором foo $("#foo" ) .select (function () { alert ("Внутри элемента foo, пользователем был выделен текст." ) ; } ) ; // вызовем событие select на элементе foo $("#foo" ) .select () ; // установим еще один обработчик события select, на этот раз элементам // с классом block. В обработчик передадим дополнительные данные $(".block" ) .select ({ a: 12 , b: "abc" } , function (eventObject) { var externalData = "a=" + eventObject.data .a + ", b=" + eventObject.data .b ; alert ("Внутри элемента с классом block был выделен текст" + "В обработчик этого события переданы данные: " + externalData ) ; } ) ;

список может быть либо с возможностью выбора только одного варианта, либо нескольких вариантов.

С каждым контейнером ассоциирован объект класса Select , а с каждым дочерним контейнером - объект класса Option , являющийся свойством данного объекта класса Select . Кроме того, свойством объекта класса Select является также коллекция options , объединяющая все его дочерние объекты Option . Перечислим основные свойства, методы и события, характеризующие эти объекты.

Объект Select Свойства Методы Обработчики событий

options size length multiple selectedIndex

focus() blur() add() remove()

onBlur onChange onFocus

Объект Option Свойства Методы События

defaultSelected selected index text value

нет нет

Мы не будем описывать все свойства, методы и события этих двух объектов. Остановимся только на типичных способах применения их комбинаций.

Создание объектов Option

Объект класса Option интересен тем, что в отличие от многих других встроенных в DOM объектов JavaScript, имеет конструктор. Это означает, что программист может сам создать объект класса Option :

opt = new Option([ text, [ value, [ defaultSelected, [ selected ]]]]);

где аргументы соответствуют свойствам обычных объектов класса Option :

  • text - строка текста, которая размещается в контейнере (например: текст );
  • value - значение, которое передается серверу при выборе альтернативы, связанной с объектом Option ;
  • defaultSelected - выбрана ли эта альтернатива по умолчанию (true / false );
  • selected - альтернатива была выбрана пользователем (true / false ).

На первый взгляд не очень понятно, для чего может понадобиться программисту такой объект, ведь создать объект класса Select нельзя и, следовательно, нельзя приписать ему новый объект Option . Все объясняется, когда речь заходит об изменении списка альтернатив у имеющегося в документе объекта Select . Делать это можно, при этом изменение списка альтернатив Select не приводит к переформатированию документа. Изменение списка альтернатив позволяет решить проблему создания вложенных меню, которых нет в HTML-формах , путем программирования обычных меню (options ).

При программировании альтернатив следует обратить внимание на то, что у объектов класса Option нет свойства name , в виду того, что у контейнера нет атрибута NAME . Таким образом, к встроенным в документ объектам класса Option можно обращаться только как к элементам коллекции options .

Коллекция options

Встроенный массив (коллекция ) options - это одно из свойств объекта Select . Элементы этого массива являются полноценными объектами класса Option . Они создаются по мере загрузки страницы браузером. Количество объектов Option , содержащихся в объекте document.f.s класса Select , можно узнать с помощью стандартного свойства массива: document.f.s.options. length . Кроме того, у самого объекта Select есть такое же свойство: document.f.s. length - оно полностью идентично предыдущему.

Программист имеет возможность не только создавать новые объекты Option , но и удалять уже созданные браузером объекты:

Первый вариант Второй вариант Третий вариант 5.3. Удаление вариантов из SELECT

В данном примере при загрузке страницы с сервера у нас имеются три альтернативы. Их можно просматривать как ниспадающий список вариантов. После нажатия на кнопку " Удалить последний вариант " в форме остается только две альтернативы. Если еще раз нажать на эту кнопку, останется только одна альтернатива. В конечном счете, вариантов не останется вовсе, т.е. пользователь лишится возможности выбора. При нажатии кнопки сброса ( reset ) варианты не восстанавливаются - альтернативы утеряны бесследно.

Теперь, используя конструктор Option , сделаем процесс обратимым:

function RestoreOptions() { document.f.s.options = new Option("Вариант один","",true,true); document.f.s.options = new Option("Вариант два"); document.f.s.options = new Option("Вариант три"); return false; } Первый вариант Второй вариант Третий вариант 5.4. Удаление и добавление вариантов из SELECT

Восстановление альтернатив мы поместили в обработчик события onReset контейнера FORM . Создаваемые объекты класса Option мы присваиваем объекту document.f.s класса Select . При этом первая альтернатива должна быть выбранной по умолчанию (аргументу defaultSelected задано значение true ), чтобы смоделировать поведение при начальной загрузке страницы.

Свойства text и value объекта Option

Свойство text представляет собой отображаемый в меню текст, который соответствует альтернативе. В HTML-коде он расположен между тэгами и . Свойство value содержит значение атрибута VALUE тэга . Например, пусть один из вариантов в списке был описан как:

Вариант первый

Тогда значение свойства text у соответствующего объекта будет равно " Вариант первый ", а значение свойства value равно " n1 ".

Возникает вопрос, зачем нужны два свойства? Дело в том, что на сервер передается значение value выбранного варианта. В случае же, когда атрибут VALUE у контейнера отсутствует, на сервер передается значение text .selectedIndex возвратит индекс первой выбранной опции. На этот случай имеется альтернатива: свойство selected у каждого объекта Option . Оно равно true , если данная опция выбрана, и false в противном случае. Пример будет приведен ниже.

Обработчик события onChange объекта Select

Событие Change наступает в тот момент, когда пользователь меняет свой выбор вариантов. Если поле является полем выбора единственного варианта, то все просто - см. предыдущий пример. Посмотрим, что происходит, когда мы имеем дело с полем выбора множественных вариантов:

Фрукты: яблоко банан киви персик
Выбраны позиции: 5.5. Обработчик onChange при выборе множественных вариантов

Обратите внимание на то, что событие Change происходит тогда, когда пользователь выбирает или отменяет какой-либо вариант. Исключение составляет тот случай, когда варианты при выборе последовательно отмечаются (нажатие кнопки мыши на одном элементе, ведение мыши до конечного элемента, отпускание кнопки мыши). В этом случае событие происходит в тот момент, когда пользователь отпускает кнопку мыши, и все отмеченные альтернативы становятся выбранными.

Свойства selected и selectedIndex

Свойства text и value объекта Option

Свойство text представляет собой отображаемый в меню текст, который соответствует альтернативе. В HTML-коде он расположен между тэгами и . Свойство value содержит значение атрибута VALUE тэга. Например, пусть один из вариантов в списке был описан как:

Вариант первый

Тогда значение свойства text у соответствующего объекта будет равно "Вариант первый ", а значение свойства value равно " n1 ".

Возникает вопрос, зачем нужны два свойства? Дело в том, что на сервер передается значение value выбранного варианта. В случае же, когда атрибутVALUE у контейнера отсутствует, на сервер передается значение text.

Свойство selectedIndex объекта Select возвращает номер выбранного варианта (нумерация начинается с нуля).

Вариант: ОдинДваВыбрали индекс:

Обратите внимание, что в обработчике события onChange мы ссылаемся на второй элемент формы. На данный момент он не определен, но событие произойдет только тогда, когда мы будем выбирать вариант - к этому моменту поле уже будет определено.

Если список вариантов задан как , т.е. с возможностью выбора нескольких опций одновременно, то свойство selectedIndex возвратит индекс первой выбранной опции. На этот случай имеется альтернатива: свойство selected у каждого объекта Option. Оно равно true, если данная опция выбрана, и false в противном случае. Пример будет приведен ниже.

Событие Change наступает в тот момент, когда пользователь меняет свой выбор вариантов. Если поле является полем выбора единственного варианта, то все просто - см. предыдущий пример. Посмотрим, что происходит, когда мы имеем дело с полем выбора множественных вариантов:

Фрукты: яблокобананкивиперсик
Выбраны позиции:

Пример 5.5. Обработчик onChange при выборе множественных вариантов (html, txt)

Обратите внимание на то, что событие Change происходит тогда, когда пользователь выбирает или отменяет какой-либо вариант. Исключение составляет тот случай, когда варианты при выборе последовательно отмечаются (нажатие кнопки мыши на одном элементе, ведение мыши до конечного элемента, отпускание кнопки мыши). В этом случае событие происходит в тот момент, когда пользователь отпускает кнопку мыши, и все отмеченные альтернативы становятся выбранными.




Top