最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring?Boot3整合OAuth2實(shí)現(xiàn)第三方登錄功能詳細(xì)示例

 更新時(shí)間:2025年06月19日 09:52:26   作者:MenzilBiz  
OAuth是一個(gè)關(guān)于授權(quán)的開放網(wǎng)絡(luò)標(biāo)準(zhǔn),在全世界得到廣泛應(yīng)用,目前的版本是2.0版,這篇文章主要介紹了Spring?Boot3整合OAuth2實(shí)現(xiàn)第三方登錄功能的相關(guān)資料,需要的朋友可以參考下

引言

在當(dāng)今互聯(lián)網(wǎng)應(yīng)用中,第三方登錄已成為提升用戶體驗(yàn)的重要功能。通過(guò)集成OAuth2協(xié)議,我們可以讓用戶使用他們已有的社交媒體賬號(hào)(如GitHub、Google、微信等)快速登錄我們的應(yīng)用,而無(wú)需創(chuàng)建新的賬號(hào)。本文將詳細(xì)介紹如何在Spring Boot 3應(yīng)用中整合OAuth2實(shí)現(xiàn)第三方登錄功能。

準(zhǔn)備工作

在開始之前,請(qǐng)確保你已經(jīng)具備以下條件:

  • JDK 17或更高版本
  • Spring Boot 3.x項(xiàng)目
  • Maven或Gradle構(gòu)建工具
  • 一個(gè)可用的第三方OAuth2服務(wù)提供商賬號(hào)(如GitHub、Google等)

添加依賴

首先,我們需要在項(xiàng)目中添加Spring Security和OAuth2客戶端依賴:

<dependencies>
    <!-- Spring Security -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    
    <!-- OAuth2 Client -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-oauth2-client</artifactId>
    </dependency>
    
    <!-- Web支持 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    
    <!-- Thymeleaf (可選,用于前端展示) -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    
    <!-- Lombok (簡(jiǎn)化代碼) -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>

配置OAuth2客戶端

application.ymlapplication.properties中配置OAuth2客戶端信息。這里以GitHub為例:

spring:
  security:
    oauth2:
      client:
        registration:
          github:
            client-id: your-github-client-id
            client-secret: your-github-client-secret
            scope: user:email,read:user
            redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}"
        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: login

server:
  port: 8080
  servlet:
    context-path: /demo

注意:你需要先在GitHub開發(fā)者設(shè)置中創(chuàng)建OAuth應(yīng)用,獲取client-idclient-secret,并設(shè)置正確的回調(diào)URL。

配置安全策略

