webentwicklung-frage-antwort-db.com.de

Verwendung von Intercept-URL in der Spring-Sicherheit

Was ist die bevorzugte Methode zum Erstellen von Mustern im intercept-url-Element in der Spring-Sicherheit? Ich erstelle einen Web-Service (RESTful), und ich fordere derzeit, dass alle Benutzer angemeldet sind und die Rolle ROLE_USER haben. Dann werden weitere Einschränkungen durch @PreAuthorize-Anmerkungen auf der Service-Ebene erzwungen. Ist es jedoch üblich, auch mehrere intercept-url-Elemente mit unterschiedlicher Konfiguration hinzuzufügen?

16
LuckyLuke

Ich sollte denken, dass "der bevorzugte Weg" subjektiv ist. Ich hatte <intercept-url>-Elemente in meinem security.xml, habe sie jedoch zugunsten von @RequestMapping-Anmerkungen mit @PreAuthorize auf den Controllern aufgegeben. Es ist eine rein persönliche Präferenz (in meinem Fall), da ich es vorziehen sollte, Dinge in Java statt in XML-Namespaces zu behalten, soweit dies möglich ist.

Sie können eine, die andere oder beide verwenden, und Sie können die Annotation dazu verwenden, das XML zu verbessern. Sie können beispielsweise Folgendes haben:

security.xml :

<intercept-url pattern="/something" access="hasRole('ROLE_USER')"/>

YourController.Java :

@RequestMapping(value="/something/else")
@PreAuthorize("hasRole('ROLE_ADMIN')")
public String getSomethingElseContents(){ return "somethingelse"; }

Wie gesagt, es scheint nur eine Frage der Präferenz zu sein. Der Vorteil der Verwendung des XML-Namespaces besteht darin, dass sich die grundlegenden Zugriffsregeln an einem Ort befinden, leicht lesbar und leicht zu befolgen sind. Die von @PreAuthorize (oder den anderen Anmerkungsvarianten) auferlegten Regeln sind besonders sexy, da Sie darin Ihren eigenen SpEL-Ausdruck aufrufen können und Ihre Erlaubnisentscheidung auf dem Zugriff auf übergebene Parameter oder auf von der Klasse zugreifbare Felder (dh @PreAuthorize("@my.project.package.hasMagicPower(#power.INVISIBILITY)")) oder Kombinationen davon basieren kann diese. Sie können logische und dynamische Berechtigungen anwenden, die ansonsten für die Namespace-Option nicht verfügbar sind.

Natürlich können Sie eine rudimentäre Logik mit 'und', 'oder' und '!' Anwenden. Connectives in SpEL-Ausdrücken im Namespace (und Sie können möglicherweise auf externe Klassenmethoden [boolean] über den @-Bezeichner in der XML zugreifen), aber alles, was in der XML angegeben ist, muss statisch sein.


tl; dr : Persönliche Präferenz ist bevorzugt, aber wenn Sie dynamische Flexibilität bei der Berechtigungsverwaltung wünschen oder benötigen, können Sie haben Annotationen verwenden. Wenn Sie keine dynamische Flexibilität wünschen oder benötigen, haben Sie die Option (und ein solides Argument legt nahe, dass die Namespace-Option in Bezug auf SoC besser ist). Ich ziehe es vor, das Java für die Flexibilität nutzen zu lassen. Wenn ich mein XML einmal eingerichtet habe, möchte ich es zur Hölle gelassen lassen und mich auf Java konzentrieren. Es gibt auch ein etwas überzeugendes Gegenargument für die SoC-Ansicht, nämlich, dass eine ordnungsgemäß konventionelle Java-Anwendung ihre Controller in einfach zu findenden Paketen mit eindeutiger Steuerung nach Namen enthält.


noch tl; dr : Meh. Sechs von einem, ein halbes Dutzend von dem anderen. Ich sage po-tay-to.

18
cabbagery

