当前位置: 代码网 > it编程>编程语言>Java > Spring Boot3整合OAuth2实现第三方登录功能详细示例

Spring Boot3整合OAuth2实现第三方登录功能详细示例

2025年06月19日 Java 我要评论
引言在当今互联网应用中,第三方登录已成为提升用户体验的重要功能。通过集成oauth2协议,我们可以让用户使用他们已有的社交媒体账号(如github、google、微信等)快速登录我们的应用,而无需创建

引言

在当今互联网应用中,第三方登录已成为提升用户体验的重要功能。通过集成oauth2协议,我们可以让用户使用他们已有的社交媒体账号(如github、google、微信等)快速登录我们的应用,而无需创建新的账号。本文将详细介绍如何在spring boot 3应用中整合oauth2实现第三方登录功能。

准备工作

在开始之前,请确保你已经具备以下条件:

  • jdk 17或更高版本
  • spring boot 3.x项目
  • maven或gradle构建工具
  • 一个可用的第三方oauth2服务提供商账号(如github、google等)

添加依赖

首先,我们需要在项目中添加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 (简化代码) -->
    <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开发者设置中创建oauth应用,获取client-idclient-secret,并设置正确的回调url。

配置安全策略

创建一个安全配置类来定义我们的安全策略:

@configuration
@enablewebsecurity
public class securityconfig {

    @bean
    public securityfilterchain securityfilterchain(httpsecurity http) throws exception {
        http
            .csrf(csrf -> csrf.disable()) // 开发阶段可禁用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用户服务

我们需要创建一个自定义的oauth2用户服务来处理用户信息:

@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());
        
        // 根据不同平台处理用户信息
        map<string, object> attributes = new hashmap<>(oauth2user.getattributes());
        
        // 添加平台标识
        attributes.put("provider", registrationid);
        
        // 标准化用户信息
        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()
        );
    }
}

自定义认证成功处理器

创建一个认证成功处理器来处理登录成功后的逻辑:

@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());
        
        // 根据不同的登录来源处理不同逻辑
        if ("github".equals(provider)) {
            // github特定处理逻辑
            handlegithubuser(oauthuser);
        }
        
        // 设置默认跳转路径
        setdefaulttargeturl("/home");
        super.onauthenticationsuccess(request, response, authentication);
    }

    private void handlegithubuser(oauth2user oauthuser) {
        // 实现github用户的特定处理逻辑
        // 例如保存用户信息到数据库等
    }
}

创建控制器

添加一些基本的控制器来处理页面请求:

@controller
@requiredargsconstructor
public class maincontroller {

    @getmapping("/")
    public string home() {
        return "index";
    }

    @getmapping("/login")
    public string login(model model) {
        model.addattribute("providers", list.of("github")); // 可以扩展更多提供商
        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";
    }
}

创建前端页面

创建几个简单的thymeleaf模板页面:

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>

测试应用

  • 启动应用并访问http://localhost:8080/demo/login
  • 点击"login with github"按钮
  • 你将被重定向到github进行授权
  • 授权后,你会被重定向回应用并显示欢迎信息和用户头像

扩展功能

  • 多提供商支持:添加google、facebook等提供商:

    spring:
      security:
        oauth2:
          client:
            registration:
              google:
                client-id: your-google-client-id
                client-secret: your-google-client-secret
                scope: email,profile
    
  • 用户信息持久化:创建用户实体和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集成:结合oauth2和jwt实现无状态认证。

常见问题解决

  • 重定向uri不匹配

    • 确保在oauth提供商后台配置的回调url与应用中的一致
    • 格式通常为:http://localhost:8080/demo/login/oauth2/code/github
  • csrf问题

    • 生产环境应启用csrf保护
    • 确保表单提交包含csrf令牌
  • 范围不足

    • 检查请求的scope是否正确
    • 某些提供商需要审核才能获取高级权限

总结

本文详细介绍了在spring boot 3中整合oauth2实现第三方登录的完整流程。通过spring security的oauth2客户端支持,我们可以轻松集成多种第三方登录提供商。关键点包括:

  • 正确配置oauth2客户端信息
  • 自定义用户服务处理不同提供商的用户信息
  • 实现认证成功处理器处理登录后逻辑
  • 提供友好的用户界面

你可以在此基础上扩展更多功能,如用户信息持久化、多提供商支持、jwt集成等。希望这篇文章对你实现第三方登录功能有所帮助!

到此这篇关于spring boot3整合oauth2实现第三方登录功能的文章就介绍到这了,更多相关springboot3整合oauth2第三方登录内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com