創(chuàng)建一個(gè)安全配置類來(lái)定義我們的安全策略:

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .csrf(csrf -> csrf.disable()) // 開發(fā)階段可禁用CSRF
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/", "/login**", "/oauth2/**", "/error**").permitAll()
                .anyRequest().authenticated()
            )
            .oauth2Login(oauth2 -> oauth2
                .loginPage("/login")
                .defaultSuccessUrl("/home", true)
                .userInfoEndpoint(userInfo -> userInfo
                    .userService(customOAuth2UserService())
                )
                .successHandler(authenticationSuccessHandler())
            )
            .logout(logout -> logout
                .logoutSuccessUrl("/").permitAll()
                .deleteCookies("JSESSIONID")
                .invalidateHttpSession(true)
            );
        
        return http.build();
    }

    @Bean
    public OAuth2UserService<OAuth2UserRequest, OAuth2User> customOAuth2UserService() {
        return new CustomOAuth2UserService();
    }

    @Bean
    public AuthenticationSuccessHandler authenticationSuccessHandler() {
        return new CustomAuthenticationSuccessHandler();
    }
}

自定義OAuth2用戶服務(wù)

我們需要?jiǎng)?chuàng)建一個(gè)自定義的OAuth2用戶服務(wù)來(lái)處理用戶信息:

@Slf4j
public class CustomOAuth2UserService extends DefaultOAuth2UserService {

    @Override
    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
        OAuth2User oAuth2User = super.loadUser(userRequest);
        
        String registrationId = userRequest.getClientRegistration().getRegistrationId();
        String accessToken = userRequest.getAccessToken().getTokenValue();
        
        log.info("Registration ID: {}", registrationId);
        log.info("Access Token: {}", accessToken);
        log.info("User Attributes: {}", oAuth2User.getAttributes());
        
        // 根據(jù)不同平臺(tái)處理用戶信息
        Map<String, Object> attributes = new HashMap<>(oAuth2User.getAttributes());
        
        // 添加平臺(tái)標(biāo)識(shí)
        attributes.put("provider", registrationId);
        
        // 標(biāo)準(zhǔn)化用戶信息
        if ("github".equals(registrationId)) {
            attributes.put("email", attributes.get("email") != null ? 
                attributes.get("email") : attributes.get("login") + "@users.noreply.github.com");
        }
        
        return new DefaultOAuth2User(
            Collections.singleton(new SimpleGrantedAuthority("ROLE_USER")),
            attributes,
            userRequest.getClientRegistration()
                .getProviderDetails()
                .getUserInfoEndpoint()
                .getUserNameAttributeName()
        );
    }
}

自定義認(rèn)證成功處理器

創(chuàng)建一個(gè)認(rèn)證成功處理器來(lái)處理登錄成功后的邏輯:

@Slf4j
public class CustomAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, 
                                      HttpServletResponse response,
                                      Authentication authentication) throws IOException {
        
        OAuth2User oauthUser = (OAuth2User) authentication.getPrincipal();
        String provider = (String) oauthUser.getAttribute("provider");
        
        log.info("User logged in from {}: {}", provider, oauthUser.getName());
        
        // 根據(jù)不同的登錄來(lái)源處理不同邏輯
        if ("github".equals(provider)) {
            // GitHub特定處理邏輯
            handleGitHubUser(oauthUser);
        }
        
        // 設(shè)置默認(rèn)跳轉(zhuǎn)路徑
        setDefaultTargetUrl("/home");
        super.onAuthenticationSuccess(request, response, authentication);
    }

    private void handleGitHubUser(OAuth2User oauthUser) {
        // 實(shí)現(xiàn)GitHub用戶的特定處理邏輯
        // 例如保存用戶信息到數(shù)據(jù)庫(kù)等
    }
}

創(chuàng)建控制器

添加一些基本的控制器來(lái)處理頁(yè)面請(qǐng)求:

@Controller
@RequiredArgsConstructor
public class MainController {

    @GetMapping("/")
    public String home() {
        return "index";
    }

    @GetMapping("/login")
    public String login(Model model) {
        model.addAttribute("providers", List.of("github")); // 可以擴(kuò)展更多提供商
        return "login";
    }

    @GetMapping("/home")
    public String userHome(Principal principal, Model model) {
        if (principal instanceof OAuth2User oauthUser) {
            model.addAttribute("username", oauthUser.getAttribute("name"));
            model.addAttribute("avatar", oauthUser.getAttribute("avatar_url"));
            model.addAttribute("provider", oauthUser.getAttribute("provider"));
        } else {
            model.addAttribute("username", principal.getName());
        }
        return "home";
    }
}

創(chuàng)建前端頁(yè)面

創(chuàng)建幾個(gè)簡(jiǎn)單的Thymeleaf模板頁(yè)面:

src/main/resources/templates/login.html:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Login</title>
    <style>
        .oauth-provider {
            display: inline-block;
            margin: 10px;
            padding: 10px 20px;
            background: #f5f5f5;
            border-radius: 5px;
            text-decoration: none;
            color: #333;
        }
        .oauth-provider:hover {
            background: #e5e5e5;
        }
    </style>
</head>
<body>
    <h1>Login with OAuth2</h1>
    <div th:each="provider : ${providers}">
        <a class="oauth-provider" th:href="@{/oauth2/authorization/{provider}(provider=${provider})}" rel="external nofollow" >
            Login with <span th:text="${provider}"></span>
        </a>
    </div>
</body>
</html>

src/main/resources/templates/home.html:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Home</title>
    <style>
        .user-info {
            display: flex;
            align-items: center;
            gap: 20px;
            margin-bottom: 20px;
        }
        .avatar {
            width: 80px;
            height: 80px;
            border-radius: 50%;
        }
    </style>
</head>
<body>
    <div class="user-info" th:if="${avatar}">
        <img class="avatar" th:src="${avatar}" alt="User Avatar"/>
        <div>
            <h1>Welcome, <span th:text="${username}"></span>!</h1>
            <p>Logged in via <span th:text="${provider}"></span></p>
        </div>
    </div>
    
    <div th:unless="${avatar}">
        <h1>Welcome, <span th:text="${username}"></span>!</h1>
    </div>
    
    <form th:action="@{/logout}" method="post">
        <button type="submit">Logout</button>
    </form>
</body>
</html>

測(cè)試應(yīng)用

  • 啟動(dòng)應(yīng)用并訪問http://localhost:8080/demo/login
  • 點(diǎn)擊"Login with GitHub"按鈕
  • 你將被重定向到GitHub進(jìn)行授權(quán)
  • 授權(quán)后,你會(huì)被重定向回應(yīng)用并顯示歡迎信息和用戶頭像

擴(kuò)展功能

  • 多提供商支持:添加Google、Facebook等提供商:

    spring:
      security:
        oauth2:
          client:
            registration:
              google:
                client-id: your-google-client-id
                client-secret: your-google-client-secret
                scope: email,profile
    
  • 用戶信息持久化:創(chuàng)建用戶實(shí)體和Repository:

    @Entity
    @Data
    public class User {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
        private String provider;
        private String providerId;
        private String name;
        private String email;
        private String avatarUrl;
        private LocalDateTime createdAt = LocalDateTime.now();
    }
    
  • JWT集成:結(jié)合OAuth2和JWT實(shí)現(xiàn)無(wú)狀態(tài)認(rèn)證。

常見問題解決

  • 重定向URI不匹配

    • 確保在OAuth提供商后臺(tái)配置的回調(diào)URL與應(yīng)用中的一致
    • 格式通常為:http://localhost:8080/demo/login/oauth2/code/github
  • CSRF問題

    • 生產(chǎn)環(huán)境應(yīng)啟用CSRF保護(hù)
    • 確保表單提交包含CSRF令牌
  • 范圍不足

    • 檢查請(qǐng)求的scope是否正確
    • 某些提供商需要審核才能獲取高級(jí)權(quán)限

總結(jié)

本文詳細(xì)介紹了在Spring Boot 3中整合OAuth2實(shí)現(xiàn)第三方登錄的完整流程。通過(guò)Spring Security的OAuth2客戶端支持,我們可以輕松集成多種第三方登錄提供商。關(guān)鍵點(diǎn)包括:

  • 正確配置OAuth2客戶端信息
  • 自定義用戶服務(wù)處理不同提供商的用戶信息
  • 實(shí)現(xiàn)認(rèn)證成功處理器處理登錄后邏輯
  • 提供友好的用戶界面

你可以在此基礎(chǔ)上擴(kuò)展更多功能,如用戶信息持久化、多提供商支持、JWT集成等。希望這篇文章對(duì)你實(shí)現(xiàn)第三方登錄功能有所幫助!

到此這篇關(guān)于Spring Boot3整合OAuth2實(shí)現(xiàn)第三方登錄功能的文章就介紹到這了,更多相關(guān)SpringBoot3整合OAuth2第三方登錄內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Spring Boot + Mybatis多數(shù)據(jù)源和動(dòng)態(tài)數(shù)據(jù)源配置方法

    Spring Boot + Mybatis多數(shù)據(jù)源和動(dòng)態(tài)數(shù)據(jù)源配置方法

    最近做項(xiàng)目遇到這樣的應(yīng)用場(chǎng)景,項(xiàng)目需要同時(shí)連接兩個(gè)不同的數(shù)據(jù)庫(kù)A, B,并且它們都為主從架構(gòu),一臺(tái)寫庫(kù),多臺(tái)讀庫(kù)。下面小編給大家?guī)?lái)了Spring Boot + Mybatis多數(shù)據(jù)源和動(dòng)態(tài)數(shù)據(jù)源配置方法,需要的朋友參考下吧
    2018-01-01
  • spring boot實(shí)戰(zhàn)之使用JSP的示例

    spring boot實(shí)戰(zhàn)之使用JSP的示例

    本篇文章主要介紹了spring boot實(shí)戰(zhàn)之使用JSP的示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-10-10
  • Java如何判斷字符串中是否包含某個(gè)字符

    Java如何判斷字符串中是否包含某個(gè)字符

    這篇文章主要介紹了Java如何判斷字符串中是否包含某個(gè)字符,可以使用String類的contains()方法,另一種方法使用String類的indexOf方法,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-02-02
  • springboot連接Redis的教程詳解

    springboot連接Redis的教程詳解

    這篇文章主要介紹了springboot連接Redis的教程詳解,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-03-03
  • MyBatis-Plus TypeHander不生效的問題解決

    MyBatis-Plus TypeHander不生效的問題解決

    MyBatis-Plus中使用lambdaUpdate更新JSON字段時(shí),TypeHandler未生效導(dǎo)致數(shù)據(jù)截?cái)噱e(cuò)誤,需手動(dòng)轉(zhuǎn)換或顯式指定typeHandler解決,下面就來(lái)介紹一下該問題的解決
    2025-08-08
  • 深入學(xué)習(xí)SpringCloud之SpringCloud簡(jiǎn)介

    深入學(xué)習(xí)SpringCloud之SpringCloud簡(jiǎn)介

    Spring Cloud是一個(gè)一站式的開發(fā)分布式系統(tǒng)的框架,為開發(fā)者提供了一系列的構(gòu)建分布式系統(tǒng)的工具集,本文給大家介紹springcloud的相關(guān)知識(shí),感興趣的朋友跟隨一起看看吧
    2021-04-04
  • java仿枚舉實(shí)例

    java仿枚舉實(shí)例

    下面小編就為大家?guī)?lái)一篇java仿枚舉實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-08-08
  • Java Tree結(jié)構(gòu)數(shù)據(jù)中查找匹配節(jié)點(diǎn)方式

    Java Tree結(jié)構(gòu)數(shù)據(jù)中查找匹配節(jié)點(diǎn)方式

    這篇文章主要介紹了Java Tree結(jié)構(gòu)數(shù)據(jù)中查找匹配節(jié)點(diǎn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-09-09
  • 判斷List和Map是否相等并合并List中相同的Map

    判斷List和Map是否相等并合并List中相同的Map

    今天小編就為大家分享一篇關(guān)于判斷List和Map是否相等并合并List中相同的Map,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2018-12-12
  • JAVA 中Spring的@Async用法總結(jié)

    JAVA 中Spring的@Async用法總結(jié)

    這篇文章主要介紹了JAVA 中Spring的@Async用法總結(jié)的相關(guān)資料,需要的朋友可以參考下
    2017-03-03

最新評(píng)論

绥化市| 黄大仙区| 长沙市| 泽州县| 周宁县| 那坡县| 双城市| 库伦旗| 西青区| 海晏县| 胶州市| 湘乡市| 玛曲县| 宁乡县| 石台县| 临沧市| 河间市| 民权县| 进贤县| 新平| 广元市| 孝义市| 新乡市| 南阳市| 峨边| 武川县| 龙门县| 石屏县| 凤庆县| 华容县| 固始县| 德安县| 房山区| 高平市| 元朗区| 和平县| 天祝| 宝鸡市| 山阴县| 长丰县| 普格县|