Herkunft
In Standard -RABC müssen die Berechtigungen die dynamische Konfiguration unterstützen, und die Spring Security stellt die Berechtigungen aus, um die Berechtigungen im Code zu vereinbaren. Reale Geschäftsszenarien erfordern normalerweise, dass Rollenzugriffsberechtigungen dynamisch konfiguriert werden, dh die Konfiguration der Zugriffsrollen, die zur Laufzeit URLs entsprechen.
Wie kann man diese Anforderung erfüllen?
Am einfachsten ist es, einen Filter an die Beurteilung des Erlaubniss anzupassen. Dies ist jedoch vom Frühlingssicherheitsrahmen getrennt. Wie kann ich es elegant basierend auf der Frühlingssicherheit implementieren?
Überprüfung der Berechtigung zur Berechtigung zur Erregerin für die Berechtigung von Frühling
Spring Security FilterchainProxy wird als Filter verwendet, um sich im Web zu registrieren. FilterchainProxy enthält mehrere integrierte Filter gleichzeitig. Zunächst müssen wir die verschiedenen in der Frühlingssicherheit eingebauten Filter verstehen:
| Alias | Filterklasse | Namespace -Element oder -attribut |
|---|---|---|
| Channel_filter | Channelprozessingfilter | http/intercept-url@benötigt Kanal |
| Sicherheit_Context_filter | SecurityContextPersistenceFilter | http |
| Concurrent_Session_Filter | ConcurrentSessionFilter | Sitzungsmanagement/Parallelitätskontrolle |
| Header_Filter | HeaderwriterFilter | HTTP/Header |
| Csrf_filter | Csrffilter | http/csrf |
| Logout_filter | Logoutfilter | http/logout |
| X509_filter | X509AuthenticationFilter | http/x509 |
| Pre_auth_filter | AbstractPreauthenticated ProcessingFilter -Unterklassen | N / A |
| Cas_filter | CasAuthenticationFilter | N / A |
| Form_login_filter | UserernamepasswordAuthenticationFilter | HTTP/Form-Login |
| BASIC_AUTH_FILTER | BasicAuthenticationFilter | http/http-basic |
| Servlet_API_SUPPORT_FILTER | SecurityContexTHolderawareRequestFilter | http/@servlet-api-lovision |
| Jaas_api_support_filter | Jaasapiintegrationfilter | http/@Jaas-api-Provision |
| Remember_me_filter | RememberMeauthenticationFilter | http/remin-me |
| Anonymous_filter | AnonymousAuthenticationFilter | http/anonym |
| Session_Management_filter | SessionManagementFilter | Sitzungsmanagement |
| AUCECT_TRANSLATION_FILTER | AUCECTTRANSLATIONFILTER | http |
| Filter_security_interceptor | FiltersecurityInterceptor | http |
| Switch_user_filter | SwitchUserFilter | N / A |
Das Wichtigste ist der Filtersicherheitsinterceptor, der die Hauptauthentifizierungslogik implementiert, und der Kerncode ist hier:
Protected InterceptorStatustoken BeforeInvocation (Objektobjekt) {// Erhalten Sie die Berechtigungen, die erforderlich sind, um auf die URL -Sammlung zuzugreifen <configAttribute> Attribute Authentifizierung authenticated = authenticateIfRequired (); // Authentifizierung über AccessDecisionManager try {this.accessDecisionManager.Docide (authentifiziert, Objekt, Attribute); } catch (AccessDdenEdException AccessDdenEDException) {PubliSheEvent (New AuthorizationFailureEvent (Objekt, Attribute, authentifiziert, AccessDdenException)); AccessDdeniDException werfen; } if (debug) {logger.debug ("Autorisierung erfolgreich"); } if (PublishAuthorizationScessful ");} if (PublishAuthorizationSuccess) {PublishEvent (neuer autorisierter Event (Objekt, Attribute, authentifiziert);} // versuchen, als andere Benutzerauthentifizierung zu laufen. logger.debug ("RunasManager hat das Authentifizierungsobjekt nicht geändert"); SecurityContextHolder.getContext ();Wie aus den oben genannten Erkenntnissen ersichtlich ist, können wir aus zwei Aspekten ausgehen:
Lassen Sie uns sehen, wie es separat implementiert werden kann.
Benutzerdefinierte AccessDecisionManager
Die drei offiziellen AccessDecisionManagers basieren auf AccessDecisionVoter, um die Authentifizierung der Berechtigung zu implementieren. Daher müssen wir nur einen AccessDecisionVoter anpassen.
Die Anpassung implementiert hauptsächlich die AccessDecisionVoter -Schnittstelle. Wir können einen folgenden Rolevoter implementieren:
public class rolebasedvoter implementiert accessDecisionVoter <Object> {@Override public boolean unterstützt (configAttribute -Attribut) {return true; } @Override public int Vote (Authentifizierungsauthentifizierung, Objektobjekt, Sammlung <configAttribute> Attribute) {if (authentication == null) {return access_denied; } int result = access_abstain; Sammlung <? erweitert GrantedAuthority> Behörden = ExtractAuthorities (Authentifizierung); für (configAttribute atricTUT: Attribute) {if (attribute.getAttribute () == null) {Fortsetzung; } if (this.Supports (Attribut)) {result = access_denied; // Versuch, eine übereinstimmende Autorität für (GrantedAuthority Authority: Behörden) {if (Attribute.getAttribute (). Equals (Authority.getAuthority ())) {return access_granted; }}}} Rückgabeergebnis; } Sammlung <? erweitert GrantedAuthority> ExtractAuthorities (Authentifizierungsauthentifizierung) {return authentication.getAuthorities (); } @Override public boolean unterstützt (Klasse clazz) {return true; }}Wie füge ich dynamische Berechtigungen hinzu?
Die Art von Objektobjekte in vote(Authentication authentication, Object object, Collection<ConfigAttribute> attributes) ist FilterInvocation, und Sie können die URL der aktuellen Anforderung über GetRequesturl erhalten:
FilterInvocation fi = (FilterInvocation) Objekt; String url = fi.getRequesturl ();
Daher gibt es hier viel Platz für die Erweiterung. Sie können es dynamisch aus der DB laden und dann die Konfiguration der URL beurteilen.
Wie nutze ich diesen rollenbasiertenVoter? Verwenden Sie die AccessDecisionManager -Methode, um die Konfiguration anzupassen. Wir sollten den offiziellen, einstimmigen Gebäude verwenden und dann den maßgeschneiderten, rollenbasiertenVoter hinzufügen.
@EnableWebecurity @enableGlobalMethodSecurity (prepostEnabled = true, SecuredEnabled = True) öffentliche Klasse SecurityConfiguration erweitert WebSecurityConFigurerAdapter {@Override Protected void configure (httpsecurity http) Ausnahme {htttp. UsernamepasswordAuthenticationFilter.class) .ExceptionHandling () .authenticationEntryPoint (problemsupport) .AccessdeniedHandler (problemsupport) .and () .csrf () .disiable () .headerers () .FrameOptions () .Disable () .-Sessionsely. .and () .AuthorizeRequests () // Custom AccessDecisionManager .AccessDecisionManager (AccessDecisionManager ()) .and () .Apply (SecurityConFigurerAdapter ()); } @Bean öffentlich AccessDeCisionManager AccessDeCisionManager () {list <AccessDecisionVoter <? erweitert Object >> entschlosseneVoter = arrays.aslist (new WebExpressionVoter (), // neuer rolevoter (), neu rollenbasierteVoter (), New AuthenticatedVoter ()); Neue einstimmige zurückgeben (DecisionVoters); }Anpassen von SecurityMetadataSource
Benutzerdefinierte Filterinvocations -DeckungMetadataSource muss nur die Schnittstelle implementieren und Regeln von DB in der Schnittstelle dynamisch laden.
Um die Definitionen im Code wiederzuverwenden, können wir die im Code generierte SecurityMetadataSource übernehmen und die Standard -FilterinvocationSecurityMetadataSource im Konstruktor übergeben.
öffentliche Klasse AppFilterInvocationSecurityMetadataSource implementiert org.springframework.security.web.access.Intercept.FilterInvocationSecurityMetadataSource {Private FilterInvocationSecurityMetaDaTaSource SupermetaDataSource; @Override public collection <configAttribute> getAllConFigAttributes () {return null; } public AppFilterInvocationSecurityMetadataSource (FilterinvocationsCurityMetAdaTaSource Expressions -based FilterinvocationsCurityMetadataSource) {this.superMetadataSource = expressionsbasierte FilterinvocurityMetadataSource; // TODO LOAD -Berechtigungskonfiguration aus der Datenbank} Private Final AntathMatcher AntathMatcher = New AntpathMatcher (); // Hier müssen Sie die private endgültige Karte <String, String> urlrolemap = new HashMap <String, String> () {{put ("/open/**", "Rollen_anonymous") laden; put ("/health", "rollen_anonymous"); put ("/restart", "rollen_admin"); put ("/Demo", "rollen_user"); }}; @Override Public Collection <ConfigAttribute> getAtTributes (Objektobjekt) löst IllegalArgumentException {FilterInvocation fi = (FilterInvocation) -Objekt aus; String url = fi.getRequesturl (); für (map.entry <String, String> Eintrag: urlrolemap.entryset ()) {if (antpathMatcher.match (Entry.getKey (), url)) {return SecurityConfig.Createlist (Entry.getValue ()); }} // Die Standardkonfiguration zurückgeben, die vom Code definiert ist, return SupermetaDataSource.getAttributes (Objekt); } @Override public boolean Supports (Klasse <?> Clazz) {return filterInvocation.class.IsSignableFrom (Clazz); }}Wie benutze ich es? Im Gegensatz zu AccessDecisionManager bietet ExpressionUrlauthorizationConfiger keine festgelegte Methode zum Festlegen der FilterinvocationsCurityMetadataSource von FilterSecurityInterceptor, wie?
Ermitteln Sie eine Erweiterungsmethode mit demObjectPostProcessor, durch das ein Objektpostprozessor angepasst wird, der den FilterSecurityInterceptor -Typ übernimmt, können Sie FilterSecurityInterceptor ändern.
@EnableWebecurity @enableGlobalMethodSecurity (prepostEnabled = true, SecuredEnabled = True) öffentliche Klasse SecurityConfiguration erweitert WebSecurityConFigurerAdapter {@Override Protected void configure (httpsecurity http) Ausnahme {htttp. UsernamepasswordAuthenticationFilter.class) .ExceptionHandling () .authenticationEntryPoint (problemsupport) .AccessdeniedHandler (problemsupport) .and () .csrf () .disiable () .headerers () .FrameOptions () .Disable () .-Sessionsely. .and() .authorizeRequests() // Custom FilterInvocationSecurityMetadataSource .withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() { @Override public <O extends FilterSecurityInterceptor> O postProcess( O fsi) { fSI.SetSecurityMetadataSource (MySecurityMetadataSource (fsi.getSecurityMetadataSource ()); } @Bean public AppFilterInvocationSecurityMetadataSource MySecurityMetadataSource (FilterInvocationSecurityMetadataSource FilterInvocationSecurityMetadataSource) {AppfilterinvocationSecurityMetAdaTaSource SecurityMetAsource = new AppFilterInvocationSecurityMetadataSource (FilterInvocationSecurityMetadataSource); Rückgabe von SecurityMetadataSource;}Zusammenfassung
In diesem Artikel werden zwei Methoden zur Implementierung dynamischer Berechtigungen auf der Grundlage der Frühjahrssicherheit eingeführt. Einer besteht darin, den AccessDecisionManager anzupassen, und das andere ist das Anpassen der FilterinvocationSecurityMetadataSource. Sie können flexibel entsprechend Ihren Anforderungen in den tatsächlichen Projekten auswählen.
Weitere Lektüre:
Frühlingssicherheitsarchitektur und Quellcodeanalyse
Zusammenfassen
Das obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, dass der Inhalt dieses Artikels einen gewissen Referenzwert für das Studium oder die Arbeit eines jeden hat. Wenn Sie Fragen haben, können Sie eine Nachricht zur Kommunikation überlassen. Vielen Dank für Ihre Unterstützung bei Wulin.com.