Salam, teman-teman! Besok akan memulai kelas pertama di utas baru kursus
"Developer on Spring Framework" . Dalam hal ini, kami secara tradisional membagikan materi yang bermanfaat tentang topik tersebut.

Pada artikel ini, kita akan mengeksplorasi penggunaan OAuth2 dan JWT dalam hubungannya dengan Spring Boot dan Spring Security.
Server Otorisasi
Server Otorisasi adalah komponen paling penting dalam arsitektur keamanan API Web. Server otorisasi bertindak sebagai titik otorisasi tunggal dan memungkinkan aplikasi dan titik akhir HTTP Anda untuk menentukan fungsi aplikasi Anda.
Server Sumber Daya
Server otorisasi memberi klien token akses untuk mengakses HTTP Endpoints dari Resource Server. Server sumber daya adalah kumpulan perpustakaan yang berisi HTTP Endpoints, sumber daya statis, dan halaman web dinamis.
OAuth2
OAuth2 adalah protokol otorisasi yang memungkinkan klien (pihak ketiga) untuk mengakses sumber daya aplikasi Anda. Untuk membangun aplikasi OAuth2, kita perlu mengetahui Jenis Hibah (kode otorisasi), ID Klien dan rahasia Klien.
Token JWT
Token JWT adalah Token Web JSON. Ini digunakan untuk mewakili informasi identifikasi (klaim) aman antara dua pihak. Anda dapat menemukan informasi lebih lanjut tentang token JWT di
www.jwt.io.Kami akan membuat aplikasi OAuth2 menggunakan token JWT, yang akan mencakup server otorisasi dan server sumber daya.
Pertama, kita perlu menambahkan dependensi ke file build kita.
Pengguna Maven dapat menambahkan dependensi berikut ke
pom.xml
.
<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>
Catatan Penerjemah - untuk java yang lebih dari 9, Anda juga harus menambahkan dependensi berikut: <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>
Pengguna Gradle dapat menambahkan dependensi berikut ke file
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")
dimana
- Spring Boot Starter Security - mengimplementasikan Spring Security
- Spring Security OAuth2 - mengimplementasikan struktur OAUTH2 untuk pengoperasian server otorisasi dan server sumber daya.
- Spring Security JWT - Menghasilkan Token JWT
- Spring Boot Starter JDBC - akses basis data untuk verifikasi pengguna.
- Spring Boot Starter Web - Menyediakan HTTP Endpoints.
- H2 Database - menyimpan informasi pengguna untuk otentikasi dan otorisasi.
File
pom.xml
lengkap ditunjukkan di bawah ini.
<?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") }
Sekarang, tambahkan anotasi
@EnableResourceServer
dan
@EnableResourceServer
ke file aplikasi Spring Boot utama sehingga aplikasi berfungsi baik sebagai server otorisasi dan server sumber daya.
Juga tambahkan HTTP Endpoint sederhana (/ produk) untuk mengakses API yang dilindungi Spring Security menggunakan token JWT.
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"; } }
Tentukan kelas POJO untuk menyimpan informasi otentikasi pengguna.
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; } }
Selanjutnya, untuk otentikasi, tambahkan kelas CustomUser, yang memperluas
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()); } }
Buat
@Repository-
untuk mengambil informasi pengguna dari database dan menambahkan hak istimewa ROLE_SYSTEMADMIN. Kelas ini juga akan digunakan di
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; } }
Untuk memanggil repositori DAO, Anda dapat membuat
UserDetailsService
Anda, mewarisi dari
org.springframework.security.core.userdetails.UserDetailsService
, seperti yang ditunjukkan di bawah ini.
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"); } } }
Selanjutnya, buat
@onfiguration-
untuk mengaktifkan
Web Security
. Tentukan parameter enkripsi kata sandi (
BCryptPasswordEncoder
) dan kacang
AuthenticationManager
di dalamnya.
Kelas
SecurityConfiguration
ini harus diwarisi dari kelas
WebSecurityConfigurerAdapter
.
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(); } }
Sekarang tambahkan kelas untuk mengkonfigurasi OAuth2. Di dalamnya, tentukan ID Klien, Rahasia Klien, JwtAccessTokenConverter, kunci pribadi dan publik untuk menandatangani dan memverifikasi token, dan konfigurasikan
ClientDetailsServiceConfigurer
untuk cakupan token yang valid.
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); } }
Sekarang buat kunci pribadi dan publik menggunakan
openssl
.
Untuk menghasilkan kunci pribadi, Anda dapat menggunakan perintah berikut -
openssl genrsa -out jwt.pem 2048 openssl rsa -in jwt.pem
Untuk kunci publik -
openssl rsa -in jwt.pem -pubout
Untuk Spring Boot yang lebih lama dari versi 1.5, tambahkan properti berikut ke file
application.properties
(untuk menentukan urutan penyaringan sumber daya OAuth2).
security.oauth2.resource.filter-order=3
Jika Anda menggunakan file YAML, tambahkan berikut ini.
security: oauth2: resource: filter-order: 3
Sekarang buat
schema.sql
dan
data.sql
di
classpath
di
src/main/resources/directory
untuk menghubungkan aplikasi ke database H2.
File
schema.sql
terlihat seperti ini:
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');
Catatan - Kata sandi dalam tabel database harus disimpan dalam format Bcrypt Encoder.
Anda dapat membuat file JAR yang dapat dieksekusi dan menjalankan aplikasi Boot Spring menggunakan perintah Maven atau Gradle berikut.
Untuk Maven, Anda dapat menggunakan perintah di bawah ini -
mvn clean install
Setelah "BUILD SUCCESS" Anda dapat menemukan file JAR di direktori
target
.
Untuk Gradle, Anda dapat menggunakan perintah -
gradle clean build
Setelah “BUILD SUCCESSFUL” Anda dapat menemukan file JAR di direktori
build/libs
.
Sekarang jalankan file JAR dengan perintah -
java –jar <
JARFILE
>
Aplikasi diluncurkan di Tomcat pada port 8080.

Sekarang kirim permintaan POST melalui POSTMAN untuk menerima token OAUTH2.
http://localhost:8080/oauth/token
Sekarang tambahkan header permintaan -
- Otorisasi - Dasar dengan ID Klien Anda dan rahasia Klien.
- Content-Type - application / x-www-form-urlencoded

Dan parameter permintaan -
- grant_type = kata sandi
- username = nama Anda
- kata sandi = kata sandi Anda

Sekarang jalankan dan dapatkan
access_token
seperti yang ditunjukkan.

Sekarang buat permintaan ke server sumber daya API dengan token Bearer di header.

Kami mendapatkan hasilnya seperti yang ditunjukkan di bawah ini.

Kami menunggu komentar Anda, dan kami juga memberi tahu Anda bahwa hingga 31 Mei Anda dapat
bergabung dengan kursus dengan harga khusus.