Leitfaden zur rollenbasierten Zugriffskontrolle und Autorisierung mit Spring Security
Heute werden wir uns ein Beispiel für rollenbasierten Zugriff und Autorisierung mit Spring Security ansehen.
Rollenbasierte Zugriffskontrolle und Autorisierung mit Spring Security
In diesem Beitrag besprechen wir, wie man Rollen in einer Spring Webanwendung definiert, verwendet und verwaltet, wie zum Beispiel „USER“ und „ADMIN“. In diesem Beispiel verwenden wir Spring 4 MVC Security mit einem In-Memory Store und der Spring Java Konfigurationsfunktion, um die Anwendung zu entwickeln. Das bedeutet, dass wir keine web.xml Datei verwenden und auch keine einzige Zeile Spring XML-Konfiguration schreiben werden. Wir werden die Option „In-Memory Store“ verwenden, um Benutzerdaten zu speichern und zu verwalten. Wir verwenden Spring 4.0.2.RELEASE, Spring STS 3.7 Suite IDE, Spring TC Server 3.1 mit Java 1.8 und das Maven Build-Tool, um dieses Beispiel zu entwickeln.
Beispiel zur rollenbasierten Zugriffskontrolle und Autorisierung mit Spring Security
Erstellen Sie ein „Einfaches Spring Web Maven“-Projekt in der Spring STS Suite mit den folgenden Details. Projektname: SpringMVCSecruityMavenRolesApp2.
<artifactId>SpringMVCSecruityMavenRolesApp</artifactId>
<build>
<finalName>SpringMVCSecruityMavenRolesApp</finalName>
</build>
</project>
Aktualisieren Sie die Datei LoginSecurityConfig.java, um Benutzerrollen wie „USER“ und „ADMIN“ zu konfigurieren
LoginSecurityConfig.java
Paket com.journaldev.spring.security.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class LoginSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder authenticationMgr) throws Exception {
authenticationMgr.inMemoryAuthentication()
.withUser("jduser").password("jdu@123").authorities("ROLE_USER")
.and()
.withUser("jdadmin").password("jda@123").authorities("ROLE_USER","ROLE_ADMIN");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/homePage").access("hasRole('ROLE_USER') or hasRole('ROLE_ADMIN')")
.antMatchers("/userPage").access("hasRole('ROLE_USER')")
.antMatchers("/adminPage").access("hasRole('ROLE_ADMIN')")
.and()
.formLogin().loginPage("/loginPage")
.defaultSuccessUrl("/homePage")
.failureUrl("/loginPage?error")
.usernameParameter("username").passwordParameter("password")
.and()
.logout().logoutSuccessUrl("/loginPage?logout");
}
}
Code-Erklärung
In der Methode configureGlobal() haben wir zwei Benutzer hinzugefügt: Einen Benutzer mit der Rolle „ROLE_USER“ und einen weiteren Benutzer mit den Rollen „ROLE_USER“ und „ROLE_ADMIN“. Das bedeutet, dieser zweite Benutzer wird als Admin-Benutzer fungieren. So können wir beliebig viele Benutzer und Rollen konfigurieren.
Wir können entweder die Methoden authorities(ROLE) oder roles(ROLE) verwenden, um Rollen in unserer Anwendung zu konfigurieren.
Unterschied zwischen den Methoden authorities() und roles():
- authorities() benötigt den vollständigen Rollennamen wie „ROLE_USER“
- roles() benötigt den Rollennamen wie „USER“. Es fügt automatisch den Wert „ROLE_“ zu diesem Rollennamen „USER“ hinzu.
In der Methode configure() haben wir verschiedene URLs mit den erforderlichen Zugriffsrollen definiert.
antMatchers(„/homePage“).access(„hasRole(‚ROLE_USER‘) or hasRole(‚ROLE_ADMIN‘)“) Dieser Code-Ausschnitt konfiguriert, dass „/homePage“ für beide Rollen USER und ADMIN verfügbar ist.
.antMatchers(„/userPage“).access(„hasRole(‚ROLE_USER‘)“) .antMatchers(„/adminPage“).access(„hasRole(‚ROLE_ADMIN‘)“) Dieser Code-Ausschnitt konfiguriert, dass „/userPage“ nur von der Rolle „USER“ und „/adminPage“ nur von der Rolle „ADMIN“ zugänglich ist. Wenn andere Rollen auf diese Seiten zugreifen, erhalten wir die Fehlermeldung „403 Zugriff verweigert“.
Aktualisieren Sie die Datei LoginController.java, um neue URL-Zugriffspfade zu definieren
LoginController.java
Paket com.journaldev.spring.web.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class LoginController {
@RequestMapping(value = { "/"}, method = RequestMethod.GET)
public ModelAndView welcomePage() {
ModelAndView model = new ModelAndView();
model.setViewName("welcomePage");
return model;
}
@RequestMapping(value = { "/homePage"}, method = RequestMethod.GET)
public ModelAndView homePage() {
ModelAndView model = new ModelAndView();
model.setViewName("homePage");
return model;
}
@RequestMapping(value = {"/userPage"}, method = RequestMethod.GET)
public ModelAndView userPage() {
ModelAndView model = new ModelAndView();
model.setViewName("userPage");
return model;
}
@RequestMapping(value = {"/adminPage"}, method = RequestMethod.GET)
public ModelAndView adminPage() {
ModelAndView model = new ModelAndView();
model.setViewName("adminPage");
return model;
}
@RequestMapping(value = "/loginPage", method = RequestMethod.GET)
public ModelAndView loginPage(@RequestParam(value = "error",required = false) String error,
@RequestParam(value = "logout", required = false) String logout) {
ModelAndView model = new ModelAndView();
if (error != null) {
model.addObject("error", "Ungültige Anmeldeinformationen bereitgestellt.");
}
if (logout != null) {
model.addObject("message", "Erfolgreich von JournalDEV abgemeldet.");
}
model.setViewName("loginPage");
return model;
}
}
<%@taglib Präfix="c" uri="https://java.sun.com/jsp/jstl/core"%>
<a href="${pageContext.request.contextPath}/userPage">JD User</a> | <a href="${pageContext.request.contextPath}/adminPage">JD Admin</a> | <a href="javascript:document.getElementById('logout').submit()">Abmelden</a>
<h3>Willkommen bei JournalDEV Tutorials</h3>
<ul>
<li>Java 8-Tutorial</li>
<li>Spring-Tutorial</li>
<li>Gradle-Tutorial</li>
<li>BigData-Tutorial</li>
</ul>
<c:url Wert="/logout" var="logoutUrl" />
<form id="logout" action="${logoutUrl}" method="post" >
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
</form>
Hier haben wir drei Menüoptionen im oberen Rahmen hinzugefügt. „Abmelden“ wurde bereits in einem vorherigen Beitrag besprochen. Die zwei neuen Links sind:
- JD User: Zugänglich für beide Rollen „USER“ und „ADMIN“
- JD Admin: Nur zugänglich für die Rolle „ADMIN“
ANMERKUNG: In Echtzeit-Anwendungen zeigen wir nur den Link „JD User“ für die Rolle „USER“ und verbergen den Link „JD Admin“. Um zu testen, ob er von der Rolle „USER“ zugänglich ist oder nicht und auch um die genaue Fehlermeldung zu sehen, haben wir diesen Link nicht versteckt.
Fügen Sie eine neue Datei adminPage.jsp für die Rolle „ADMIN“ hinzu
adminPage.jsp
<%@taglib Präfix="c" uri="https://java.sun.com/jsp/jstl/core"%>
<h3>Willkommen bei JournalDEV Tutorials</h3>
<h3>Admin-Seite</h3>
<c:url Wert="/logout" var="logoutUrl" />
<form id="logout" action="${logoutUrl}" method="post" >
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
</form>
<c:if test="${pageContext.request.userPrincipal.name != null}">
<a href="javascript:document.getElementById('logout').submit()">Abmelden</a>
</c:if>
Fügen Sie eine neue Datei userPage.jsp für die Rolle „USER“ hinzu
userPage.jsp
<%@taglib Präfix="c" uri="https://java.sun.com/jsp/jstl/core"%>
<h3>Willkommen bei JournalDEV Tutorials</h3>
<h3>Benutzerseite</h3>
<c:url Wert="/logout" var="logoutUrl" />
<form id="logout" action="${logoutUrl}" method="post" >
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
</form>
<c:if test="${pageContext.request.userPrincipal.name != null}">
<a href="javascript:document.getElementById('logout').submit()">Abmelden</a>
</c:if>
Wir haben nun die Entwicklung unserer Anwendung abgeschlossen. Es ist an der Zeit, unsere Projektstruktur zu betrachten und die Anwendung zu testen. Die finale Projektstruktur sieht folgendermaßen aus:
Rechtsklicken Sie auf das Projekt in Spring STS IDE und wählen Sie „Run AS >> Run on Server“. Es wird die Standard-Willkommensseite der Anwendung aufgerufen, wie unten gezeigt:
Klicken Sie auf den Link „Login to JournalDEV“. Jetzt sind Sie auf der Anmeldeseite.
Melden Sie sich zuerst mit den Anmeldeinformationen der Rolle „USER“ an: Benutzername: jduser Passwort: jdu@123
Jetzt sehen wir die Anwendungs-Startseite mit 3 Menüoptionen: „JD User“, „JD Admin“ und „Abmelden“. Klicken Sie auf den Link „JD User“. Da wir uns mit den Anmeldeinformationen der Rolle „USER“ angemeldet haben, können wir diesen Link aufrufen, wie unten gezeigt.
Verwenden Sie den Rückwärtspfeil in Spring STS IDE und klicken Sie diesmal auf den Link „JD Admin“.
Da wir uns mit den Anmeldeinformationen der Rolle „USER“ angemeldet haben, können wir diesen Link nicht aufrufen. Deshalb sehen wir diese Fehlermeldung: „403 Zugriff verweigert“.9. Jetzt abmelden und erneut mit den Anmeldeinformationen der Rolle ADMIN anmelden: Benutzername: jdadmin Passwort: jda@123 Diesmal können wir den Link „JD Admin“ erfolgreich aufrufen, wie unten gezeigt.
Testen Sie den Link „Abmelden“, um sich von der Anwendung abzumelden.
Das ist alles über unseren Leitfaden zur rollenbasierten Zugriffsberechtigung und Autorisierung mit Spring Security.