手摸手接入Github实现Oauth2第三方登录

这篇具有很好参考价值的文章主要介绍了手摸手接入Github实现Oauth2第三方登录。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

最近在学习oauth2授权登录流程,oauth2简单来说就是接入第三方应用(qq、微信、github、gitee等),不用在本站登录,而是去请求第三方应用的用户信息完成登录。

下面就一起来看一下如何接入github实现第三方登录

前置操作

首先,我们需要在github中添加OAuth App,登录你的github(如果还有无法登录github的,请在评论区留言或私信我)

手摸手接入Github实现Oauth2第三方登录,Demo,github,java,vue.js

手摸手接入Github实现Oauth2第三方登录,Demo,github,java,vue.js

手摸手接入Github实现Oauth2第三方登录,Demo,github,java,vue.js

手摸手接入Github实现Oauth2第三方登录,Demo,github,java,vue.js

手摸手接入Github实现Oauth2第三方登录,Demo,github,java,vue.js

手摸手接入Github实现Oauth2第三方登录,Demo,github,java,vue.js

点击注册

手摸手接入Github实现Oauth2第三方登录,Demo,github,java,vue.js

如果你成功执行到这里,那么就恭喜你已经把前置工作完成了

实战演练

下面就以我个人的博客代码为例,和大家一起实现github第三方登录

博客地址:www.yuuu.online,

项目地址:蔚泽华 (yuuu-zehua) - Gitee.com

业务流程

我这里先说一下我项目的业务流程:用户第一次使用github登录,那么我会让其与我的网站进行绑定(邮箱);如果是非第一次使用,那么就直接登录

话不多说,直接进入!

业务代码

因为我的项目是前后端分离的,所以一切请求都要过一遍前端代理,因此我写了一个Loading页,这也是我添加的github回调地址。

// Loading页的执行方法
oauth() {
            const urlParams = new URLSearchParams(window.location.search);
            const code = urlParams.get('code');
            const state = urlParams.get('state');
            if (code && code != '') {
                request.post('user/oauth?code=' + code + '&state=' + state).then(response => {
                    console.log(response);
                    if(response === undefined){
                        this.$router.push({ path: '/Login?login=9' });
                    }else{
                        setToken(response.token)
                        localStorage.setItem("userInfo", JSON.stringify(response.userInfo))
                        this.$router.push({ path: '/' });
                    }
                })
            }
        },

在这里会根据后端的返回去判断是第一次登录还是非第一次登录,下面是后端接口实现

public ResponseResult oauth(String code) {

        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        BlogUserLoginVo blogUserLoginVo;
        try {
            String oauthToken = getOauthToken(code);
            GithubUser githubUser = getUserInfoWithGithub(oauthToken);

            queryWrapper.eq(User::getGithubId, githubUser.getId());
            User one = getOne(queryWrapper);
            if (one != null) {
                // 已经绑定过用户信息,直接登录
                blogUserLoginVo = getBlogUserLoginVo(one);
                return ResponseResult.okResult(blogUserLoginVo);
            } else {
                redisCache.setCacheObject(code,githubUser);//注意这里
                Map<Integer,String> map = new HashMap<>();
                map.put(999, "未绑定");
                return ResponseResult.okResult(map);
            }
        } catch (IOException e) {
            throw new SystemException(AppHttpCodeEnum.SYSTEM_ERROR);
        }
    }

private BlogUserLoginVo getBlogUserLoginVo(User user) {
        // 获取userId,生成token
        String jwt = JwtUtil.createJWT(user.getId().toString());
        // 把用户信息存入redis
        LoginUser loginUser = new LoginUser();
        loginUser.setUser(user);
        loginUser.setPermissions(null);
        redisCache.setCacheObject(SystemConstants.BLOG_LOGIN_KEY + user.getId(), loginUser, 1800, TimeUnit.SECONDS);
        // 把token和userInfo封装返回
        // 把user转换为userInfo
        UserInfoVo userInfoVo = BeanCopyUtils.copyBean(user, UserInfoVo.class);
        BlogUserLoginVo blogUserLoginVo = new BlogUserLoginVo(jwt, userInfoVo);
        return blogUserLoginVo;
    }

private String getOauthToken(String code) throws IOException {
        String url = "https://github.com/login/oauth/access_token";

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));

        String requestBody = String.format("{\"client_id\":\"%s\",\"client_secret\":\"%s\",\"code\":\"%s\"}",
                clientId, clientSecret, code);

        HttpEntity<String> request = new HttpEntity<>(requestBody, headers);

        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, request, String.class);

        if (response.getStatusCode().is2xxSuccessful()) {
            // 解析JSON响应,获取access_token字段
            String jsonString = JSON.toJSONString(response);
            JSONObject jsonObject = JSON.parseObject(jsonString);
            JSONObject body = jsonObject.getJSONObject("body");
            Object token = body.get("access_token");
            return token.toString();
        } else {
            throw new SystemException(AppHttpCodeEnum.SYSTEM_ERROR);
        }
    }

