All streams
Search
Write a publication
Pull to refresh
25
0
Андрей Родин @AndreyRodin

Разработчик

Send message
Надо думать, каждый блок кода, следующий за меткой, должен заканчиваться оператором return? И вот ваша функция уже превращается в блюдо спагетти, пусть даже уложенных ровным слоем. Хотя, возможно, вы просто перепутали последовательность меток в конце функции, и на самом деле они должны следовать в обратном порядке. Вот, кстати, еще один довод в пользу отказа от использования goto — оказывается, можно легко допустить ошибку и не заметить это!

На самом деле, я готов согласиться с тем, что возможны очень редкие случаи использования goto. В конце концов, Никлаус Вирт после долгих размышлений оставил этот оператор в своём языке Паскаль, изначально предназначенном исключительно для обучения.
Я только могу заметить, что за свою тридцатилетнюю практику работы разработчиком всего пару раз использовал оператор goto, и то в лишь в начале карьеры.

Что касается глобальных объектов, да — по большому счёту это зло. Почему — хорошо объясняется, например, здесь: ru.stackoverflow.com/questions/510910/%D0%9F%D0%BE%D1%87%D0%B5%D0%BC%D1%83-%D0%B3%D0%BB%D0%BE%D0%B1%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D0%B5-%D0%BF%D0%B5%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D1%8B%D0%B5-%D1%8D%D1%82%D0%BE-%D0%B7%D0%BB%D0%BE-%D0%B0-%D0%BF%D0%BE%D0%BB%D1%8F-%D0%BA%D0%BB%D0%B0%D1%81%D1%81%D0%B0-%D0%BD%D0%B5%D1%82. Но иногда глобальные обекты все-же приходится использовать, и thread-safe singletone — это лучший паттерн для этого. Кстати, сфера применения паттерна singletone чуть больше, чем просто объявление глобального объекта.
Звучит убедительно, спасибо.
Похоже, идея авторизации и использования OPTIONS в качестве довеска к HATEOAS не всегда проходит.

Когда я писал статью, я имел в виду чистый RESTful подход безо всяких кроссдоменных запросов. Ну что ж, тогда полезной частью статьи остаётся автоматизация реализации OPTIONS в ASP.NET Web API 2.

Ещё раз благодарю за подробные ответы!
Вы всё делаете неправильно

Призываю вас быть осторожнее в формулировках. Исход нашей дискуссия не повлияет на ценность статьи, даже если я окажусь неправ. Кстати, приведённый в статье код никак не принимает во внимание авторизацию и лишь автоматизирует выдачу ответов по запросу OPTIONS.

Стандарт говорит:
This method allows the client to determine the options and/or requirements associated with a resource, or the capabilities of a server, without implying a resource action or initiating a resource retrieval.
В стандарте идёт речь о цепочке запрос/ответ, определяемой по URI запроса. Надо ли серверу принимать во внимание такие хедеры как Authorization и формировать ответ в зависимости от прав текущего пользователя? Я полагаю, да. В стандарте явного запрета использовать хедеры нет.

Давайте взглянем на ситуацию с другой точки зрения. Должен ли метод OPTIONS вернуть NotAuthorized, если текущей пользователь не аутентифицирован? Если вы ответите нет, то я скажу, что в вашем проекте что-то не в порядке с безопасностью.

Почему делать бизнес-логику или отрисовку на основе хедера Allow – неправильно, я не понял. Вы же сами вначале говорили о том, что вы в вашем проекте делаете валидацию форм таким образом?

Что касается методов, то приведённые вами примеры – это не RESTful подход. Это что-то другое. Вас сразу должно насторожить наличие глаголов в ваших Url.
Кажется, где-то выше было замечено, что в общем случае это приводит к увеличению количества запросов. Так что, как ни крути, приходится признать, что буквальное следование принципам HATEOAS приводит к некоторому снижению отказоустойчивости в архитектуре микросервисов.
В теории это очень красиво и – спору нет – на самом деле решает многие проблемы, связанные с потенциальным изменением Uri на сервере.

