spring security oauth2.0 使用GitHub

在 Spring Security 中集成 GitHub 的 OAuth 2.0 登录,可以实现用户通过 GitHub 账号快速认证。以下是完整的分步实现指南和代码示例:


一、前置准备

1. 在 GitHub 注册 OAuth 应用
  1. 访问 GitHub Settings → Developer settings → OAuth Apps
  2. 点击 New OAuth App,填写:
    Application name: 你的应用名称
    Homepage URL: http://localhost:8080(开发环境)
    Authorization callback URL: http://localhost:8080/login/oauth2/code/github
  3. 生成 Client IDClient Secret

二、Spring Boot 项目配置

1. 添加依赖
<!-- Spring Security OAuth2 Client -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
2. 配置 application.yml
spring:
  security:
    oauth2:
      client:
        registration:
          github:
            client-id: your-github-client-id
            client-secret: your-github-client-secret
            scope: user:email, read:user  # 请求的用户权限范围

三、Spring Security 核心配置

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeRequests(authorize -> authorize
                .antMatchers("/", "/login**", "/error**").permitAll()
                .anyRequest().authenticated()
            )
            .oauth2Login(oauth2 -> oauth2
                .loginPage("/login")  // 自定义登录页
                .userInfoEndpoint(userInfo -> userInfo
                    .userService(customOAuth2UserService)  // 自定义用户处理
                )
                .successHandler(loginSuccessHandler())    // 登录成功处理
                .failureHandler(loginFailureHandler())    // 登录失败处理
            )
            .logout(logout -> logout
                .logoutSuccessUrl("/")
                .permitAll()
            );

        return http.build();
    }

    @Autowired
    private CustomOAuth2UserService customOAuth2UserService;

    // 登录成功处理器
    private AuthenticationSuccessHandler loginSuccessHandler() {
        return (request, response, authentication) -> {
            response.sendRedirect("/dashboard");
        };
    }

    // 登录失败处理器
    private AuthenticationFailureHandler loginFailureHandler() {
        return (request, response, exception) -> {
            response.sendRedirect("/login?error=true");
        };
    }
}

四、自定义用户信息处理

@Service
public class CustomOAuth2UserService extends DefaultOAuth2UserService {

    @Override
    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
        OAuth2User oauth2User = super.loadUser(userRequest);

        // 提取 GitHub 用户信息
        String username = oauth2User.getAttribute("login");
        String email = getEmailFromAttributes(oauth2User.getAttributes());
        String name = oauth2User.getAttribute("name");

        // 构建应用内用户模型(可在此处保存用户到数据库)
        return new DefaultOAuth2User(
            Collections.singleton(new SimpleGrantedAuthority("ROLE_USER")),
            oauth2User.getAttributes(),
            "id"  // 对应 GitHub 用户信息的唯一标识字段名
        );
    }

    // 获取用户邮箱(需申请 user:email 权限)
    private String getEmailFromAttributes(Map<String, Object> attributes) {
        List<Map<String, Object>> emails = (List<Map<String, Object>>) attributes.get("email");
        if (emails != null && !emails.isEmpty()) {
            return (String) emails.get(0).get("email");
        }
        return null;
    }
}

五、控制器示例

@Controller
public class LoginController {

    @GetMapping("/dashboard")
    public String dashboard(Model model, @AuthenticationPrincipal OAuth2User user) {
        model.addAttribute("username", user.getAttribute("login"));
        return "dashboard";
    }

    @GetMapping("/login")
    public String loginPage() {
        return "login";
    }
}

六、前端页面示例

1. login.html(Thymeleaf 模板)
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Login</title>
</head>
<body>
    <h2>选择登录方式</h2>
    <a th:href="@{/oauth2/authorization/github}">
        <button>使用 GitHub 登录</button>
    </a>
    
    <div th:if="${param.error}" style="color: red">
        登录失败,请重试!
    </div>
</body>
</html>
2. dashboard.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Dashboard</title>
</head>
<body>
    <h2>欢迎, <span th:text="${username}"></span>!</h2>
    <a href="/logout">退出登录</a>
</body>
</html>

七、高级配置

1. 同时支持多个 OAuth 提供商(如 Google + GitHub)
spring:
  security:
    oauth2:
      client:
        registration:
          github:
            client-id: github-client-id
            client-secret: github-secret
          google:
            client-id: google-client-id
            client-secret: google-secret
            scope: email, profile
2. 自定义授权端点路径
.oauth2Login(oauth2 -> oauth2
    .authorizationEndpoint(authorization -> authorization
        .baseUri("/oauth2/authorize")  // 默认是 /oauth2/authorization/{providerId}
    )
)

八、生产环境注意事项

  1. HTTPS 强制启用
    http.requiresChannel().anyRequest().requiresSecure();
    
  2. 加密敏感信息
    • 将 client-secret 存储在环境变量或 Vault 中
    client-secret: ${GITHUB_CLIENT_SECRET}
    
  3. 优化用户信息存储
    // 在 CustomOAuth2UserService 中将用户保存到数据库
    User user = userRepository.findByGithubId(githubId)
        .orElseGet(() -> userRepository.save(new User(githubId, email)));
    

九、常见问题排查

1. 重定向 URI 不匹配

• 检查 GitHub OAuth App 的 Authorization callback URL 是否与 application.yml 中的配置一致

2. 权限不足

• 确保申请的 scope 正确(如需要用户邮箱需添加 user:email

3. CSRF 错误

• 确保登录表单包含 CSRF Token(Spring Security 默认启用)

<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/>

通过以上配置,您的 Spring Boot 应用即可实现基于 GitHub 的 OAuth 2.0 登录。用户点击 GitHub 登录按钮后,将跳转至 GitHub 授权页面,完成授权后返回应用并访问受保护资源。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值