Dieser Artikel versteht, wie Filter und Interceptors eine einfache Entwicklungspraxis für Sicherheitszertifizierung durchführen.
Viele Artikel assoziieren Filter, Interceptors und Zuhörer mit Frühling und glauben, dass Filter, Interceptors und Zuhörer weit verbreitete Komponentenfunktionen sind, die von Spring bereitgestellt werden.
Aber streng genommen gehören Filter und Zuhörer zur Servlet -API und haben nichts mit dem Frühling zu tun.
Da der Filter von der Schnittstelle von javax.servlet.filter und der Hörer von der Schnittstelle javax.servlet.servletcontextListener erbt, erbt nur der Interceptor die org.springframework.web.Servlet.HandlerinterceTor -Oberfläche.
Aus dem obigen Flussdiagramm wird aus den Online -Informationen verwiesen, und ein Bild ist mehr als tausend Worte. Nach dem Lesen dieses Artikels haben Sie ein tieferes Verständnis für den aufrufenden Prozess von Filtern und Abfangjäger.
1. Ideen für Sicherheitszertifizierungsdesign
Manchmal, wenn interne und externe Netzwerke APIs aufrufen, die Sicherheitsanforderungen für unterschiedliche Anforderungen. In vielen Fällen sind im Intranet die verschiedenen Beschränkungen für externe Netzwerke APIs nicht erforderlich. Bei der Bereitstellung von Gateways können die APIs jedoch von internen und externen Netzwerken aufgerufen werden, die aufgrund von Kosten- und Komplexitätsproblemen zusammen bereitgestellt werden können.
Um die Sicherheit der REST -Schnittstelle zu verwirklichen, kann sie durch reife Frameworks wie Frühlingssicherheit oder Shiro erfolgen.
Da jedoch Sicherheitsrahmen häufig komplex sind (ich habe die Frühlingssicherheit gezählt, gibt es ungefähr 11 Kernmodule und die Menge an Quellcode von Shiro ist ebenfalls ziemlich erstaunlich). Gleichzeitig können komplexe Konfigurationen eingeführt werden (können sie Menschen angenehmer machen), was der flexiblen und schnellen Entwicklung, Einsatz und Problemuntersuchung kleiner und mittlerer Teams nicht förderlich ist.
Viele Teams bauen ihre eigenen Räder, um eine Sicherheitszertifizierung zu erreichen. Dieses einfache Zertifizierungsbeispiel in diesem Artikel bezieht sich auf das ehemalige Werksentwicklungsteam, wo ich mich bin, und kann als Token-basierter Sicherheitszertifizierungsdienst angesehen werden.
Die allgemeine Designidee lautet wie folgt:
1. Passen Sie den HTTP -Anforderungsheader an. Jedes Mal, wenn die API aufgerufen wird, wird ein Token -Wert im Anforderungsheader übergeben.
2. Legen Sie das Token in den Cache (wie z. B. Redis) und legen Sie die Ablaufzeit unterschiedlicher Richtlinien nach verschiedenen Geschäft und APIs fest.
3. Token kann Whitelisten und Blacklisten einstellen, was die Häufigkeit von API -Aufrufen einschränken, die Entwicklung und Prüfung erleichtern, die Notfallabwicklung von Abnormalitäten erleichtern und sogar die API vorübergehend schließen kann.
4. Der externe Netzwerkanruf muss an Token gesendet werden. Das Token kann mit dem Benutzer in Verbindung gebracht werden, z.
Es gibt zwei Konzepte im Frühlingssicherheitsrahmen, nämlich Authentifizierung und Autorisierung . Die Authentifizierung bezieht sich auf Benutzer, die auf das System zugreifen können, während die Autorisierung eine Ressource ist, auf die Benutzer zugreifen können.
Um die obigen einfachen Sicherheitsauthentifizierungsanforderungen zu erfüllen, müssen Sie möglicherweise unabhängig einen Token -Service erstellen, um sicherzustellen, dass das Token global einzigartig ist. Die Module, die benutzerdefinierte Flussgeneratoren, CRM, Verschlüsselung und Entschlüsselung, Protokolle, API -Statistiken, Caches usw. umfassen können, sind jedoch tatsächlich schwach an Benutzer gebunden (CRM). Einige öffentliche Dienste, die sich mit Benutzern zusammenhängen, wie beispielsweise SMS und E -Mail -Dienste, die wir häufig verwenden, können auch Sicherheitsanrufe über den Token -Mechanismus lösen.
Zusammenfassend unterscheidet sich die einfache Sicherheitszertifizierung in diesem Artikel tatsächlich etwas von der Authentifizierung und Autorisierung des Frühlingssicherheits -Frameworks. Natürlich ist diese "Sicherheitsbehandlungsmethode" für Fachkräfte nicht neu, kann jedoch eine große Anzahl von Anfängern von außen blockieren.
2. Filter anpassen
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 Um einige häufige Funktionen zu implementieren, z. B. Aufzeichnungen von Protokollen, festlegen, ob sich anmelden soll, die Überprüfung der Berechtigung usw.
1. Anforderungsheader
Es ist sehr einfach. Fügen Sie einen benutzerdefinierten Anforderungsheader im Anforderungsheader hinzu:
@RequestMapping(value = "/getinfobyid", method = RequestMethod.POST) @ApiOperation("Query product information based on product Id") @ApiImplicitParams({ @ApiImplicitParam(paramType = "header", name = "authtoken", required = true, value = "authtoken", dataType = "String"), }) public GetGoodsByGoodSIDResponse getGoodsByGoodsid (@Requestheader String authToken, @RequestBody GetGoodsByGoodSIdRequest -Anforderung) {return _goodsapise.getGoodsByGoodsid (Anfrage); } GetGoodsByGoodsidDas von @Requestheader geänderte authToken -Feld kann unter einem Framework wie Prahlerei angezeigt werden.
Nach dem Anruf können Sie den Anforderungsheader entsprechend dem HTTP -Tool sehen. Das Beispiel in diesem Artikel ist authToken (anders als das Token einiger Frameworks):
Hinweis: Viele HTTPCLIENT -Tools unterstützen dynamische Header für Übertragungsanforderungen wie RestTemplate.
2. Filter implementieren
Es gibt drei Methoden in der Filterschnittstelle, nämlich Init, Dofilter und Destory. Wenn Sie den Namen sehen, werden Sie wahrscheinlich ihre Hauptnutzungen kennen. Normalerweise müssen wir nur HTTP -Anforderungen innerhalb der Dofilter -Methode bearbeiten:
Paket com.power.demo.controller.filter; import com.power.demo.common.appconst; import com.power.demo.common.bizresult; import com.power com.power.demo.util.serializeUtil; import org.springframework.bean.factory.annotation Java.io.ioException; @ComponentPublic Class AuthTokenFilter implementiert Filter {@autowired private authTokenService authTokenService; @Override public void init (filterconfig var1) löst ServletException {} @Override public void dofilter aus (ServletRequest Request, ServletResponse -Antwort, Filterchain -Kette) löst eine IOException, ServletException {httpserVletRequest REQ = (httpservace) an; 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 bestanden"); chain.dofilter (Anfrage, Antwort); } else {throw New servleTException (bizResult.getMessage ()); }} @Override public void Destroy () {}} AuthTokenFilterBeachten Sie, dass aus der Perspektive der tatsächlichen Hierarchie die meisten Dinge, die mehr Expressionsschichten verarbeiten, verarbeitet werden. Es wird nicht empfohlen, die Datenzugriffsschicht im Filter direkt zu verwenden. Obwohl ich einen solchen Code in vielen alten antiken Projekten vor ein oder zwei Jahren schon oft gesehen habe und es Präzedenzfälle für das Schreiben im Buch in dem Buch << Frühlingspraktikum >> gibt.
3.. Zertifizierungsdienst
Dies ist die Hauptgeschäftslogik. Der Beispielcode ist nur eine einfache Möglichkeit, Ideen aufzuschreiben, und sollte in Produktionsumgebungen nicht einfach verwendet werden:
paket com.power.demo.service.impl; import com.power.demo.cache.powercacheBuilder; import com.power.demo.common.bizresult; import com.power org.springframework.stereotype.comPonent; import org.springframework / * * Überprüfen Sie, ob das Anfrage -Header -Token legal ist System.out.println ("Tokens Wert ist:" + Token); if (stringutils.isempty (token) == true) {bizResult.setFail ("authToken ist leer"); return bizResult; } // Blacklist bizResult = checkForbidlist (Token) verarbeiten; if (bizResult.getisok () == false) {return bizResult; } // Whitelist bizResult = checkAllowlist (Token) verarbeiten; if (bizResult.getisok () == false) {return bizResult; } String key = string.format ("power.authtokenService.%S", token); //cacheBuilder.set(Key, Token); //cacheBuilder.set(Key, token.touppercase ()); // String, die aus dem Cache = cacheBuilder.get (Schlüssel) existiert; if (stringutils.isempty (existtoken) == true) {bizResult.setFail (string.format ("this authToken:%s", token)); return bizResult; } // Vergleichen Sie, ob das Token der gleiche boolesche isequal = token.equals ist (existiert); if (isequal == false) {bizResult.setfail (string.format ("illegal witHeToken:%s", Token)); return bizResult; } // etwas return bizResult; }} AuthTokenServiceImplSie können sich auf den hier verwendeten Cache -Dienst beziehen, der auch eine Zusammenfassung meiner Erfahrung in der vorherigen Fabrik darstellt.
4. Registerfilter
Es gibt zwei allgemeine Möglichkeiten zum Schreiben:
(1) Verwenden Sie die @Webfilter -Annotation, um den Filter zu identifizieren
@Order (1) @webfilter (urlpatterns = {"/api/v1/gares/*", "/api/v1/userInfo/*"}) public class AuthTokenFilter -Implements Filter {Mit @Webfilter Annotation können Sie auch @Order Annotation in Verbindung mit der @Order -Annotation verwenden. Die @order -Annotation repräsentiert die Reihenfolge der Filterung. Je kleiner der Wert ist, desto mehr führen Sie ihn zuerst aus. Diese Bestellgröße ist genauso nützlich wie die Verarbeitung des Lebenszyklus von HTTP -Anfragen während unseres Programmierungsprozesses. Wenn die Bestellung nicht angegeben ist, wird die Reihenfolge des Filters der Reihenfolge der hinzugefügten Filter entgegengesetzt, und die Implementierung des Filters ist das Verantwortungskettenmuster.
Fügen Sie schließlich die Annotation von @ServletComponentscan zur Startklasse hinzu, um den benutzerdefinierten Filter normal zu verwenden.
(2) Verwenden Sie die Filterregistrierungsbean, um die Filterregistrierung anzupassen
In diesem Artikel wird die zweite Implementierung verwendet, um die benutzerdefinierte Filterregistrierung zu implementieren:
Paket com.power.demo.controller.filter; import com.google.common.collect.lists; org.springframework.context.annotation.configuration; import org.springframework.stereotype.comPonent; import Java.util.list;@configuration@componentpublic class rastFilterconfig {@autowired private authTokenfilter; @Bean public FilterregistrationBean FilterregistrationBean () {FilterregistrationBean RegistrationBean = new FilterregistrationBean (); RegistrierungBean.SetFilter (Filter); // set (fuzzy) Matching url list <string> urlpatterns = lists.newarrayList (); urlpatterns.add ("/api/v1/good/*"); urlpatterns.add ("/api/v1/userInfo/*"); RegistrierungBean.Seturlpatterns (Urlpatterns); RegistrierungBean.Setorder (1); RegistrierungBean.SetEnabled (true); Rückgaberegistrierung; }} RestFilterConfigBitte achten Sie besonders auf Urlmulden. Die Attribut -URLmulden geben das zu filterne URL -Muster an. Dieser Parameter ist für den Filterbereich von großer Bedeutung.
Registrieren Sie den Filter und fügen Sie beim Start des Spring -Starts die Filter -Call -Ketten -Anwendungfilterchain automatisch hinzu, wenn sie eine Bohne mit javax.servlet.Filter erkennt.
Rufen Sie eine API an, um den Effekt auszuprobieren:
Normalerweise passen wir eine Global Unified Exception Management -Verbesserung GlobalExceptionHandler unter Spring Boot an (es unterscheidet sich geringfügig von den oben genannten).
Nach meiner Praxis werden im Filter geworfene Ausnahmen nicht durch die weltweit einzigartige Ausnahmeverwaltung des Managements erfasst und verarbeitet. Dies unterscheidet sich vom Interceptor Inteptor und dem im nächsten Artikel eingeführten benutzerdefinierten AOP -Interceptor.
Zu diesem Zeitpunkt erfolgt ein einfacher Sicherheitsauthentifizierungsdienst, der über den benutzerdefinierten Filter implementiert ist.
3. Custom Interceptor
1. Implementieren Sie den Interceptor
Erben Sie den Schnittstellenhandlerinterzeptor und implementieren Sie den Interceptor. Die Schnittstellenmethoden sind wie folgt:
Vorhandle wird vor der Anfrage ausgeführt
Posthandle ist das Ende der Anfrageausführung
Die Aftercompletion wird nach Abschluss der Ansicht ausgeführt, nachdem die Ansicht abgeschlossen ist
Paket com.power.demo.controller.Interceptor; import com.power.demo.common.appconst; import com.power.demo.common.bizresult; import com.power com.power.demo.util.serializeUtil; import org.springframework.beans.factory.annotation.autowired; javax.servlet.http.httpServletRequest; importieren javax.servlet.http.httpServletResponse;/ * * Authentifizierung token Interceptor * */ @componentpublic class AuthTokenInterceTor -Implements HandlerinterceTor {@autoutive -AuthTokenService -AuthTokenService Authtokenservice -AuthTokenservice; / * * Vor der Anforderung Ausführung ausführen * */ @Override public boolean prehandle (httpServletRequest -Anforderung, httpServletResponse -Antwort, Objekthandler) löst eine Ausnahme aus {boolean Handleresult = false; String token = request.getheader (AppConst.Auth_Token); BizResult <string> bizResult = authTokenService.powerCheck (Token); System.out.println (SerializeUtil.Serialize (bizResult)); Handleresult = bizResult.getIsok (); PowerLogger.info ("Auth Token Interceptor Interceptor Interceptor Interceptor Interceptor Interceptor Interceptor Interceptor Interceptor -Interceptor bestanden"); } else {neue Ausnahme werfen (bizResult.getMessage ()); } return Handleresult; } / * * Die Anforderung beendet die Ausführung * * / @Override public void posthandle (httpServletRequest -Anforderung, httpServletResponse -Antwort, Objekthandler, modelAndView modelandView) löst Ausnahme {} / * * Ausführung nach Ansicht Rendering ab. Handler, Ausnahme ex) löst Ausnahme {}} AuthTokenInterceptor ausIm Beispiel entscheiden wir uns für die Durchführung einer Token -Sicherheitsauthentifizierung, bevor die Anfrage ausgeführt wird.
Der Authentifizierungsdienst ist der im Filter eingeführte Authtokenservice, und die Geschäftslogikschicht wird wiederverwendet.
2. Registrieren Sie den Interceptor
Definieren Sie eine InterceptorConfig -Klasse, die von WebMVCConfigurationsupport ererbt wurde, und das WebMVCConFigurerAdapter ist veraltet.
Inject AuthTokenInterceptor als Bean, die URLs und Filter, die andere Einstellungen Interceptor Intercept haben, sind sehr ähnlich:
Paket com.power.demo.controller.Interceptor; import com.google.common.collect.lists; import org.springframework.context.annotation org.springframework.web.servlet.config.annotation.defaultServletHanderConfigurer; Import org.springframework.web.servlet.config.Annotation.Interceptorregistry; org.springframework.web.servlet.config.annotation.webmvcconFigurationsupport; import Java.util.List;@configuration@componentpublic class InterceptorConFig erweitert webmvcconFigurations -Support {// webmvcconFigurerDepeded -favicon_UrlconFigerDace -Is Outdated private. "/Favicon.ico"; /*** stellte fest, dass der relevante in YML konfigurierte relevante Inhalte, wenn WebMVCConfigurations -Support geerbt wird, ungültig ist. * *@param Registry */@Override public void addResourceHandlers (RessourcenHandlerregistry Registry) {Registry.AddresourceHandler ("/"). AddResourcelocations ("/**"); Registry.AddresourceHandler ("/static/**"). AddResourcelocations ("ClassPath:/static/"); } / *** SERGLET -Verarbeitung konfigurieren* / @Override public void configuredFaultServletHandling (defaultServletHandherConfigurer configure) {configurer.enable (); } @Override public void addInterceptors (InterceptorRegistry Registry) {// set (fuzzy) Matching url list <string> urlpatterns = lists.newarrayList (); urlpatterns.add ("/api/v1/good/*"); urlpatterns.add ("/api/v1/userInfo/*"); Registry.AdDInterceptor (AuthTokenInterceptor ()). Super.AdDInterceptors (Registrierung); } // Schreiben Sie den Interceptor als Bean in die Konfiguration @Bean public AuthTokenInterceptor AuthTokenInterceptor () {return New AuthTokenInterceptor (); }} InterceptorConfigNach dem Beginn der Anwendung können Sie den Effekt des Interceptor -Abfangens sehen, indem Sie die Schnittstelle aufrufen. Global Unified Exception Management GlobalExceptionHandler übernimmt die folgenden Ausnahmen, nachdem sie sie gefangen haben:
Es ist fast dasselbe wie die Hauptfehlermeldung, die vom Filter angezeigt wird, aber die Stapelinformationen sind reicher.
4. Die Differenz zwischen Filter und Interceptor
Die Hauptunterschiede sind wie folgt:
1. Interceptors basieren hauptsächlich auf dem Reflexionsmechanismus von Java, während Filter auf Funktionsanfällen basieren
2. Der Interceptor hängt nicht vom Servlet -Container ab, Filter verlassen sich auf den Servlet -Container
3.. Interceptors können nur an Aktionsanfragen arbeiten, während Filter an fast allen Anfragen arbeiten können.
4. Der Interceptor kann auf das Objekt im Aktionskontext und im Wertstapel zugreifen, der Filter kann jedoch nicht darauf zugreifen.
5. Während des Lebenszyklus einer Aktion kann der Interceptor mehrmals aufgerufen werden, während der Filter nur einmal aufgerufen werden kann, wenn der Container initialisiert wird.
In einigen Artikeln, auf die ich verwiesen habe, sagten, dass "der Interceptor verschiedene Bohnen im IOC -Container erhalten kann, aber der Filter kann nicht. Dies ist sehr wichtig. Einen Dienst in den Interceptor kann die Geschäftslogik aufrufen." Nach der tatsächlichen Überprüfung ist dies falsch.
HINWEIS: Die Auslöserzeit des Filters ist nach dem Container und vor dem Servlet, sodass der Eintragsparameter des Filterdofilters (ServletRequest -Anforderung, ServletResponse -Antwort, Filterchain -Kette) ServletRequest, nicht httpServletRequest ist, da der Filter vor dem Httpservlet liegt. Die folgende Abbildung kann Ihnen ein intuitiveres Verständnis des Ausführungszeitpunkts von Filter und Interceptor vermitteln:
Die von DispatherServlet verabschiedeten Anfragen folgen von der Interceptor -Kette. Benutzerdefinierte Servlet -Anfragen werden nicht abgefangen. Zum Beispiel wird unsere angepasste Servlet -Adresse http: // localhost: 9090/testServlet vom Interceptor nicht abgefangen. Unabhängig davon, zu welchem Servlet es gehört, wird der Filter ausgeführt, solange er den Filterregeln des Filters entspricht.
Gemäß der obigen Analyse ist das Verständnis des Prinzips einfach, selbst ASP.NET -Filter sind gleich.
Problem: Erreichen Sie eine flexiblere Sicherheitsauthentifizierung
Im Java -Web kann über den benutzerdefinierten Filterfilter oder der Interceptor Interceptor eine sichere Authentifizierung spezifischer passender APIs erreicht werden, z.
Wir können uns auf die Frühlingssicherheit beziehen, um durch Annotation + Spel starke Funktionen zu erzielen.
Beispielsweise verwenden wir in ASP.NET häufig die autorisierte Funktion, die zu Klassen hinzugefügt oder auf Methoden angewendet werden kann und die Sicherheitsauthentifizierung dynamischer und flexibler steuern kann.
Wir haben uns nicht für Spring Security entschieden, sodass wir eine flexible Sicherheitszertifizierung ähnlich wie autorisiert implementieren können. Die wichtigste Implementierungstechnologie ist die AOP, mit der wir vertraut sind.
Das Grundwissen über die Erreichung von flexiblerem Abfangen durch AOP -Methode wird in diesem Artikel nicht erwähnt. Weitere Themen zu AOP werden im nächsten Artikel geteilt.
Zusammenfassen
Das obige ist das, was der Herausgeber Ihnen vorgestellt hat. Spring Boot verwendet Filter und Interceptors, um eine einfache und sichere Authentifizierung von REST -Schnittstellen zu erreichen. Ich hoffe, es wird für alle hilfreich sein. Wenn Sie Fragen haben, hinterlassen Sie mir bitte eine Nachricht und der Editor wird allen rechtzeitig antworten. Vielen Dank für Ihre Unterstützung auf der Wulin.com -Website!