文章目录
本文将详细介绍如何使用最新版本的Spring Boot搭建一个基于OAuth2的认证授权服务。我们将使用Spring Security OAuth2来简化构建过程。
一、环境准备
- JDK 1.8或更高版本
- Maven 3.5或更高版本
- Spring Boot 2.6.x(本文使用的是2.6.3版本)
- Spring Security 5.6.x(与Spring Boot版本兼容)
二、创建Spring Boot项目
1. 使用Spring Initializr
访问Spring Initializr,填写以下信息:
- Project: Maven Project
- Language: Java
- Spring Boot: 选择最新版本(本文为2.6.3)
- Group: com.example
- Artifact: oauth2-demo
- Name: oauth2-demo
- Description: Spring Boot OAuth2 Demo
- Packaging: Jar
- Java: 8(或更高版本)
在Dependencies部分,添加以下依赖: - Spring Web
- Spring Security
- Spring Data JPA
- H2 Database (用于演示,实际项目中可以使用MySQL、PostgreSQL等)
- Thymeleaf (用于前端页面展示)
点击Generate按钮,下载生成的项目压缩包,并解压。
2. 使用IDE导入项目
使用IntelliJ IDEA或Eclipse等IDE导入项目。
三、配置数据源
在application.properties
文件中配置H2数据库:
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=password
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.h2.console.enabled=true
四、添加用户实体和存储
创建一个用户实体User.java
:
package com.example.oauth2demo.entity;
import javax.persistence.*;
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String password;
// 省略getter和setter方法
}
创建一个用户存储接口UserRepository.java
:
package com.example.oauth2demo.repository;
import com.example.oauth2demo.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User, Long> {
User findByUsername(String username);
}
五、配置Spring Security
创建一个配置类WebSecurityConfig.java
:
package com.example.oauth2demo.config;
import org.springframework.context.annotation.Bean;
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;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import com.example.oauth2demo.repository.UserRepository;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private final UserRepository userRepository;
public WebSecurityConfig(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(username -> userRepository.findByUsername(username)
.map(user -> new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), new ArrayList<>()))
.orElseThrow(() -> new UsernameNotFoundException("User not found")));
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/home").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
}
六、配置OAuth2
创建一个配置类AuthorizationServerConfig.java
:
package com.example.oauth2demo.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.password.PasswordEncoder;
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.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private PasswordEncoder passwordEncoder;
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.inMemory()
.withClient("client")
.secret(passwordEncoder.encode("secret"))
.authorizedGrantTypes("password", "authorization_code", "refresh_token")
.scopes("read", "write")
.redirectUris("http://localhost:8080/login/oauth2/code/client")
.accessTokenValiditySeconds(3600) // 1 hour
.refreshTokenValiditySeconds(2592000); // 30 days
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
// Configure the endpoints for token generation
endpoints.tokenStore(tokenStore())
.authenticationManager(authenticationManager);
}
// Other necessary bean configurations for token store, etc.
}
接下来,我们需要配置一个令牌存储。在这个例子中,我们将使用内存中的令牌存储,但在生产环境中,你可能会使用JDBC或JWT令牌存储。
@Bean
public TokenStore tokenStore() {
return new InMemoryTokenStore();
}
创建一个配置类ResourceServerConfig.java
来配置资源服务器:
package com.example.oauth2demo.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/api/**").authenticated()
.antMatchers("/").permitAll();
}
}
七、创建控制器
创建一个简单的控制器HomeController.java
:
package com.example.oauth2demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class HomeController {
@GetMapping("/")
public String home() {
return "home";
}
@GetMapping("/login")
public String login() {
return "login";
}
}
创建一个REST控制器ApiController.java
来提供受保护的资源:
package com.example.oauth2demo.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api")
public class ApiController {
@GetMapping("/hello")
public String hello() {
return "Hello, OAuth2!";
}
}
八、创建前端页面
在src/main/resources/templates
目录下创建home.html
和login.html
页面。
home.html
:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Home</title>
</head>
<body>
<h1>Welcome to the Home Page</h1>
<a href="/login">Login</a>
</body>
</html>
login.html
:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Login</title>
</head>
<body>
<form action="/login" method="post">
<div>
<label for="username">Username:</label>
<input type="text" id="username" name="username" required>
</div>
<div>
<label for="password">Password:</label>
<input type="password" id="password" name="password" required>
</div>
<div>
<button type="submit">Login</button>
</div>
</form>
</body>
</html>
九、运行和测试
启动Spring Boot应用,访问http://localhost:8080/
,你应该会看到主页。点击登录链接,你将被重定向到登录页面。
使用Postman或其他API测试工具,你可以尝试获取访问令牌:
- 使用POST请求到
http://localhost:8080/oauth/token
,并附上以下参数:grant_type
:password
username
: 你的用户名password
: 你的密码client_id
:client
client_secret
:secret
获取到访问令牌后,你可以使用它来访问受保护的API资源,例如http://localhost:8080/api/hello
。
十、总结
在这篇博客中,我们成功搭建了一个基于Spring Boot和OAuth2的认证授权服务。我们配置了用户存储、安全配置、OAuth2授权服务器和资源服务器,并创建了一些基本的控制器和前端页面来演示登录和访问受保护资源的过程。
请注意,这只是一个简单的示例,用于演示基本的OAuth2流程。在生产环境中,你需要考虑更多的安全性和配置选项,例如使用JWT令牌、配置数据库、添加错误处理、日志记录等。