OAuth2使用授权码模式 概述及 gitee登录第三方网站,并拿到gitee系统的用户信息

现在我们的系统想实现通过gitee的账号登陆我们的系统,使用微信,QQ,支付宝等等,大同小异

角色描述


授权服务器(Authorization Server)
它负责验证资源所有者的身份,并向客户端发放访问令牌。这里指的就是 gitee

资源服务器
托管资源所有者的受保护资源。资源服务器可以接受和响应来自客户端的受保护资源请求,但前提是客户端必须拥有有效的访问令牌。这里指的就是我们自己的系统


1 进入gitee网站,申请个第三方应用的授权,标箭头的特别注意
Client ID和Client Secret
,以及设置应用回调地址CALLBACK_URI

2 pom.xml

        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.26</version>
        </dependency>

3 核心类

import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

/**
 * gitee 登陆测试
 */
@Slf4j
@Controller
public class OAuth2Controller {

    private static final String CLIENT_ID = "xxxxx";
    private static final String CLIENT_SECRET = "xxxxxx";
    private static final String CALLBACK_URI = "http://localhost:8080/callback";
    private static final String AUTHORIZE_URL = "https://gitee.com/oauth/authorize";
    private static final String TOKEN_URL = "https://gitee.com/oauth/token";

    private static final String GET_USER_INFO_URL = "https://gitee.com/api/v5/user";

    /**
     * gitee 请求授权页面
     */
    @GetMapping(value = "/gitee/auth")
    public String qqAuth() {

        // Step1:获取Authorization Code
        StringBuilder urlBuilder = new StringBuilder(AUTHORIZE_URL);
        urlBuilder.append("?response_type=code")
                .append("&client_id=").append(CLIENT_ID)
                .append("&redirect_uri=").append(URLEncoder.encode(CALLBACK_URI))
                .append("&scope=user_info");

        //重定向
        return "redirect:" + urlBuilder.toString();
    }

    /**
     * 授权回调,程序会自动调用,不是人来访问的
     */
    @GetMapping(value = "/callback")
    @ResponseBody
    public String giteeCallback(@RequestParam("code") String code) throws Exception {

        try {
            // 得到Authorization Code
            System.out.println("code = " + code);

            // Step2:通过Authorization Code获取Access Token
            Map<String, Object> params = new HashMap<>();
            params.put("grant_type", "authorization_code");
            params.put("client_id", CLIENT_ID);
            params.put("client_secret", CLIENT_SECRET);
            params.put("code", code);
            params.put("redirect_uri", CALLBACK_URI);

            String s1 = HttpRequest.post(TOKEN_URL)
                    .form(params)//表单内容
                    .timeout(20000)//超时,毫秒
                    .execute().body();

            JSONObject accessTokenJson = Optional.ofNullable(s1).map(x -> JSONUtil.parseObj(x)).get();
            System.out.println("accessTokenJson = " + accessTokenJson);
            if (!accessTokenJson.containsKey("access_token")) {
                throw new RuntimeException("获取accessToken失败");
            }

            System.out.println("accessTokenJson = " + accessTokenJson);
            System.out.println();
            String accessTokenStr = accessTokenJson.get("access_token").toString();

            // Step3: 获取用户信息
            HttpRequest httpRequest = HttpRequest.get(GET_USER_INFO_URL + "?access_token=" + accessTokenStr);
            System.out.println("httpRequest = " + httpRequest);
            return httpRequest.execute().body();

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

4 测试


访问 http://localhost:8080/gitee/auth ,点击授权,输入gitee的账号和密码,就可以登陆系统了,并返回了gitee的用户信息


5 全局异常处理类和通用返回类,可选

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

/**
 * RestControllerAdvice = ControllerAdvice + ResponseBody
 * 是controller的增强器,可以全局捕获spring mvc抛的异常
 * 优雅异常处理程序
 * 统一拦截处理
 * 在该类中,可以定义多个方法,不同的方法处理不同的异常
 */
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    @ExceptionHandler({Exception.class})
    public R exceptionHandler(Exception e) {
        log.error("Exception异常:", e);
        return R.error(e.getMessage());
    }
}
package com.example.demo_6.bbb;

import lombok.Data;

import java.io.Serializable;

@Data
public class R implements Serializable {

    private Integer code;
    private String message;
    private Object data;
    private static final Integer DEFAULT_SUCCESS_CODE = 200;
    private static final Integer DEFAULT_ERROR_CODE = 500;

    /**
     * 成功
     *
     * @return
     */
    public static R success() {
        R r = new R();
        r.setCode(DEFAULT_SUCCESS_CODE);
        r.setMessage("请求成功");
        r.setData(new Object());
        return r;
    }

    /**
     * 成功-data
     *
     * @return
     */
    public static R success(Object data) {
        R r = new R();
        r.setCode(DEFAULT_SUCCESS_CODE);
        r.setMessage("请求成功");
        r.setData(data);
        return r;
    }

    /**
     * 成功-data和message
     *
     * @return
     */
    public static R success(Object data, String message) {
        R r = new R();
        r.setCode(DEFAULT_SUCCESS_CODE);
        r.setMessage(message);
        r.setData(data);
        return r;
    }

    /**
     * 错误
     *
     * @return
     */
    public static R error() {
        R r = new R();
        r.setCode(DEFAULT_ERROR_CODE);
        r.setMessage("请求失败");
        return r;
    }

    /**
     * 错误-code
     *
     * @return
     */
    public static R error(Integer code) {
        R r = new R();
        r.setCode(code);
        r.setMessage("请求失败");
        return r;
    }

    /**
     * 错误-message
     *
     * @return
     */
    public static R error(String message) {
        R r = new R();
        r.setCode(DEFAULT_ERROR_CODE);
        r.setMessage(message);
        return r;
    }

    /**
     * 错误-code和message
     *
     * @return
     */
    public static R error(Integer code, String message) {
        R r = new R();
        r.setCode(code);
        r.setMessage(message);
        r.setData(new Object());
        return r;
    }
}

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值