private GithubUser getUserInfoWithGithub(String oauthToken) throws IOException {
        String url = "https://api.github.com/user";
        HttpHeaders headers = new HttpHeaders();
        headers.set("Authorization", "Bearer " + oauthToken);
        headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
        HttpEntity<Void> requestEntity = new HttpEntity<>(headers);
        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.GET, requestEntity, String.class);
        if (responseEntity.getStatusCode().is2xxSuccessful()) {
            String body = responseEntity.getBody();
            cn.hutool.json.JSONObject jsonObject = JSONUtil.parseObj(body);
            GithubUser githubUser = jsonObject.toBean(GithubUser.class);
            return githubUser;
        } else {
            throw new SystemException(AppHttpCodeEnum.SYSTEM_ERROR);
        }
    }

相关实体类,其实内容有很多,但是在我项目里我只抽出了其中返回的几个字段

public class GithubUser {
    private String login;
    private Integer id;
    private String nodeId;
    private String avatarUrl;
}

到这里,如果用户已经绑定过邮箱信息,那么就可以直接登录主页。如果用户没有绑定,就会跳转到绑定页。

这是我的绑定页

手摸手接入Github实现Oauth2第三方登录,Demo,github,java,vue.js

绑定的代码也和前面的差不多

前端代码

oauthWithGithub() {
            const urlParams = new URLSearchParams(window.location.search);
            const code = urlParams.get('code');
            const state = urlParams.get('state');
            if (!this.emailCaptchaUpdate) {
                this.$message.error('验证码不能为空');
            } else {
                request.post('/user/oauth/github?code='+code, {
                    emailPassword: this.emailPassword,
                    confirmNewPassword: this.confirmNewPassword,
                    emailCaptchaUpdate: this.emailCaptchaUpdate,
                })
                    .then((response) => {
                        console.log(response)
                        this.$alert('绑定成功', '', {
                            confirmButtonText: '确定'
                        })
                        this.isButtonDisabled2 = false;
                        this.emailPassword = '';
                        this.emailCaptchaUpdate = '';
                        setToken(response.token)
                        localStorage.setItem("userInfo", JSON.stringify(response.userInfo))
                        this.$router.push({ path: '/' });
                    })
                    .catch((error) => {
                        console.log(error);
                    });
            }
        },

后端接口

public ResponseResult oauthGithub(ChangePassword user,String code) {
        String email = user.getEmailPassword();
        String captcha = user.getEmailCaptchaUpdate();
        if (StrUtil.isBlank(email)) {
            throw new SystemException(AppHttpCodeEnum.EMAIL_ISNULL);
        }
        if (StrUtil.isBlank(captcha)) {
            throw new SystemException(AppHttpCodeEnum.CAPTCHA_ISNULL);
        }
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getEmail, email);
        String cacheCaptcha = redisCache.getCacheObject(SystemConstants.MAIL_KEY + captcha);
        if (!captcha.equals(cacheCaptcha)) {
            return ResponseResult.errorResult(601, "请再检查一下验证码~");
        } else {
            redisCache.deleteObject(SystemConstants.MAIL_KEY + captcha);
        }
        User existingUser = getOne(queryWrapper);
        BlogUserLoginVo blogUserLoginVo;
        // 还记得上面让大家注意的地方吗?如果忘记了速速回滚查看!
        // 因为github的code只能用一次,本来想使用ThreadLocal,但是实现起来总报错,就直接用            
        // redis存储
        GithubUser githubUser = redisCache.getCacheObject(code);
        if (existingUser == null) {
            // 新增
            User userByGithub = new User();
            userByGithub.setGithubId(githubUser.getId());
            userByGithub.setAvatar(githubUser.getAvatarUrl());
            userByGithub.setEmail(user.getEmailPassword());
            userByGithub.setPassword(passwordEncoder.encode(SystemConstants.DEFAULT_PASSWORD));
            userByGithub.setNickName(githubUser.getNodeId());
            userByGithub.setUserName(githubUser.getLogin());
            save(userByGithub);
            // 用户登录
            blogUserLoginVo = getBlogUserLoginVo(userByGithub);
        } else {
            // 修改
            existingUser.setGithubId(githubUser.getId());
            updateById(existingUser);
            // 用户登录
            blogUserLoginVo = getBlogUserLoginVo(existingUser);
        }
        // 用完就及时删除,避免资源浪费
        redisCache.deleteObject(code);
        return ResponseResult.okResult(blogUserLoginVo);
    }

到这里,就实现了全部的功能,大家可以去尽情的尝试了!

总结

Oauth2实现的原理就是拿code去换第三方的token,然后再用token去获取用户信息,看起来很容易,但是实现起来有点麻烦,其实也不是难,就是麻烦,你需要去看每个厂商的api文档,每一个还都不一样,就比如github和gitee。

我想大家在实现时也会常常出现接口超时,没有办法,我的代码在本地不会超时,但是部署在华为云服务器上就反复报接口超时,后面我也会进行优化。谢谢大家观看。

