Gruß, Freunde! Morgen beginnen die ersten Klassen im neuen Thread des Kurses
"Developer on Spring Framework" . In diesem Zusammenhang teilen wir traditionell nützliches Material zu diesem Thema.

In diesem Artikel werden wir die Verwendung von OAuth2 und JWT in Verbindung mit Spring Boot und Spring Security untersuchen.
Autorisierungsserver
Ein Autorisierungsserver ist die wichtigste Komponente in der Web-API-Sicherheitsarchitektur. Der Autorisierungsserver fungiert als einzelner Autorisierungspunkt und ermöglicht Ihren Anwendungen und HTTP-Endpunkten, die Funktionen Ihrer Anwendung zu definieren.
Ressourcenserver
Der Autorisierungsserver stellt Clients ein Zugriffstoken für den Zugriff auf die HTTP-Endpunkte des Ressourcenservers zur Verfügung. Ein Ressourcenserver ist eine Sammlung von Bibliotheken, die HTTP-Endpunkte, statische Ressourcen und dynamische Webseiten enthalten.
OAuth2
OAuth2 ist ein Autorisierungsprotokoll, mit dem ein Client (Dritter) auf die Ressourcen Ihrer Anwendung zugreifen kann. Um eine OAuth2-Anwendung zu erstellen, müssen wir den Grant-Typ (Autorisierungscode), die Client-ID und das Client-Geheimnis kennen.
JWT-Token
Ein JWT-Token ist ein JSON-Web-Token. Es wird verwendet, um sichere Identifikationsinformationen (Ansprüche) zwischen zwei Parteien darzustellen. Weitere Informationen zu JWT-Token finden Sie unter
www.jwt.io.Wir werden eine OAuth2-Anwendung mit JWT-Token erstellen, die einen Autorisierungsserver und einen Ressourcenserver enthält.
Zuerst müssen wir die Abhängigkeiten zu unserer Build-Datei hinzufügen.
Maven-Benutzer können
pom.xml
die folgenden Abhängigkeiten hinzufügen.
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.security.oauth</groupId> <artifactId>spring-security-oauth2</artifactId> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-jwt</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-test</artifactId> <scope>test</scope> </dependency>
Anmerkung des Übersetzers - Für Java, das älter als 9 Jahre ist, müssen Sie außerdem die folgenden Abhängigkeiten hinzufügen: <dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> <version>2.3.0</version> </dependency> <dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-impl</artifactId> <version>2.2.11</version> </dependency> <dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-core</artifactId> <version>2.2.11</version> </dependency>
Gradle-Benutzer können der Datei
build.gradle
die folgenden Abhängigkeiten
build.gradle
.
compile('org.springframework.boot:spring-boot-starter-security') compile('org.springframework.boot:spring-boot-starter-web') testCompile('org.springframework.boot:spring-boot-starter-test') testCompile('org.springframework.security:spring-security-test') compile("org.springframework.security.oauth:spring-security-oauth2") compile('org.springframework.security:spring-security-jwt') compile("org.springframework.boot:spring-boot-starter-jdbc") compile("com.h2database:h2:1.4.191")
wo
- Spring Boot Starter Security - implementiert Spring Security
- Spring Security OAuth2 - implementiert OAUTH2-Strukturen für den Betrieb des Autorisierungsservers und des Ressourcenservers.
- Spring Security JWT - Generiert JWT-Token
- Spring Boot Starter JDBC - Datenbankzugriff zur Benutzerüberprüfung.
- Spring Boot Starter Web - Stellt HTTP-Endpunkte bereit.
- H2-Datenbank - speichert Benutzerinformationen zur Authentifizierung und Autorisierung.
Die vollständige Datei
pom.xml
unten angezeigt.
<?xml version = "1.0" encoding = "UTF-8"?> <project xmlns = "http://maven.apache.org/POM/4.0.0" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.tutorialspoint</groupId> <artifactId>websecurityapp</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>websecurityapp</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.9.RELEASE</version> <relativePath /> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.security.oauth</groupId> <artifactId>spring-security-oauth2</artifactId> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-jwt</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
Gradle — build.gradle
buildscript { ext { springBootVersion = '1.5.9.RELEASE' } repositories { mavenCentral() } dependencies { classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") } } apply plugin: 'java' apply plugin: 'eclipse' apply plugin: 'org.springframework.boot' group = 'com.tutorialspoint' version = '0.0.1-SNAPSHOT' sourceCompatibility = 1.8 repositories { mavenCentral() } dependencies { compile('org.springframework.boot:spring-boot-starter-security') compile('org.springframework.boot:spring-boot-starter-web') testCompile('org.springframework.boot:spring-boot-starter-test') testCompile('org.springframework.security:spring-security-test') compile("org.springframework.security.oauth:spring-security-oauth2") compile('org.springframework.security:spring-security-jwt') compile("org.springframework.boot:spring-boot-starter-jdbc") compile("com.h2database:h2:1.4.191") }
@EnableAuthorizationServer
@EnableResourceServer
jetzt in der Hauptanwendungsdatei von Spring Boot die Anmerkungen
@EnableAuthorizationServer
und
@EnableResourceServer
damit die Anwendung sowohl als Autorisierungsserver als auch als Ressourcenserver fungiert.
Fügen Sie außerdem einen einfachen HTTP-Endpunkt (/ products) hinzu, um mithilfe eines JWT-Tokens auf die durch Spring Security geschützte API zuzugreifen.
package com.tutorialspoint.websecurityapp; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @SpringBootApplication @EnableAuthorizationServer @EnableResourceServer @RestController public class WebsecurityappApplication { public static void main(String[] args) { SpringApplication.run(WebsecurityappApplication.class, args); } @RequestMapping(value = "/products") public String getProductName() { return "Honey"; } }
Definieren Sie eine POJO-Klasse zum Speichern von Benutzerauthentifizierungsinformationen.
package com.tutorialspoint.websecurityapp; import java.util.ArrayList; import java.util.Collection; import org.springframework.security.core.GrantedAuthority; public class UserEntity { private String username; private String password; private Collection<GrantedAuthority> grantedAuthoritiesList = new ArrayList<>(); public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Collection<GrantedAuthority> getGrantedAuthoritiesList() { return grantedAuthoritiesList; } public void setGrantedAuthoritiesList(Collection<GrantedAuthority> grantedAuthoritiesList) { this.grantedAuthoritiesList = grantedAuthoritiesList; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } }
Fügen Sie als Nächstes zur Authentifizierung die CustomUser-Klasse hinzu, die
org.springframework.security.core.userdetails.User
.
package com.tutorialspoint.websecurityapp; import org.springframework.security.core.userdetails.User; public class CustomUser extends User { private static final long serialVersionUID = 1L; public CustomUser(UserEntity user) { super(user.getUsername(), user.getPassword(), user.getGrantedAuthoritiesList()); } }
Erstellen Sie eine
@Repository-
, um Benutzerinformationen aus der Datenbank abzurufen und die Berechtigungen ROLE_SYSTEMADMIN hinzuzufügen. Diese Klasse wird auch in
CustomDetailsService
.
package com.tutorialspoint.websecurityapp; import java.sql.ResultSet; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.stereotype.Repository; @Repository public class OAuthDao { @Autowired private JdbcTemplate jdbcTemplate; public UserEntity getUserDetails(String username) { Collection<GrantedAuthority> grantedAuthoritiesList = new ArrayList<>(); String userSQLQuery = "SELECT * FROM USERS WHERE USERNAME=?"; List<UserEntity> list = jdbcTemplate.query(userSQLQuery, new String[] { username }, (ResultSet rs, int rowNum) -> { UserEntity user = new UserEntity(); user.setUsername(username); user.setPassword(rs.getString("PASSWORD")); return user; }); if (list.size() > 0) { GrantedAuthority grantedAuthority = new SimpleGrantedAuthority("ROLE_SYSTEMADMIN"); grantedAuthoritiesList.add(grantedAuthority); list.get(0).setGrantedAuthoritiesList(grantedAuthoritiesList); return list.get(0); } return null; } }
Um ein DAO-Repository
UserDetailsService
, können Sie Ihren
UserDetailsService
erstellen, der von
org.springframework.security.core.userdetails.UserDetailsService
(siehe unten).
package com.tutorialspoint.websecurityapp; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; @Service public class CustomDetailsService implements UserDetailsService { @Autowired OAuthDao oauthDao; @Override public CustomUser loadUserByUsername(final String username) throws UsernameNotFoundException { UserEntity userEntity = null; try { userEntity = oauthDao.getUserDetails(username); CustomUser customUser = new CustomUser(userEntity); return customUser; } catch (Exception e) { e.printStackTrace(); throw new UsernameNotFoundException("User " + username + " was not found in the database"); } } }
Erstellen Sie als Nächstes eine
@onfiguration-
, um
Web Security
zu aktivieren. Definieren Sie darin Kennwortverschlüsselungsparameter (
BCryptPasswordEncoder
) und die
AuthenticationManager
Bean.
Diese
SecurityConfiguration
Klasse muss von der
WebSecurityConfigurerAdapter
Klasse erben.
package com.tutorialspoint.websecurityapp; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; @Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Autowired private CustomDetailsService customDetailsService; @Bean public PasswordEncoder encoder() { return new BCryptPasswordEncoder(); } @Override @Autowired protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(customDetailsService).passwordEncoder(encoder()); } @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests().anyRequest().authenticated().and().sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.NEVER); } @Override public void configure(WebSecurity web) throws Exception { web.ignoring(); } @Override @Bean public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } }
Fügen Sie nun eine Klasse hinzu, um OAuth2 zu konfigurieren. Definieren Sie darin die Client-ID, das Client-Geheimnis, den JwtAccessTokenConverter sowie private und öffentliche Schlüssel zum Signieren und Überprüfen des Tokens und konfigurieren Sie
ClientDetailsServiceConfigurer
für gültige Token-Bereiche.
package com.tutorialspoint.websecurityapp; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; import org.springframework.security.oauth2.provider.token.store.JwtTokenStore; @Configuration public class OAuth2Config extends AuthorizationServerConfigurerAdapter { private String clientid = "tutorialspoint"; private String clientSecret = "my-secret-key"; private String privateKey = "private key"; private String publicKey = "public key"; @Autowired @Qualifier("authenticationManagerBean") private AuthenticationManager authenticationManager; @Bean public JwtAccessTokenConverter tokenEnhancer() { JwtAccessTokenConverter converter = new JwtAccessTokenConverter(); converter.setSigningKey(privateKey); converter.setVerifierKey(publicKey); return converter; } @Bean public JwtTokenStore tokenStore() { return new JwtTokenStore(tokenEnhancer()); } @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints.authenticationManager(authenticationManager).tokenStore(tokenStore()) .accessTokenConverter(tokenEnhancer()); } @Override public void configure(AuthorizationServerSecurityConfigurer security) throws Exception { security.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()"); } @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.inMemory().withClient(clientid).secret(clientSecret).scopes("read", "write") .authorizedGrantTypes("password", "refresh_token").accessTokenValiditySeconds(20000) .refreshTokenValiditySeconds(20000); } }
Erstellen Sie nun den privaten und öffentlichen Schlüssel mit
openssl
.
Um einen privaten Schlüssel zu generieren, können Sie die folgenden Befehle verwenden:
openssl genrsa -out jwt.pem 2048 openssl rsa -in jwt.pem
Für öffentlichen Schlüssel -
openssl rsa -in jwt.pem -pubout
Fügen Sie für Spring Boot, das älter als Version 1.5 ist, der Datei
application.properties
die folgende Eigenschaft hinzu (um die Filterreihenfolge der OAuth2-Ressourcen zu bestimmen).
security.oauth2.resource.filter-order=3
Wenn Sie eine YAML-Datei verwenden, fügen Sie Folgendes hinzu.
security: oauth2: resource: filter-order: 3
Erstellen
schema.sql
data.sql
schema.sql
und
data.sql
im
classpath
im
src/main/resources/directory
, um die Anwendung mit der H2-Datenbank zu verbinden.
Die Datei
schema.sql
sieht folgendermaßen aus:
CREATE TABLE USERS (ID INT PRIMARY KEY, USERNAME VARCHAR(45), PASSWORD VARCHAR(60)); data.sql: INSERT INTO USERS (ID, USERNAME,PASSWORD) VALUES ( 1, 'tutorialspoint@gmail.com','$2a$08$fL7u5xcvsZl78su29x1ti.dxI.9rYO8t0q5wk2ROJ.1cdR53bmaVG'); INSERT INTO USERS (ID, USERNAME,PASSWORD) VALUES ( 2, 'myemail@gmail.com','$2a$08$fL7u5xcvsZl78su29x1ti.dxI.9rYO8t0q5wk2ROJ.1cdR53bmaVG');
Hinweis - Das Kennwort in der Datenbanktabelle muss im Bcrypt Encoder-Format gespeichert sein.
Sie können eine ausführbare JAR-Datei erstellen und die Spring Boot-Anwendung mit den folgenden Maven- oder Gradle-Befehlen ausführen.
Für Maven können Sie den folgenden Befehl verwenden:
mvn clean install
Nach "BUILD SUCCESS" finden Sie die JAR-Dateien im
target
.
Für Gradle können Sie den Befehl verwenden -
gradle clean build
Nach "BUILD SUCCESSFUL" finden Sie die JAR-Dateien im Verzeichnis
build/libs
.
Führen Sie nun die JAR-Datei mit dem Befehl - aus.
java –jar <
JARFILE
>
Die Anwendung wurde in Tomcat auf Port 8080 gestartet.

Senden Sie nun eine POST-Anfrage über POSTMAN, um ein OAUTH2-Token zu erhalten.
http://localhost:8080/oauth/token
Fügen Sie nun die Anforderungsheader hinzu -
- Autorisierung - Grundlegend mit Ihrer Kunden-ID und Ihrem Kundengeheimnis.
- Inhaltstyp - application / x-www-form-urlencoded

Und Parameter anfordern -
- grant_type = Passwort
- Benutzername = Ihr Name
- Passwort = Ihr Passwort

Führen Sie nun aus und erhalten Sie
access_token
wie gezeigt.

Erstellen Sie nun eine Anforderung an die Ressourcenserver-API mit einem Bearer-Token im Header.

Wir erhalten das Ergebnis wie unten gezeigt.

Wir warten auf Ihre Kommentare und informieren Sie darüber, dass Sie bis zum 31. Mai zum Sonderpreis am Kurs teilnehmen können.