Oauth2.0 github认证登录实现

认证

创建一个授权github app网址

前言

在这里插入图片描述

1. 右上角点击设置

在这里插入图片描述

2.点击开发者设置

在这里插入图片描述

3. 点击 OAuth Apps

在这里插入图片描述

4. 创建一个 新的 OAuth App,如果没有注册会跳转到注册页面

在这里插入图片描述
注册页面网址

在这里插入图片描述

流程:
(1) 用户跳转到github 去获取权限
(2) github 授权成功会跳转回我们的网站 带回来一个code
(3) 通过第(2)中github跳转回来的code去访问 githubApi 拿到token

1.用户去github 授权,目的是授权成功后拿到code
在这里插入图片描述
2. 拿到 code,去交换 token
在这里插入图片描述
3.拿着token去访问github 获取github的用户信息
在这里插入图片描述

  • 流程图

    在这里插入图片描述

    5.输入你的被认证的app 的名字

    在这里插入图片描述

    6. 输入被认证app 主页的名字

    在这里插入图片描述

    7. 展现给用户的描述

    在这里插入图片描述

    8.认证完后跳转到 哪个页面(回调)

    在这里插入图片描述

    9. 注册

    在这里插入图片描述

    10.授权

    在这里插入图片描述

    11.输入github 用户名秘密或者点击授权(已经登录github的)后,返回一个code 码

    在这里插入图片描述

    12.拿着 code ,client_id ,client_secret,redirect_uri ,state 去换 token

    13. 拿着token 去换 用户id 和 其他信息

    在这里插入图片描述

    在这里插入图片描述


    ---------------------------------------------- 总结: -------------------------------------------------------

    1.用户点击登录按钮,浏览器去访问github 服务器请求code 码,
    https://github.com/login/oauth/authorize?client_id=d41ff3a3c0873a0a4b6c&redirect_uri=http://localhost:8080/callback&scope=user & state=1
    出现一个github 登录界面,让用户登录授权
    在这里插入图片描述

    2.用户登录授权后,Github 服务器返回 给浏览器一个 code 码
    如下:
    http://localhost:8080/callback?code=ee2fa64ef1e81757a6bd
    自己的服务器拦截 到code 码,

    在这里插入图片描述

    3.post 请求:
    https://github.com/login/oauth/access_token
    参数: client_id , client_secret , code , redirect_uri , state,

    返回token令牌,
    4.拿着令牌去访问 用户的信息
    Request request = new Request.Builder()
    .addHeader(“Authorization”,"token "+accessToken)
    .url(“https://api.github.com/user?access_token=” + accessToken)
    .build();
    5.拿到用户的信息,进行处理

    相关代码

    目录结构
    在这里插入图片描述
    login.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <h1> Hello OAuth2</h1>
    
    <hr>
    <p>其他登录方式</p>
    <a href="{{ context.github_auth_url }}">github登录</a> <br>
    <a href="{{ context.gitee_auth_url }}">gitee登录</a>
    </body>
    </html>
    

    index.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Home</title>
    </head>
    <body>
    <div>
        <h1>欢迎登录</h1>
        {% if user_info.user_name %}
            <p>用户名: {{ user_info.user_name }}</p>
        {% else %}
            <p>{{ user_info.msg }}</p>
        {% endif %}
    
        {% if user_info.avatar_url %}
            <p>头像: <img src="{{ user_info.avatar_url }}" alt="头像信息"></p>
        {% endif %}
    
        <p>token: {{ jwt }}</p>
    
        <a href="http://127.0.0.1:5000/source?token={{ jwt }}">获取资源列表</a>
    </div>
    </body>
    </html>
    
    

    app.py

    # -*- coding:utf-8 -*-
    
    '''
    PROJECT_NAME : auth_demo
    file    : app5_oauth
    author  : 1032162439@qq.com
    date    : 2022-09-09 11:37
    IDE     : PyCharm
    '''
    import json
    
    import jwt
    import requests
    from jwt import exceptions
    from flask import Flask, render_template, request, redirect
    
    # 实例化app对象
    app = Flask(__name__)
    
    # 设置secret key
    app.secret_key = 'secret key string!'
    
    # github 的 client id、 client secret、 redirect uri
    github_client_id = 'bc19fcdf968ffbb1fa05'
    github_client_secret = 'you client secret'
    github_redirect_uri = 'http://127.0.0.1:5000/oauth2/github/callback'
    # github 用户信息 api
    github_user_info_url = 'https://api.github.com/user'
    # github access_token api
    github_access_token_url = 'https://github.com/login/oauth/access_token'
    
    # gitee 的 client id、 client secret、 redirect uri
    gitee_client_id = '0dd3dc5d005a384d1e5dba633eabfdb59c6bc9d68df8eca374e3245e92156e40'
    gitee_client_secret = 'you client secret'
    gitee_redirect_uri = 'http://127.0.0.1:5000/oauth2/gitee/callback'
    # gitee 用户信息api
    gitee_user_info_url = 'https://gitee.com/api/v5/user'
    # gitee access_token api
    gitee_access_token_url = 'https://gitee.com/oauth/token'
    
    
    def get_github_user_info(access_token):
        """
        获取github用户信息
        注意:github用户信息api,要求必须以请求头的形式传递token,不能以url方式传参
        :param access_token:
        :return:
        """
        headers = {
            'Authorization': f'token {access_token}'
        }
        print(github_user_info_url)
        resp = requests.get(url=github_user_info_url, headers=headers)
        if resp.status_code == 200:
            return json.loads(resp.text)
        else:
            return {'msg': '认证失败'}
    
    
    def get_gitee_user_info(access_token):
        """
        获取gitee用户信息
        :param access_token:
        :return:
        """
        resp = requests.get(url=gitee_user_info_url,
                            data={
                                'access_token': access_token
                            })
        if resp.status_code == 200:
            return json.loads(resp.text)
        else:
            return {'msg': '认证失败'}
    
    
    def get_gitee_access_token(code):
        """
        获取gitee的access token  该token用于向gitee请求用户信息
        :param code:
        :return:
        """
        status = {'status': None, 'msg': None, 'data': ''}
        try:
            resp = requests.post(
                url=gitee_access_token_url,
                data={
                    'grant_type': 'authorization_code',
                    'client_id': gitee_client_id,
                    'client_secret': gitee_client_secret,
                    'code': code,
                    'redirect_uri': gitee_redirect_uri
                }
            )
            if resp.status_code == 200:
                status['status'] = True
                status['msg'] = 'ok'
                status['data'] = json.loads(resp.text).get('access_token')
        except Exception as e:
            status['status'] = False
            status['msg'] = f'error:{e}'
        return status
    
    
    def get_github_access_token(code):
        """
        获取github 的access token 用于向github获取用户信息
        :param code:
        :return:
        """
        status = {'status': None, 'msg': None, 'data': ''}
        try:
            resp = requests.post(
                url=github_access_token_url,
                data={
                    'client_id': github_client_id,
                    'client_secret': github_client_secret,
                    'code': code,
                }
            )
            if resp.status_code == 200:
                status['status'] = True
                status['msg'] = 'ok'
                status['data'] = resp.content.decode('utf-8').split('&')[0].split('=')[1]
        except Exception as e:
            status['status'] = False
            status['msg'] = f'error:{e}'
        return status
    
    
    @app.route('/login')
    def login():
        """
        登录接口
        :return:
        """
        print(f'https://github.com/login/oauth/authorize?client_id={github_client_id}&redirect_uri={github_redirect_uri}')
        context = {
            'github_auth_url': f'https://github.com/login/oauth/authorize?client_id={github_client_id}&redirect_uri={github_redirect_uri}',
            'gitee_auth_url': f'https://gitee.com/oauth/authorize?client_id={gitee_client_id}&redirect_uri={gitee_redirect_uri}&response_type=code'
        }
        return render_template('login.html', context=context)
    
    
    @app.route('/oauth2/github/callback')
    def oauth_github_callback():
        code = request.args.get('code')
        print(f'github-code:{code}')
        status = get_github_access_token(code)
        print(status)
        access_token = status.get('data')
        github_user_info = get_github_user_info(access_token)
        print(github_user_info)
        jwt_payload = {
            'user_id': github_user_info['id'],
            'user_name': github_user_info['login'],
        }
        jwt = create_jwt(jwt_payload)
        return render_template('index.html', user_info=github_user_info, jwt=jwt)
    
    
    @app.route('/oauth2/gitee/callback')
    def oauth_gitee_callback():
        code = request.args.get('code')
        print(f'gitee: {code}')
        status = get_gitee_access_token(code)
        access_token = status.get('data')
        gitee_user_info = get_gitee_user_info(access_token)
        print(gitee_user_info)
        jwt_payload = {
            'user_id': gitee_user_info['id'],
            'user_name': gitee_user_info['login'],
        }
        jwt = create_jwt(jwt_payload)
        return render_template('index.html', user_info=gitee_user_info, jwt=jwt)
    
    
    def create_jwt(payload):
        """
        生成token
        :param payload: 需要jwt携带的参数
        :return:
        """
        # 构造header
        headers = {
            'typ': 'jwt',
            'alg': 'HS256'
        }
        token = jwt.encode(payload=payload, key=app.secret_key, algorithm="HS256", headers=headers)
        return token
    
    
    def check_jwt(token):
        status = {'status': None, 'msg': None}
        try:
            verified_payload = jwt.decode(jwt=token, key=app.secret_key, algorithms=['HS256'])
            status['status'] = True
            status['msg'] = verified_payload
        except exceptions.ExpiredSignatureError:
            status['msg'] = 'token已失效'
        except jwt.DecodeError:
            status['msg'] = 'token认证失败'
        except jwt.InvalidTokenError:
            status['msg'] = '非法的token'
        return status
    
    
    # 不需要验证token的白名单
    WHITE_LIST = [
        '/login',
        '/oauth2/gitee/callback',
        '/oauth2/github/callback',
    ]
    
    
    @app.route('/source')
    def source():
        """
        资源接口
        :return:
        """
        return '资源列表'
    
    
    @app.before_request
    def check_jwt_hook():
        """
        拦截请求,校验token是否合法
        :return:
        """
        # 如果请求路径在白名单内
        if request.path in WHITE_LIST:
            return
        # 获取请求路径中的token
        jwt = request.args.get('token')
        if not jwt:
            # 如果没有传递token,重定向到登录页面
            return redirect('/login')
        # 检验jwt
        status = check_jwt(jwt)
        if not status['status']:
            print(status['msg'])
            # 如果jwt校验失败还是重定向到登录页面
            return redirect('/login')
        # jwt校验成功直接到视图函数
        return
    
    
    if __name__ == '__main__':
        app.run(debug=True)
    
    
    
    • 0
      点赞
    • 0
      收藏
      觉得还不错? 一键收藏
    • 0
      评论
    ### 回答1: 要实现OAuth2.0服务端代码需要以下步骤: 1. 确保你已经安装了Java开发环境(JDK)和一个集成开发环境(例如Eclipse或IntelliJ IDEA)。 2. 在你选择的开发环境中创建一个新的Java项目。 3. 下载并导入OAuth2.0的Java库。你可以选择使用Spring Security OAuth库,该库提供了实现OAuth2.0服务端所需的核心功能。你可以在Spring官方网站上找到该库的下载链接。 4. 在你的项目中引入Spring Security OAuth库。根据你选用的开发环境不同,导入库的方法也会有所不同。你可以在官方文档中找到相应的说明。 5. 创建一个Java类来配置和启动你的OAuth2.0服务。在这个类中,你需要配置OAuth2的一些参数,如客户端ID和客户端密钥,以及授权的范围和访问令牌的有效期等。你可以使用Java注解配置来完成这些工作。 6. 在代码中实现OAuth2.0的核心功能,如授权码、密码和客户端凭证等授权类型的处理。你可以使用Spring Security OAuth库提供的工具来简化这个过程。 7. 在你的服务中添加一个端点来处理OAuth2.0的授权请求。这个端点将接收来自客户端的请求,并根据请求的类型和参数来执行相应的授权逻辑。 8. 完成OAuth2.0授权逻辑后,你可以根据需要对返回的访问令牌进行自定义处理。例如,你可以在令牌中添加一些额外的属性,以便在后续的请求中进行验证或授权。 9. 编译和运行你的项目。确保服务已经成功启动,并且可以处理来自客户端的授权请求。 以上就是实现OAuth2.0服务端代码的大致步骤。你可以根据自己的项目需求和具体情况来进行进一步的调整和扩展。 ### 回答2: 要实现OAuth2.0服务端代码的下载,可以参考以下步骤: 1. 从OAuth2.0的官方文档或者其他可靠的资源中了解OAuth2.0的基本概念和流程,确保对OAuth2.0有一定的理解。 2. 在Java中实现OAuth2.0服务端,一种常见的选择是使用开源框架Spring Security OAuth。可以通过Spring Security OAuth的官方文档或其他可靠的资源了解其使用方法和配置。 3. 在项目中添加Spring Security OAuth的依赖,可以通过Maven或Gradle等构建工具进行添加。同时,还需要确保项目的其他基础依赖都已正确配置。 4. 配置OAuth2.0的相关参数,包括客户端ID、密钥、授权模式等。这些参数可以根据具体需求进行调整,也可以在代码中进行读取。 5. 实现认证服务器的代码逻辑,包括处理授权请求、验证用户身份、生成和返回访问令牌等。可以根据业务需求进行定制化的逻辑实现。 6. 提供API接口,用于进行授权码获取、令牌刷新、访问资源等操作。可以使用Spring的注解方式定义API接口,如@RequestMapping、@GetMapping等。 7. 验证和测试实现OAuth2.0服务端代码,确保其能够正常运行并符合预期的功能和安全要求。 需要注意的是,OAuth2.0实现涉及到一些安全和授权的问题,因此在实际开发过程中需要加强对权限、令牌管理等方面的保护措施。同时也建议参考OAuth2.0的最佳实践和安全标准,确保系统的安全性。 最后,可以通过搜索引擎、开源社区等渠道获取更多关于Java实现OAuth2.0服务端的代码示例和参考资料。 ### 回答3: 要实现一个OAuth 2.0服务端的代码下载,可以按照以下步骤进行: 1. 首先,需要准备一个Java开发环境,确保已经安装了Java Development Kit(JDK)和任意一个Java开发环境,如Eclipse或IntelliJ IDEA。 2. 接下来,可以从GitHub等代码托管平台上搜索并下载OAuth 2.0的相关库,如Spring Security OAuth或其他第三方库来快速实现OAuth 2.0服务端功能。 3. 下载所需的库后,可以将其导入Java开发环境中,创建一个新的Java项目。 4. 在新项目中创建所需的Java类文件,通常需要创建一个授权服务器类或者控制器(Controller),用于处理OAuth 2.0的请求和响应。可以参考库的文档或者示例代码来编写相应的代码逻辑。 5. 在授权服务器类中,需要配置OAuth 2.0的认证和授权相关信息,例如设置访问令牌(Token)的过期时间、定义客户端(Client)的信息、配置用户(User)的认证逻辑等。 6. 然后,可以在授权服务器类中实现OAuth 2.0的认证和授权流程,包括处理授权码授权流程、客户端凭证授权流程、刷新令牌流程等。 7. 在代码开发完成后,可以编译并运行代码,可以使用Swagger等API文档工具测试OAuth 2.0的相关接口,确保服务端和客户端的交互正常。 8. 最后,根据需要对代码进行优化和调试,确保代码质量和安全性。 以上是一个大致的思路和步骤,具体的实现方式会因使用的库和需求而有所不同。可以参考库的官方文档或者示例代码来更详细地了解客户端代码的实现细节。
    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

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

    抵扣说明:

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

    余额充值