现在我们的系统想实现通过gitee的账号登陆我们的系统,使用微信,QQ,支付宝等等,大同小异
角色描述
授权服务器(Authorization Server):
它负责验证资源所有者的身份,并向客户端发放访问令牌。这里指的就是 gitee
资源服务器
托管资源所有者的受保护资源。资源服务器可以接受和响应来自客户端的受保护资源请求,但前提是客户端必须拥有有效的访问令牌。这里指的就是我们自己的系统
1 进入gitee网站,申请个第三方应用的授权,标箭头的特别注意
Client ID和Client Secret,以及设置应用回调地址CALLBACK_URI
![](https://img-blog.csdnimg.cn/direct/20a44556fff24cb5be6a438b57854be7.png)
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;
}
}