Die meisten Webanwendungen, die Spring Security verwenden, haben nur ein paar intercept-urls, da sie nur sehr grundlegende Sicherheitsanforderungen haben. Sie müssen über einen nicht authentifizierten Zugriff auf die Bildschirme für Login und Login-Fehler verfügen, und in der Regel einige Aspekte der öffentlichen Website, sodass einige URL-Muster angezeigt werden können. Dann gibt es oft einen Admin-Bereich und alles andere ist ROLE_USER.

Wenn Sie mehr Rollen benötigen, ist es üblich, sie mit URL-Pfadkomponenten der obersten Ebene zu verknüpfen. Dies ist zwar nicht erforderlich, erleichtert jedoch den angemessenen Schutz der Ressourcen. 

<http realm="Contacts Realm" use-expressions="false">
    <intercept-url pattern="/index.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
    <intercept-url pattern="/login.jsp*" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
    <intercept-url pattern="/admin/*" access="ROLE_ADMIN"/>
    <intercept-url pattern="/secret/*" access="ROLE_SECRET"/>
    <intercept-url pattern="/**" access="ROLE_USER,ROLE_ADMIN,ROLE_SECRET"/>
    <http-basic/>
</http>

Sie müssen auf der Grundlage Ihrer Anwendungsfälle entscheiden, ob Personen mehrere Rollen zugewiesen werden sollen. Die Verwaltung in der App ist etwas schwieriger. Daher ist es für die meisten Benutzer mit einfacher Sicherheit so eingerichtet, dass Benutzer genau eine Rolle haben und dann mehreren Rollen den Zugriff auf geschützte Inhalte ermöglichen. Die andere Möglichkeit, dies zu tun, ist natürlich eine Rolle pro URL-Muster und gibt den Leuten mehrere Rollen.

Die Antwort auf Ihre Frage (oder zumindest auf die Frage, die Sie meiner Meinung nach stellen) ist die, dass normalerweise eine Komponente der obersten Ebene pro Rolle zum Schutz aller Ressourcen mit denselben Sicherheitsbeschränkungen erforderlich ist. Natürlich gruppieren Sie auch Funktionen unter diesem Pfadpräfix. Daher hassen manche Leute diese Struktur, und manche Leute ziehen es vor, Anmerkungen im Code zu verwenden. Ich mag meine Sicherheit dort, wo ich sie an einem Ort sehen kann, und kann anhand der URL leicht erkennen, welche Erwartungen an die Sicherheit gestellt werden. 

8
Old Pro

Die Konfiguration von SpringSecurity hängt von der Authentifizierung ab, die Sie für Ihre Anwendung auswählen: Für die Formularauthentifizierung möchten Sie beispielsweise die Anmelde-URL und die Abmelde-Erfolgs-URL ohne Berechtigungen konfigurieren:

<http realm="Contacts Realm">
    <intercept-url pattern="/index.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
    <intercept-url pattern="/login.jsp*" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
    <intercept-url pattern="/**" access="ROLE_USER"/>
    <form-login login-page="/login.jsp" authentication-failure-url="/login.jsp?login_error=1"/>
    <logout logout-success-url="/index.jsp"/>
</http>

Bei der Basisauthentifizierung haben Sie keine Anmelde- und Abmelde-URLs, und die Konfiguration ist einfacher:

<http realm="Contacts Realm">
    <intercept-url pattern="/**" access="ROLE_USER"/>
    <http-basic/>
</http>

Wenn Sie die Standardauthentifizierung auswählen, verwenden Sie das zweite Beispiel.

3
Michael

Ja, es ist durchaus üblich, mehrere Intercept-URL-Muster zu definieren und dann Anmerkungen hinzuzufügen, um bestimmte Ressourcen weiter einzuschränken.

