Эта статья понимает, как фильтры и перехватчики работают через простую практику разработки сертификации безопасности.
Многие статьи ассоциируют фильтры, перехватчики и слушателей с пружиной, чтобы объяснить, и считают, что фильтры, перехватчики и слушатели являются широко используемыми компонентными функциями, предоставленными весной.
Но строго говоря, фильтры и слушатели принадлежат к API сервлета и не имеют ничего общего с весной.
Поскольку фильтр наследует от интерфейса javax.servlet.filter и слушатель наследует от интерфейса javax.servlet.servletcontextlister, только интерфейс Interceptor наследует интерфейс org.springframe.web.servlet.handlerinterceptor.
Вышеупомянутая блок -схема ссылается на онлайн -информацию, а одна картина стоит тысячи слов. После прочтения этой статьи у вас будет более глубокое понимание процесса вызова фильтров и перехватчиков.
1. Идеи дизайна сертификации безопасности
Иногда, когда внутренние и внешние сети вызывают API, требования безопасности для различных требований. Во многих случаях различные ограничения на внешние сети вызовы API не являются необходимыми во интрасети. Однако при развертывании шлюзов API, которые должны быть вызваны внутренними и внешними сетями, могут быть развернуты вместе из -за проблем с затратами и сложностью.
Чтобы реализовать безопасность интерфейса остального, это может быть сделано с помощью зрелых рамок, таких как Spring Security или Shiro.
Однако, поскольку структура безопасности часто бывает сложными (я подсчитал Spring Security, существует около 11 основных модулей, а количество исходного кода Shiro также довольно удивительна). В то же время могут быть введены сложные конфигурации (может ли это заставить людей чувствовать себя более приятными), что не способствует гибкому и быстрому развитию, развертыванию и проблемному исследованию малых и средних команд.
Многие команды строят свои собственные колеса для обеспечения сертификации безопасности. Этот простой пример сертификации в этой статье относится к бывшей команде по разработке фабрики, где я являюсь, и может считаться сертификацией сертификации безопасности на основе токенов.
Общая идея дизайна заключается в следующем:
1. Настройте заголовок HTTP -запроса. Каждый раз, когда называется API, значение токена передается в заголовке запроса.
2. Поместите токен в кэше (например, Redis) и установите время истечения срока действия различных политик в соответствии с различным бизнесом и API.
3. Токен может устанавливать белые списки и черные списки, которые могут ограничивать частоту вызовов API, облегчить развитие и тестирование, облегчить аварийное управление аномалиями и даже временно закрывать API.
4. Внешний сетевой вызов должен быть отправлен токен. Токен может быть связан с пользователем, например, каждый раз, когда вы открываете страницу или входите в систему, чтобы генерировать заголовок запроса на запись токена, страница проверяет обоснованность файлов cookie и токенов и т. Д.
В рамках безопасности весны есть две концепции, а именно аутентификация и авторизация . Аутентификация относится к пользователям, которые могут получить доступ к системе, в то время как авторизация - это ресурс, к которому пользователи могут получить доступ.
Для достижения вышеуказанных требований к аутентификации безопасности вам может потребоваться самостоятельно создать службу токена, чтобы гарантировать, что токен является уникальным. Модули, которые могут включать в себя пользовательские генераторы потока, CRM, шифрование и дешифрование, журналы, статистику API, кэши и т. Д., Но они фактически слабо связаны с пользователями (CRM). Некоторые общественные услуги, которые связаны с пользователями, такими как SMS и услуги по электронной почте, которые мы часто используем, также могут решать звонки безопасности с помощью механизма токена.
Таким образом, простая сертификация безопасности в этой статье на самом деле немного отличается от аутентификации и авторизации, предоставленной в рамках Spring Security Framework. Конечно, этот метод лечения «безопасности» не является новым для профессионалов, но он может заблокировать большое количество начинающих пользователей извне.
2. Настроить фильтр
Similar to Spring MVC, Spring Boot provides many servlet filters (Filters) to use, and it automatically adds some commonly used filters, such as CharacterEncodingFilter (used to handle encoding problems), HiddenHttpMethodFilter (hidden HTTP function), HttpPutFormContentFilter (form form processing), RequestContextFilter (request context), etc. Usually we will also customize Filter to Реализуйте некоторые общие функции, такие как запись журналов, определение того, следует ли войти в систему, проверка разрешения и т. Д.
1. Пользовательский заголовок запроса
Это очень просто, добавьте пользовательский заголовок запроса в заголовке запроса:
@RequestMapping (value = "/getInfobyid", method = requestMethod.post) @Apioperation ("Информация о продукте запроса на основе идентификатора продукта") @ApiimplicitaParams ({@ApiimplicitAlicAram (paramtype = "Header", name = "Authtoken", обязательно = true, value = "Authtoken", datatype = ")") ")") Getgoodsbygoodsidresponse getgoodsbygoodsid (@requestheader string authtoken, @requestbody getgoodsbygoodsidrequest) {return _goodsapiservice.getgoodsbygoodsid (запрос); } getgoodsbygoodsidПоле Authtoken, модифицированное @RequestHeader, может отображаться в рамках, как Swagger.
После вызова вы можете увидеть заголовок запроса в соответствии с инструментом HTTP. Пример в этой статье - Authtoken (отличается от токена некоторых рамок):
Примечание. Многие инструменты HTTPClient поддерживают заголовки запросов динамической передачи, такие как RestTemplate.
2. Реализуйте фильтр
В интерфейсе фильтра есть три метода, а именно init, Dofilter и Destory. Когда вы увидите имя, вы, вероятно, узнаете их основное использование. Обычно нам просто нужно обработать HTTP -запросы в методе Dofilter:
пакет com.power.demo.controller.filter; import com.power.demo.common.appconst; import com.power.demo.common.bizresult; импорт com.power.demo.service.contract.authtokenservice; импорт com.power.demo.util.powerlogger; com.power.demo.util.serializeutil; import org.springframework.beans.factory.annotation.autowired; import org.springframework.stereotyle.component; import javax.servlet.*; import javax.servlet.htp.httpserveltrequest; Authtokenfilter реализует фильтр {@autowired private authtokenservice authtokenservice; @Override public void init (filterConfig var1) бросает ServletException {} @Override public void dofilter (запрос ServletRequest, ответ servletresponse, цепь Filterchain) бросает ioException, servletexception {httpservlectrequest req = (httpservlectrequest) запрос; String token = req.getheader (appconst.auth_token); BizResult <string> bizResult = authtokenservice.powercheck (token); System.out.println (serializeutil.serialize (BizResult)); if (bizresult.getisok () == true) {powerlogger.info ("Auth Token Filter прошел"); chain.dofilter (запрос, ответ); } else {бросить новое ServletException (bizResult.getMessage ()); }} @Override public void destress () {}} authtokenfilterОбратите внимание, что с точки зрения фактической иерархии, большинство вещей, которые обрабатывают больше выражений, обрабатываются. Не рекомендуется напрямую использовать уровень доступа данных в фильтре. Хотя я видел такой код много раз во многих старых антикварных проектах год или два назад, и есть прецеденты для написания этого пути в книге << Spring Practice >>.
3. Сертификационный сервис
Это основная бизнес -логика. Пример кода - это просто простой способ записать идеи, и его нельзя легко использовать в производственных средах:
пакет com.power.demo.service.impl; import com.power.demo.cache.powercachebuilder; import com.power.demo.common.bizresult; импорт com.power.demo.service.contract.authtokenservice; импорт org.spramework.beans.factory.annotation; org.springframework.stereotype.component; import org.springframework.util.stringutils; @componentpublic class AuthtokenServiceimpl реализует authtokenservice {@autowired powercachebuilder cachebuilder; / * * Убедитесь, является ли токен заголовка запроса законным * */ @override public bizresult <string> powercheck (string token) {bizresult <string> bizresult = new bizresult <> (true, «проверка прошла»); System.out.println ("значение токена:" + token); if (stringutils.isempty (token) == true) {bizresult.setfail ("authtoken пуст"); вернуть BizreSult; } // Обработка BlackList BizResult = CheckForbidList (token); if (bizresult.getisok () == false) {return bizresult; } // Обработка белого списка bizResult = checkallowist (token); if (bizresult.getisok () == false) {return bizresult; } String key = string.format ("power.authtokenservice.%S", token); //cachebuilder.set(key, токен); //cachebuilder.set(key, token.touppercase ()); // Извлекать строку существует из cache = cachebuilder.get (key); if (stringUtils.isempty (существует) == true) {bizresult.setfail (string.format ("this authToken:%s", token)); вернуть BizreSult; } // Сравните, является ли токен одним и тем же логическим isequal = token.equals (существует); if (isequal == false) {bizresult.setfail (string.format ("Незаконная authtoken:%s", token)); вернуть BizreSult; } // Сделайте что -нибудь возвращение BizResult; }} AuthtokenserviceimplВы можете ссылаться на кеш -сервис, который вы используете здесь, что также является кратким опытом моего опыта на предыдущей фабрике.
4. Зарегистрировать фильтр
Есть два распространенных способа написать:
(1) Используйте аннотацию @webfilter, чтобы идентифицировать фильтр
@Order (1) @webfilter (urlpatterns = {"/api/v1/good/*", "/api/v1/userinfo/*"}) открытый класс Authtokenfilter реализует фильтр {Используя аннотацию @WebFilter, вы также можете использовать аннотацию @Order в сочетании с аннотацией @Order. Аннотация @Order представляет порядок фильтрации. Чем меньше значение, тем больше вы выполняете его первым. Этот размер заказа так же полезен, как и обработка жизненного цикла HTTP -запросов во время нашего процесса программирования. Конечно, если заказ не указан, порядок фильтра называется противоположным порядку добавленных фильтров, а реализация фильтра является шаблоном цепочки ответственности.
Наконец, добавьте аннотацию @servletcomponentscan в класс запуска, чтобы обычно использовать пользовательский фильтр.
(2) Используйте FilterRegistrationBean для настройки регистрации фильтра
В этой статье используется вторая реализация для реализации пользовательской регистрации фильтра:
пакет com.power.demo.controller.filter; import com.google.common.collect.lists; импорт org.springframework.beans.factory.annotation.autowired; импорт org.springframework.boot.web.servlet.filterRegistrationbebebebebebebebebe. org.springframework.context.annotation.configuration; import org.springframework.stereotyle.component; import java.util.list;@configuration@componentpublic class restfilterconfig {@autowired private filter @Bean Public FilterRegistrationBean FilegerRegistrationBean () {FilterRegistrationBean RegistrationBean = new FilterRegistrationBean (); RegistrationBean.SetFilter (фильтр); // set (fuzzy) Сопоставление URL -списка <string> urlpatterns = lists.newarraylist (); urlpatterns.add ("/api/v1/tober/*"); urlpatterns.add ("/api/v1/userinfo/*"); RegistrationBean.SetUrlPatterns (urlPatterns); RegistrationBean.SetOrder (1); RegistrationBean.SetEnabled (TRUE); возврат регистрации }} RestFilterConfigПожалуйста, обратите особое внимание на urlpatterns. Атрибут urlpatterns определяет отфильтрованный шаблон URL. Этот параметр имеет большое значение для области действий фильтра.
Зарегистрируйте фильтр, и после начала пружины он автоматически добавит цепочку приложений для приложений Filter ApplicationFilterChain, когда он обнаружит фасоль с помощью javax.servlet.filter.
Позвоните в API, чтобы попробовать эффект:
Обычно мы настраиваем глобальное унифицированное управление исключением GlobalexceptionHandler в рамках Spring Boot (он будет немного отличаться от вышесказанного).
Согласно моей практике, исключения, брошенные в фильтр, не будут пойманы и обрабатываются глобально уникальным улучшением управления исключениями. Это отличается от Interceptor Inteceptor и пользовательского AOP -перехватчика, представленного в следующей статье.
На этом этапе выполняется простая служба аутентификации безопасности, реализованная с помощью пользовательского фильтра.
3. Пользовательский перехватчик
1. Реализуйте перехватчик
Уточните интерфейс andler -interceptor и реализуйте перехватчик. Методы интерфейса следующие:
Prehandle выполняется до выполнения запроса
Posthandle - это конец выполнения запроса
После завершения выполнения после завершения визуализации представление
пакет com.power.demo.controller.interceptor; import com.power.demo.common.appconst; import com.power.demo.common.bizresult; импорт com.power.demo.service.contract.authtokenservice; импорт com.power.demo.util.powerlogger; com.power.demo.util.serializeutil; import org.springframework.beans.factory.annotation.autowired; import org.springframework.stereotype.component; импорт org.springframework.web.servlet.hhormlerinterceptor; import org.sprimework.weble.shlemerv.shlemerv.shlemerv.shle. javax.servlet.http.httpservletrequest; import javax.servlet.http.httpservletresponse; * * * * / * * Выполнить перед выполнением запроса * */ @override public boolean prehandle (httpservletrequest, httpservletresponse response, обработчик объекта) Throws exection {boolean handleresult = false; String token = request.getheader (appconst.auth_token); BizResult <string> bizResult = authtokenservice.powercheck (token); System.out.println (serializeutil.serialize (BizResult)); HastlerSult = bizResult.getisok (); Powerlogger.info ("auth token token interceptor receptor receptor receptor receptor receptor receptor receptor receptor receptor topen everceptor"); } else {бросить новое исключение (bizresult.getmessage ()); } return handlerSult; } / * * Запрос заканчивает выполнение * * / @override public void poshandle (httpservletrequest, httpservletresponse ответ, обработчик объекта, модель и модель модели и halks exection {} / * * execute revender redender * * * / @ @ @ @ @ @ @ @ @ @ @ @ @ @@override public -whipcomplotion (htttpservlectersersersersersersersersersevlectresersersersersersersersersersersersersersersersersersersersersersersersersersersersersersersersersersev Handler, Exception Ex) бросает исключение {}} authtokenInterceptorВ примере мы решили выполнить аутентификацию безопасности токена до выполнения запроса.
Служба аутентификации - это Authtokenservice, представленная в фильтре, а уровень бизнес -логики используется повторно.
2. Зарегистрируйте перехватчик
Определите класс InterceptorConfig, унаследованный от WebMVCConfigurationsUpport, а WebMVCConfigurerAdapter устарел.
Inject AuthtokenInterceptor в качестве компонента, URL и фильтры, которые перехватывают другие настройки, очень похожи:
Пакет com.power.demo.controller.interceptor; import com.google.common.collect.lists; import org.springframework.context.annotation.bean; импорт org.springframework.context.annotation.configuration; импорт org.spramework.stereotype.compontation; org.springframework.web.servlet.config.annotation.defauldervlethandlerconfigurer; импорт org.springframework.web.servlet.config.annotation.InterceptorRegistry; импорт org.springframework.web.servlet.annotation.resourcehandler; org.springframework.web.servlet.config.annotation.webmvcconfigurationsupport; import java.util.list;@configuration@componentpublic class classconfig extends webmvcconfigurationsupport {// webmvcconfigerdapge exterends webmvcconfiguration "/favicon.ico"; /*** обнаружил, что если WebMVCConfigurationsUpport унаследован, соответствующий контент, настроенный в YML, будет недействительным. * *@param Registry */@override public void addresourcehandlers (реестр ресурсов -индлеререгистика) {Registry.addresourcehandler ("/"). addresourcelocations ("/**"); Registry.addresourcehandler ("/static/**"). Addresourcelocations ("classpath:/static/"); } / *** Настройка обработки сервлета* / @Override public void configuredEfauldervleThandling (defaulderserlethandlerconfigurer configure) {configururer.enable (); } @Override public void AddInterceptors (реестр ReceptorTorgistry) {// set (Fuzzy) Сопоставление URL -лист <string> urlpatterns = lists.newarraylist (); urlpatterns.add ("/api/v1/tober/*"); urlpatterns.add ("/api/v1/userinfo/*"); Registry.addinterceptor (AuthtokenInterceptor ()). addPathPatterns (urlPatterns) .ExcludePathPatterns (favicon_url); Super.addinterceptors (реестр); } // Напишите перехватчик в качестве боба в конфигурацию @bean public authtokenInterceptor authTokenInterceptor () {return new authtOkenInterceptor (); }} ReceptorConfigПосле запуска приложения вы можете увидеть эффект перехвата перехвата, вызывая интерфейс. Global Unified Exception Management GlobalexceptionHandler обрабатывает следующие исключения после их поймы:
Он почти такой же, как основное сообщение об ошибке, отображаемое фильтром, но информация о стеке богаче.
4. Разница между фильтром и перехватчиком
Основные различия заключаются в следующем:
1. Перехватыватели в основном основаны на механизме отражения Java, в то время как фильтры основаны на образец функций
2. Interceptor не зависит от контейнера сервлета, фильтры полагаются на контейнер сервлета
3. Interceptors могут работать только над запросами действий, в то время как фильтры могут работать почти по всем запросам.
4. Перехватчик может получить доступ к объекту в стеке контекста действия и значений, но фильтр не может получить к нему доступ.
5. В течение жизненного цикла действия перехватчик можно назвать несколько раз, в то время как фильтр можно назвать только один раз при инициализировании контейнера.
В некоторых статьях, на которые я ссылался, говорится, что «перехватчик может получить различные бобы в контейнере МОК, но фильтр не может. Это очень важно. Внедрение услуги в перехватчик может вызвать бизнес -логику». После фактической проверки это неправильно.
Примечание. Время запуска фильтра состоит после контейнера и до сервлета, поэтому параметр входа фильтра DoFilter (запрос ServletRequest, отклик сервис -ответ, цепь FilterChain) является ServletRequest, а не httpservlectrequest, поскольку фильтр находится до Httpservlet. Следующая цифра может дать вам более интуитивно понятное понимание времени выполнения фильтра и перехватчика:
Только запросы, пройденные диспетчером, последует цепочке перехватчиков. Пользовательские запросы сервлета не будут перехвачены. Например, наш индивидуальный адрес сервенса http: // localhost: 9090/testservlet не будет перехвачен перехватчиком. Но независимо от того, к какому сервлету он принадлежит, фильтр будет выполнен, если он соответствует правилам фильтра фильтра.
Согласно вышеуказанному анализу, понимание принципа будет простым, даже фильтры ASP.NET будут такими же.
Проблема: достичь более гибкой аутентификации безопасности
В рамках Java Web через пользовательский фильтр фильтров или перехватчик перехватчика может быть достигнута безопасная аутентификация конкретных соответствующих API, таких как сопоставление всех API, сопоставление одного или нескольких API и т. Д., Но иногда этот соответствующий шаблон относительно не дружелюбен для разработчиков.
Мы можем обратиться к Spring Security для достижения мощных функций с помощью аннотации + Spel.
Например, в ASP.NET мы часто используем авторизованную функцию, которая может быть добавлена в классы или применять к методам, и можем контролировать аутентификацию безопасности более динамически и гибко.
Мы не выбрали Spring Security, поэтому мы можем реализовать гибкую сертификацию безопасности, аналогичную авторизованной. Основная технология реализации - это AOP, с которой мы знакомы.
Основное знание достижения более гибкого перехвата с помощью метода AOP не будет упомянуто в этой статье. Больше тем о AOP будут переданы в следующей статье.
Суммировать
Вышесказанное - это то, что редактор представил вам. Spring Boot использует фильтры и перехватчики для достижения простой и безопасной аутентификации интерфейсов отдыха. Я надеюсь, что это будет полезно для всех. Если у вас есть какие -либо вопросы, пожалуйста, оставьте мне сообщение, и редактор ответит всем вовремя. Большое спасибо за вашу поддержку сайту wulin.com!