后续

后面也是成功解决了github超时的问题,给大家说一下方法。

我是自己在Cloudflare开了一个代理,把自己的域名代理到了github
如果有需要我的代理域名的小伙伴可以私信我。如果有需要出教程的也可以在评论区留言,需要的人多了就继续手摸手实现github代理。文章来源地址https://www.toymoban.com/news/detail-764279.html

到了这里,关于手摸手接入Github实现Oauth2第三方登录的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Oauth2.0 单点登录 + 第三方授权认证】用户认证、授权模式

    本文主要对 SpringSecurity Oauth 2.0 用户认证,授权码授权模式、密码授权模式,以及授权流程进行讲解 开发中,有些功能只有管理员才有,普通用户是没有的。即需要对用户的身份进行认证,是管理员还是普通用户。认证方式有两种: 身份认证: 用户在访问相应资源时对用户

    2023年04月08日
    浏览(44)
  • Spring Boot 最新版3.x 集成 OAuth 2.0实现认证授权服务、第三方应用客户端以及资源服务

    Spring Boot 3 已经发布一段时间,网上关于 Spring Boot 3 的资料不是很多,本着对新技术的热情,学习和研究了大量 Spring Boot 3 新功能和新特性,感兴趣的同学可以参考 Spring 官方资料全面详细的新功能/新改进介绍 Spring 版本升级到6.x JDK版本至少17+ … 新特性有很多,本文主要针对

    2024年02月02日
    浏览(50)
  • 到底要不要,手摸手指导下属?

    leader的 核心职责 是: (1)对上 ,完成老板交予的任务; (2)对同事 ,为队友赋能; (3)对下 ,为下属搭舞台唱戏,帮助下属解决问题,帮助下属成长和提升; 其中,帮助下属成长和提升,指导与培养员工,是非常重要的一块,新晋管理者心中可能会有这样 一些疑问

    2024年02月05日
    浏览(46)
  • OAuth2.0从入门到实战(附github地址)

    OAuth 是一个开放标准 ,该标准允许用户让第三方应用访问该用户在某一网站上存储的私密资源(如头像、照片、视频等),而在这个过程中无需将用户名和密码提供给第三方应用。实现这一功能是通过提供一个令牌(token),而不是用户名和密码来访问他们存放在特定服务提

    2023年04月08日
    浏览(11)
  • 手摸手带你初探Vue 3.0

    距离Vue 3.0正式发布已经过去一段时间了,2月7日Vue团队正式宣布Vue 3正式成为新的默认版本。最近接触的新项目也使用Vue 3.0来开发,因此有必要对它进行一波总结和学习。 在最开始的时候,Vue仅仅是一个运行时库。但经过多年的发展,它已经逐渐变成了一台包含许多子项目的

    2024年02月16日
    浏览(36)
  • SpringSecurity:OAuth2 Client 结合GitHub授权案例(特简单版)

    本随笔说明:这仅作为OAuth2 Client初次使用的案例,所以写得很简单,有许多的不足之处。 OAuth2 Client(OAuth2客户端)是指使用OAuth2协议与授权服务器进行通信并获取访问令牌的应用程序或服务。OAuth2客户端代表最终用户(资源拥有者)向授权服务器请求授权,并使用授权后的

    2024年02月03日
    浏览(82)
  • 手摸手教你写任务中心-积分领取&消耗&回收

    继上一篇签到任务之后呢, 就有朋友让我写一下任务积分的领取和使用, 以及回收; 其实前面两种都不难, 就只是积分的加减而已, 真正麻烦的是回收, 有回收的话你就需要考虑到每笔积分存在多种状态的可能了; 明细表(mysql) 记录积分的每一笔获取, 消耗的回收的记录, 并且回收

    2024年02月08日
    浏览(37)
  • 手摸手带你 在Windows系统中安装Istio

    通过负载均衡、服务间的身份验证、监控等方法,Istio 可以轻松地创建一个已经部署了服务的网络,而服务的代码只需很少更改甚至无需更改。 通过在整个环境中部署一个特殊的 sidecar 代理为服务添加 Istio 的支持,而代理会拦截微服务之间的所有网络通信,然后使用其控制

    2024年02月06日
    浏览(36)
  • 不用魔法,快速、手摸手上线Midjourney!【附源码】【示例】

    首先来一波感谢: 感谢laf提供赞助,目前可以免费使用Midjourney进行开发和测试。 感谢白夜、米开朗基杨@sealos.io的耐心解答,让我对laf有了更多的使用与了解。 什么是laf?来了解下。 文末有【示例】 废话不多说,进入正题。 laf在做一个活动,可以使用快速上手Midjourney《人

    2024年02月05日
    浏览(34)
  • 手摸手2-springboot编写基础的增删改查

    创建controller层 实现 test 表中的添加、修改、删除及列表查询接口(未分页) 添加service层接口 service层实现 添加mapper层 mapper层对应的sql 添加扫描注解,对应sql文件的目录

    2024年02月10日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包