在 Spring Boot 3.3.5 中使用 Spring Security 接入 GitHub 社区登录的过程大致与之前的版本相似,但需要根据 Spring Boot 3.x 的新特性稍作调整。以下是具体步骤:
1. 在 GitHub 上创建 OAuth 应用
- 登录 GitHub Developer Settings。
- 在 OAuth Apps 中点击 New OAuth App。
- 填写应用信息:
- Application name:应用名称。
- Homepage URL:应用主页地址。
- Authorization callback URL:通常为
http://localhost:8080/login/oauth2/code/github
。
- 创建完成后,记录下 Client ID 和 Client Secret,稍后在 Spring Security 中使用。
2. 配置 Spring Security OAuth2 Client
.xml
配置
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</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-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity6</artifactId>
</dependency>
在 Spring Boot 3.3.5 中,你可以在 application.yml
或 application.properties
文件中配置 GitHub 的 OAuth Client 信息。
在 application.yml
中配置
spring:
security:
oauth2:
client:
registration:
github:
client-id: YOUR_CLIENT_ID
client-secret: YOUR_CLIENT_SECRET
scope: read:user, user:email
redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}"
authorization-grant-type: authorization_code
# client-authentication-method: basic
client-authentication-method: client_secret_basic
provider:
github:
authorization-uri: https://github.com/login/oauth/authorize
token-uri: https://github.com/login/oauth/access_token
user-info-uri: https://api.github.com/user
user-name-attribute: id
替换
YOUR_CLIENT_ID
和YOUR_CLIENT_SECRET
为 GitHub 中生成的 Client ID 和 Client Secret。
3. 配置 Spring Security
在 Spring Boot 3 中,Spring Security 的默认配置会自动适配 OAuth2 登录,但你仍然可以自定义配置。
自定义 Security 配置类
通过 SecurityFilterChain
配置自定义的安全规则和 OAuth2 登录参数。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(authorize -> authorize
.requestMatchers("/", "/login").permitAll() // 配置访问权限
.anyRequest().authenticated() // 其他请求需要认证
)
.oauth2Login(oauth2 -> oauth2
.loginPage("/login") // 自定义登录页面
.defaultSuccessUrl("/home") // 登录成功后的页面
.failureUrl("/login?error=true") // 登录失败跳转页面
);
http.logout(logout -> logout
.logoutUrl("/logout") // 指定注销路径
.logoutSuccessUrl("/") // 注销后跳转到主页
.invalidateHttpSession(true)
.clearAuthentication(true)
.permitAll() // 允许所有用户访问 /logout
);
// http.logout(logout -> logout.logoutSuccessUrl("/"));;
return http.build();
}
}
4. 创建控制器和视图
控制器类
定义一个简单的控制器,用于处理主页、登录页和成功登录后的主页。
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class HomeController {
@GetMapping("/")
public String index() {
return "index"; // 首页
}
@GetMapping("/login")
public String login() {
return "login"; // 登录页
}
@GetMapping("/home")
public String home() {
return "home"; // 登录成功后的页面
}
}
视图文件
在 src/main/resources/templates
目录下创建以下 Thymeleaf 文件。
- index.html:主页内容
- login.html:自定义登录页面
- home.html:登录成功后的页面
index.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Welcome</title>
</head>
<body>
<h1>Welcome to the GitHub Login Demo</h1>
<a href="/oauth2/authorization/github">Login with GitHub</a>
</body>
</html>
login.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Login</title>
</head>
<body>
<h1>Login</h1>
<a href="/oauth2/authorization/github">Login with GitHub</a>
</body>
</html>
home.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Home</title>
</head>
<body>
<h1>Welcome, <span th:text="${name}">User</span>!</h1>
<p>GitHub Username: <span th:text="${login}"></span></p>
<p>Email: <span th:text="${email}">N/A</span></p>
<div>
<img th:src="${avatar_url}" alt="GitHub Avatar" width="100" height="100" />
</div>
<form th:action="@{/logout}" method="post">
<button type="submit">Logout</button>
</form>
<!--<a th:href="@{/logout}">Logout</a>-->
</body>
</html>
5. 测试 GitHub 登录
- 运行 Spring Boot 应用。
- 访问
http://localhost:8080
,点击 Login with GitHub,会跳转到 GitHub 登录页面。 - 使用 GitHub 账号登录授权后,应用会跳转到
/home
页面,显示登录成功的信息。
6. 自定义用户信息处理(可选)
如需自定义 GitHub 返回的用户信息,可以实现 OAuth2UserService<OAuth2UserRequest, OAuth2User>
接口,解析 GitHub 返回的用户数据。
自定义 OAuth2UserService
实现
import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.core.user.DefaultOAuth2User;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.stereotype.Service;
import java.util.Map;
@Service
public class CustomOAuth2UserService extends DefaultOAuth2UserService {
@Override
public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
OAuth2User user = super.loadUser(userRequest);
// 提取并处理用户信息
Map<String, Object> attributes = user.getAttributes();
return new DefaultOAuth2User(user.getAuthorities(), attributes, "id"); // GitHub 用 'id' 作为用户名属性
}
}
在 上面SecurityConfig
中注入自定义的 OAuth2UserService
:
在 Spring Boot 3.3.5 中使用 Spring Security 接入 GitHub 社区登录并不复杂,主要依赖 OAuth2 协议完成 GitHub 的授权认证,通过简单的配置文件和安全配置即可实现。
GitHub 的 OAuth2 登录流程
在 Spring Boot 中集成 GitHub 的 OAuth2 登录时,大部分认证流程确实由 Spring Security 底层自动处理,开发者无需显式处理具体的认证和令牌交换逻辑。以下是每个配置项的具体作用以及 Spring Security 的处理方式:
在 Spring Security 集成 GitHub 的 OAuth2 登录流程中,这些接口和 URI 之间有以下关系:
1. http://localhost:8080/oauth2/authorization/github
- 作用:这是应用的登录入口 URL,Spring Security 使用这个 URL 来启动 OAuth2 授权流程。
- 触发方式:当用户访问此 URL 时,Spring Security 会将用户重定向到 GitHub 的授权页面,即
authorization-uri
。 - 映射的配置:这个 URL 由
OAuth2LoginConfigurer
生成,自动映射到配置的authorization-uri
,即https://github.com/login/oauth/authorize
。
2. authorization-uri: https://github.com/login/oauth/authorize
- 作用:这是 GitHub 的授权端点,用于请求用户授权访问。
- 触发方式:当用户通过
http://localhost:8080/oauth2/authorization/github
启动登录流程时,Spring Security 会自动重定向到此 URL,向 GitHub 请求用户授权。 - 流程:Spring Security 在构建授权请求时会将
client_id
、redirect_uri
(即{baseUrl}/login/oauth2/code/{registrationId}
)以及scope
等参数添加到此 URL,GitHub 授权完成后会重定向回应用。
3. redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}"
- 作用:这是授权完成后的回调地址(GitHub 授权页面完成授权后会重定向至此 URL)。
- URL 示例:对于 GitHub 的登录流程,该 URL 实际会被解析为
http://localhost:8080/login/oauth2/code/github
,其中{registrationId}
是github
。 - 流程:GitHub 在授权成功后,会附带
code
和state
参数重定向到此 URL。Spring Security 在此处理回调请求,并使用code
向 GitHub 的token-uri
请求访问令牌。
4. token-uri: https://github.com/login/oauth/access_token
- 作用:这是 GitHub 的令牌端点,用于交换访问令牌。
- 流程:Spring Security 在收到 GitHub 回调请求后,会使用授权代码
code
向token-uri
发送请求以获取访问令牌。 - 实现:Spring Security 自动处理令牌请求和响应,无需额外配置或代码。
5. user-info-uri: https://api.github.com/user
- 作用:这是 GitHub 的用户信息端点,用于获取已授权用户的基本信息。
- 流程:Spring Security 在成功获取访问令牌后,会自动向
user-info-uri
发送请求,获取用户的详细信息(如用户名、电子邮件、头像等)。 - 应用:从
user-info-uri
获取的数据会自动映射到OAuth2User
对象中,供应用使用,例如在控制器中通过@AuthenticationPrincipal OAuth2User
注解获取。
整体流程总结
- 用户点击登录:访问
http://localhost:8080/oauth2/authorization/github
,触发 OAuth2 登录流程。 - 重定向到 GitHub 授权页面:Spring Security 将用户重定向到
authorization-uri
(https://github.com/login/oauth/authorize
),用户在 GitHub 授权。 - GitHub 回调:授权完成后,GitHub 重定向到应用的
redirect-uri
(例如http://localhost:8080/login/oauth2/code/github
),附带授权code
。 - 获取访问令牌:Spring Security 使用
code
请求token-uri
(https://github.com/login/oauth/access_token
)来交换访问令牌。 - 获取用户信息:在成功获取令牌后,Spring Security 使用
user-info-uri
(https://api.github.com/user
)获取用户信息,并将信息映射到OAuth2User
对象中。 - 完成登录:用户被重定向到应用的主页或配置的默认成功页面。