Siapkan aplikasi web Spring Boot yang mengotentikasi pengguna melalui Resource Access Management (RAM) Alibaba Cloud menggunakan OAuth 2.0 dan Spring Security.
Prasyarat
Sebelum memulai, pastikan Anda telah memiliki:
Aplikasi OAuth Alibaba Cloud. Untuk informasi lebih lanjut, lihat Mengelola aplikasi OAuth.
Proyek Spring Boot yang telah diinisialisasi dengan Maven.
Java Development Kit (JDK) 1.8 atau versi yang lebih baru.
Langkah 1: Tambahkan dependensi Maven
Tambahkan dependensi berikut ke file pom.xml proyek Spring Boot Anda.
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.18</version>
<relativePath />
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!-- Klien OAuth 2.0 untuk alur login -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<!-- Server sumber daya OAuth 2.0 untuk validasi token -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
<version>3.1.0</version>
</dependency>
<!-- Spring Security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- Framework web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Dukungan pengujian -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- Pustaka frontend -->
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>4.3.1</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>webjars-locator-core</artifactId>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>js-cookie</artifactId>
<version>2.1.0</version>
</dependency>
</dependencies>Jalankan mvn install untuk mengunduh dependensinya.
Langkah 2: Konfigurasikan penyedia OAuth 2.0
Buat file application.yml (atau application.yaml) di direktori src/main/resources. File ini mendaftarkan Alibaba Cloud sebagai penyedia OAuth 2.0 dan mengonfigurasi kredensial klien.
spring:
security:
oauth2:
client:
registration:
alibabacloud:
client-id: <your-client-id>
client-secret: <your-client-secret>
client-authentication-method: client_secret_basic
authorization-grant-type: authorization_code
redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}"
client-name: alibabacloud
provider:
alibabacloud:
authorization-uri: https://signin.alibabacloud.com/oauth2/v1/auth
token-uri: https://oauth.alibabacloud.com/v1/token
user-info-uri: https://oauth.alibabacloud.com/v1/userinfo
user-name-attribute: sub
jwk-set-uri: https://oauth.alibabacloud.com/v1/keysGanti placeholder berikut dengan nilai aktual Anda:
| Placeholder | Deskripsi | Cara menemukannya |
|---|---|---|
<your-client-id> | ID aplikasi dari aplikasi OAuth Anda | Konsol RAM > Integrations > OAuth (Preview) > aplikasi Anda |
<your-client-secret> | Rahasia aplikasi dari aplikasi OAuth Anda | Konsol RAM > Integrations > OAuth (Preview) > aplikasi Anda > tab Application Secret > Create Secret |
Tabel berikut menjelaskan parameter konfigurasi penyedia:
| Parameter | Nilai | Deskripsi |
|---|---|---|
authorization-uri | https://signin.alibabacloud.com/oauth2/v1/auth | Titik akhir otorisasi tempat pengguna diarahkan untuk login |
token-uri | https://oauth.alibabacloud.com/v1/token | Titik akhir yang menukar kode otorisasi menjadi token akses |
user-info-uri | https://oauth.alibabacloud.com/v1/userinfo | Titik akhir yang mengambil profil pengguna terotentikasi |
user-name-attribute | sub | Klaim dalam respons info pengguna yang digunakan sebagai username (identifier subjek) |
jwk-set-uri | https://oauth.alibabacloud.com/v1/keys | Titik akhir set JSON Web Key (JWK) untuk memverifikasi tanda tangan token |
Langkah 3: Tulis konfigurasi keamanan backend
Buat kelas WebApplication yang mengonfigurasi Spring Security dengan login OAuth 2.0, perlindungan cross-site request forgery (CSRF), dan kontrol akses.
Simpan file ini sebagai WebApplication.java di paket sumber utama proyek Anda.
import org.springframework.boot.SpringApplication;
import org.springframework.http.HttpStatus;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.security.web.authentication.AuthenticationEntryPointFailureHandler;
import org.springframework.security.web.authentication.HttpStatusEntryPoint;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
import org.springframework.web.bind.annotation.GetMapping;
import javax.servlet.http.HttpServletRequest;
import java.util.Collections;
import java.util.Map;
public class WebApplication extends WebSecurityConfigurerAdapter {
private AuthenticationEntryPointFailureHandler handler = new AuthenticationEntryPointFailureHandler((request, response, authException) -> response.sendError(401, "Unauthorized"));
@GetMapping("/user")
public Map<String, Object> user(@AuthenticationPrincipal OAuth2User principal) {
return Collections.singletonMap("name", principal.getAttribute("name"));
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests(a -> a
.antMatchers("/", "/error", "/webjars/**").permitAll()
.anyRequest().authenticated()
)
.exceptionHandling(e -> e
.authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED))
)
.oauth2Login(o -> o
.failureHandler((request, response, exception) -> {
request.getSession().setAttribute("error.message", exception.getMessage());
handler.onAuthenticationFailure(request, response, exception);
})
)
.logout(l -> l
.logoutSuccessUrl("/").permitAll()
)
.csrf(c -> c
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
);
}
@GetMapping("/error")
public String error(HttpServletRequest request) {
String message = (String) request.getSession().getAttribute("error.message");
if (message != null) {
request.getSession().removeAttribute("error.message");
}
return message;
}
}Kelas ini menangani hal-hal berikut:
| Komponen | Perilaku |
|---|---|
| Kontrol akses | /, /error, dan /webjars/** mengizinkan akses anonim. Semua path lainnya memerlukan autentikasi. |
| Login OAuth 2.0 | Permintaan tanpa autentikasi ke path yang dilindungi akan dialihkan ke halaman login Alibaba Cloud. Setelah autentikasi berhasil, pengguna dialihkan kembali ke aplikasi. |
| Penanganan kegagalan | Kegagalan autentikasi menyimpan pesan error di session dan mengembalikan HTTP 401. |
| Logout | Mengarahkan pengguna ke /. |
| Perlindungan CSRF | Menggunakan CookieCsrfTokenRepository dengan HttpOnly dinonaktifkan, sehingga JavaScript frontend dapat membaca token CSRF. |
/user endpoint | Mengembalikan nama pengguna terotentikasi dari atribut pengguna OAuth 2.0. |
/error endpoint | Mengembalikan pesan error terbaru dari session dan menghapusnya. |
Langkah 4: Buat halaman frontend
Buat file index.html di direktori src/main/resources/static.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<title>Demo</title>
<meta name="description" content=""/>
<meta name="viewport" content="width=device-width"/>
<base href="/"/>
<link rel="stylesheet" href="/webjars/bootstrap/css/bootstrap.min.css"/>
<script src="/webjars/jquery/jquery.min.js"></script>
<script src="/webjars/bootstrap/js/bootstrap.min.js"></script>
<script src="/webjars/js-cookie/js.cookie.js">
$.ajaxSetup({
beforeSend: function (xhr, settings) {
if (settings.type === 'POST' || settings.type === 'PUT' || settings.type === 'DELETE') {
if (!(/^(http:\/\/|https:\/\/)/.test(settings.url))) {
xhr.setRequestHeader("X-XSRF-TOKEN", Cookies.get('XSRF-TOKEN'));
}
}
}
});
</script>
</head>
<body>
<h1>Demo</h1>
<div class="container text-danger error"></div>
<script>
$.get("/error", function (data) {
if (data) {
$(".error").html(data);
} else {
$(".error").html('');
}
});
</script>
<div class="container unauthenticated">
Dengan Aliyun: <a href="/oauth2/authorization/aliyun">click here</a>
</div>
<div class="container authenticated">
Dengan Google: <a href="/oauth2/authorization/google">click here</a>
</div>
<script type="text/javascript">
$.get("/user", function(data) {
$("#user").html(data.name);
$(".unauthenticated").hide()
$(".authenticated").show()
});
</script>
<div class="container authenticated">
Login sebagai:
<div>
<button onClick="logout()" class="btn btn-primary">Logout</button>
</div>
</div>
<script type="text/javascript">
var logout = function() {
$.post("/logout", function() {
$("#user").html('');
$(".unauthenticated").show();
$(".authenticated").hide();
})
return true;
}
</script>
</body>
</html>Sebelum autentikasi, halaman menampilkan tautan login. Setelah pengguna login melalui OAuth Alibaba Cloud, halaman menampilkan nama pengguna dan tombol Logout. Token CSRF secara otomatis ditambahkan ke permintaan POST, PUT, dan DELETE melalui header X-XSRF-TOKEN.
Langkah 5: Verifikasi integrasi
Jalankan aplikasi Spring Boot:
mvn spring-boot:runBuka
http://localhost:8080di browser. Halaman menampilkan tautan login Alibaba Cloud.Klik tautan login tersebut. Browser akan mengarahkan Anda ke halaman login Alibaba Cloud.
Login dengan Akun Alibaba Cloud Anda. Setelah autentikasi berhasil, browser akan mengarahkan kembali ke aplikasi dan menampilkan nama pengguna Anda.
Klik Logout untuk mengakhiri sesi. Halaman akan kembali ke kondisi awal sebelum login.