Sie können auch ein Verzeichnis für jede Einschränkung verwenden, damit Sie keine Anmerkungen benötigen. Ex./user/** erfordert ROLE_USER,/admin/** erfordert ROLE_ADMIN usw.

Denken Sie bei der Verwendung einer der beiden Methoden daran, wie sich diese auf Ihre Sicherheit auswirkt, falls Sie einen Fehler machen.

Wenn Sie eine Intercept-URL verwenden, müssen Sie die Zeilen in der richtigen Reihenfolge platzieren. Beispiel:

<intercept-url pattern="/**" access="permitAll"/>
<intercept-url pattern="/user/**" access="hasRole('ROLE_USER')"/>

Funktioniert nicht, da Sie alle Zugriffe in der ersten Zeile erledigen und die Zeilen vertauscht werden müssen. Wenn ein Anfänger an Ihrem Projekt arbeitet und die Zeilen umkehrt, könnte dies ein großes Problem sein.

Wenn Sie Anmerkungen verwenden, können Sie die Anmerkungszeile versehentlich löschen, wodurch eine Sicherheitslücke in Ihrer Anwendung entsteht.

@PreAuthorize("hasRole('ROLE_USER')")

Wenn Sie eine Controller-Klasse zwischen zwei Projekten wiederverwenden und in einem Projekt ROLE_USER für alle Methoden innerhalb des Controllers zulassen möchten, während für das andere Projekt, das den allgemeinen Code verwendet, ROLE_ADMIN erforderlich ist, können Sie dies am einfachsten erreichen Intercept-URL 

Denken Sie also daran, dass @PreAuthorize hart codiert und für Projekte freigegeben ist. Sie können die Klassen erweitern und für jedes Projekt unterschiedliche @PreAuthorize hinzufügen, dies erhöht jedoch die Komplexität.

Ich verwende gerne intercept-url, um einen gesamten Bereich zu sichern, wie/user/**, da die Gefahr besteht, dass eine Anmerkung versehentlich entfernt wird.

Wenn ich einen feinkörnigen Zugriff hinzufügen muss, füge ich der Methode im Controller eine Anmerkung hinzu, die bereits durch intercept-url gesichert ist. Dies geschieht jedoch sehr selten.

2
otterslide

Das Abfangen von URLs kann auf diese Weise erfolgen. Angenommen, Ihre URL-URLs für den Ruhedienst beginnen mit /rest/.

<http auto-config="true" use-expressions="true" access-denied-page="/accessDeniedPageURL">
    <intercept-url pattern="/rest/**" access="hasRole('ROLE_USER')"/>
    <intercept-url pattern="/view/products" access="isFullyAuthenticated()"/>        

    <form-login login-page="/landing" default-target-url="/view/products" authentication-failure-handler-ref="authenticationFailureHandler"/>
    <logout invalidate-session="true" logout-success-url="/landing" delete-cookies="JSESSIONID"/>

    <session-management invalid-session-url="/landing" session-authentication-error-url="/landing?msg=alreadyLogin">
        <concurrency-control max-sessions="1" expired-url="/landing?msg=sessionExpiredDuplicateLogin" error-if-maximum-exceeded="false"/>
    </session-management>    
</http>
2
Jeevan Patil

Spring Security ist im Allgemeinen gut für rollenbasierte Zugriffe. und das war's auch schon. Sie könnten Ihren eigenen ProcessingFilter erstellen, um einige zusätzliche Aufgaben zu erledigen. Ich finde jedoch, dass dies viel Arbeit für wenig Nutzen ist.

Die Alternative besteht darin, Request Interceptors zu verwenden. In mehreren Projekten für RESTful-Dienste, die Spring MVC verwenden, verwende ich Request Interceptors, um einige Authentifizierungen abzuschließen, die über den grundlegenden Rollenzugriff hinausgehen. Dies funktioniert, und meiner Meinung nach macht es die Kette von Ereignissen viel einfacher zu folgen, aber wenn Sie mit Tausenden von Transaktionen pro Minute zu tun haben, kann dies die Anfragen verkürzen.

0
chrsdbll