Но на практике, мне кажется, это будет выглядеть не так радужно.

Предположим, передо мной стоит задача: получить ресурс по известному идентификатору. Что для меня, как разработчика, проще: сформировать Uri books/123 или полезть в документацию, прочитать, как организован поиск и построить Uri books?searchField=Id&searchText=123? Это ещё хорошо, если поиск реализован. А если нет?

Боюсь, большинство разработчиков предпочтут первый вариант.
А есть доказательства, что использование метода OPTIONS с учётом авторизации – неправильное?
Вы говорите о мандатном управлении доступом. А что насчёт избирательного управления доступом?
В любом случае, я предлагаю взглянуть на проблему шире, с точки зрения HATEOAS.
Ответ 404 может использоваться вместо 403, если требуется тщательно скрыть от посторонних глаз определённые ресурсы

ru.wikipedia.org/wiki/%D0%A1%D0%BF%D0%B8%D1%81%D0%BE%D0%BA_%D0%BA%D0%BE%D0%B4%D0%BE%D0%B2_%D1%81%D0%BE%D1%81%D1%82%D0%BE%D1%8F%D0%BD%D0%B8%D1%8F_HTTP#404
Пользователи – это, действительно, отдельный микросервис. У меня нигде не используется прямой доступ к базе пользователей. Маркер доступа позволяет получать данные текущего пользователя. Текущий пользователь – это пользователь, который был аутентифицирован приложением, и используется во всех межсервисных обменах, поэтому параметр userId в запросах не имеет смысла.

Разделение ресурсов и прав доступа к ним на два разных микросервиса теоретически возможно, равно как и совмещение их в одном микросервисе.

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

Всё, что описано в данной статье, реализовано в реальных проектах, и работает без нареканий.
Я описывал не приложение, а подход к реализации механизма авторизации в микросервисе.
Фильтрация сущностей на основе прав доступа входит в задачу авторизации. Операция GET для коллекции должна возвращать список объектов, к которым текущий пользователь имеет доступ.
Класс DbContext предназначен для обеспечения чтения и записи в базу данных. Проще говоря, он должен содержать только свойства DbSet — и ничего более. Попытка добавить в этот класс бизнес-логику выглядит как смешение зон ответственности. Обычно этот класс используется многими контроллерами совместно. Что будет, если ради каждого контроллера мы начнём добавлять свою бизнес-логику в наш DbContext?
Классы Entity тем более должны содержать исключительно свойства, соответствующие полям в базе. Сущности неразрывно связаны с нашим классом DbContext.
Бизнес-логика – это отдельный слой более высокого порядка. В данном примере логика авторизации сосредоточена в реализациях интерфейса IAccessor.
Не думаю, что перенос бизнес-логики в DB модель – это хорошая идея. Зона ответственности класса DbContext состоит в обеспечении модели сущностей, и ничего больше.
Но вы навели меня на важную мысль. Вызовы в контроллерах, действительно, смотрятся несколько неуклюже и могут выглядеть как нарушение закона Деметры.
Слегка подправил код, спасибо.
Да, вполне можно. Класс Factory приведён лишь для иллюстрации, а реализация IPrincipal может быть самой различной, в том числе, с использованием Claims. Надо только иметь в виду, что для данного подхода необходимо наличие Id пользователя в Thread.CurrentPrincipal
А вот это уже вопрос.
Есть мнение, что с точки зрения безопасности наилучшим выбором будет возврат NotFound, поскольку это не дает потенциальному взломщику знания о том, какие ресурсы реально существуют, а какие – нет.
Это старая дискуссия, и каждая компания выбирает свой стандарт.
Да, вы правы, кое-что потерялось при адаптации реального проекта, поправил.
Переименовал класс Accessor в UserBase, так, пожалуй, будет лучше.
Спасибо за внимательное чтение и замечания!

Information

Rating
Does not participate
Location
Электросталь, Москва и Московская обл., Россия
Date of birth
Registered
Activity