1. OAuth2.0 简介
全称:Open Authorization
OAuth(Open Authorization)是一个关于授权(authorization)的敞开网络标准,答运用户授权第三方 运用拜访他们存储在另外的服务供给者上的信息,而不需求将用户名和暗码供给给第三方。 OAuth在全世界得到广泛运用,现在的版本是2.0版。
特点:
- 简略:不管是OAuth服务供给者仍是运用开发者,都很易于了解和运用
- 安全:没有涉及到用户密钥等信息,更安全灵活
- 敞开:任何服务供给商都能够完结OAuth,任何软件开发上商都能够运用OAuth
四种形式
-
授权码形式(Authorization Code):OAuth2 中现在最安全最杂乱也是最常用的形式
-
隐式授权形式(Implicit Grant):
-
用户命暗码形式(Resource Owner Passowrd Credentials grant ):暗码凭据授权
-
客户端形式(Client Credientials Grant):客户端授权
2. OAuth2.0 长处
OAuth登录的长处
- 第三方登录简略便利,面对不同渠道不同的用户名和暗码的问题,第三方登 录正好解决这个问题,几乎能够直接一个账号搞定一切
- 第三方登录还能够将自己在某个运用的动态信息同步到当前运用下,无需再为每个运用重新写个人材料
- 第三方登录有很多材料信息能够共用(比方头像和昵称),一般关于灵敏材料如手机、邮箱是第三方渠道是不会供给的,所以安全信息能够放心
OAuth为企业带来的价值
-
简化登录过程,降低注册门槛,更能获取海量用户,有用降低了用户的流失。本地注册的稳定+第三方登 录的快捷才是最合适的登录计划
-
第三方登录接入后,运用可直接获取用户昵称、头像、用户D等信息,便利产品获取用户的基本材料,削减产品规划本钱
-
现在市面上的短信验证码的价钱约在0.05元左右,当用户挑选运用第三方登录时,可有用削减产品的登 录本钱
OAuth为第三方供给商带来的价值
-
增加用户对渠道(QQ\微信\支付宝\Google)的依靠,用户越多运用本渠道的第三方登录,就代表着渠道对该用户的粘性越高
-
获得更广泛的影响力,只要用户运用供给第三方登录的运用,那么这个供给第三方登录的品牌就会被用户阅读,有利于对渠道的拉新和促活
3 OAuth2.0 人物
人物 | 效果 |
---|---|
客户端 | 本身不存储资源,需求经过资源具有者去恳求资源服务器的资源。APP,游戏,影视网站… |
资源具有者 | 一般为用户,也能够是运用程序,即资源的 |
授权服务器 | 用于服务供给商对资源具有者的身份进行认证、对拜访资源进行授权发放授权码(code)。 认证成功后经过授权码恳求发放令牌(token),作为客户端拜访资源服务器的凭据。 |
资源服务器 | 存储资源的服务器,比方微信端存储的用户信息 |
4 OAuth2.0 授权码形式
OAuth2 中现在最安全最杂乱也是最常用的形式,履行流程如下
5 二维码生成
5.1 依靠要求
<!--Hutool:JaVa东西包类库,对文件、流、加密解密、转码、正则、线程、XML等JDK办法进行封装,组成各种Ui东西类。-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.15</version>
</dependency>
<!--生成二维码-->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.3.3</version>
</dependency>
5.2 生成二维码示例
- 一般生成:四个参数:Url,宽,高,输出路径
QrCodeUtil.generate(
"https://warriorsgo.netlify.app",300,300, FileUtil.file("d:/qrcode.jpg")
);
- 装备生成:装备信息较多时推荐将装备信息写入装备目标再生成
//装备参数较多时运用装备生成
QrConfig config = new QrConfig(1000, 1000);//新建装备文件并指定宽高
config.setErrorCorrection(ErrorCorrectionLevel.Q);//指定纠错等级
QrCodeUtil.generate(
"https://warriorsgo.netlify.app",config, FileUtil.file("d:/qrcode.jpg")
);
其间:纠错等级 ErrorCorrectionLevel有四个等级:L,M,Q,H
从左到右:纠错等级进步,即便被遮挡一小部分也能识别成功,单位像素块面积减小,像素块数量增多,
- 其他装备
装备办法 | 效果 |
---|---|
setBackColor(Color.XXX) | 设置背景颜色 |
setForeColor(Color.XXX) | 设置像素块颜色 |
setImg(ImgPath) | 设置中心logo图标 |
setMargin(margin) | 设置边缘宽度 |
setHeight(h)/setWidth(w) | 设置宽高 |
6 Cpolar 内网穿透东西
cpolar极点云: 揭露一个本地Web站点至公网
效果:只需一行命令,就能够将内网站点发布至公网,便利给客户演示。高效调试微信大众号、小程序、对接支付宝网关等云端服务,进步您的编程效率。
- 登录注册下载安装
download下载 – cpolar 极点云:www.cpolar.com/download
- 获取cpolar账号Token
cpolar – secure introspectable tunnels to localhost:dashboard.cpolar.com/auth
- 命令行运行cpolar,验证token
cpolar authtoken MGU1OWY4NWItXXXXXXXXXXXXXXXX
- 完结简略内网穿透:cpolar 协议名 内网端口
cpolar http 8080
留意:每次重启后随机域名会改动!
Forwarding里边的域名便是公网域名,能够给其他外网设备拜访。
7 OAuth2.0 – 微信登录
7.1 准备工作
扫码登陆微信有两种完结方法
-
依据微信大众渠道的扫码登录
让第三方运用投入微信的怀有而规划的,这第三方运用指的是比方android、ios、网站、体系等;
-
依据微信敞开渠道的扫码登录(For common people) 为了让程序员小伙伴利用微信自家技能(大众号、小程序)开发大众号、小程序而准备的。
区别 微信敞开渠道需求开企业认证才能注册。 微信大众渠道需求认证微信服务号,才能进行扫码登录的开发。只需恳求一个大众号。
关于初学者,即没有企业认证,也纷歧定有自己的大众号,就只能运用测验大众号
测验大众号恳求地址:微信大众渠道 (qq.com)
mp.weixin.qq.com/debug/cgi-b…
1. 接口装备信息:
接入概述 | 微信敞开文档 (qq.com)
参数 | 阐明 |
---|---|
URL | 此处要加协议,以及对应的检验接口 |
token | 随意设置自定义token |
示例:
URL : 63c27f47.r7.cpolar.top/wechat/chec…
Token :AASAdd
2. 网页授权获取用户基本信息 – 修改回调域名
在本网页里边找到 – 网页服务 – 网页账号 – 网页授权获取用户基本信息 -修改:授权回调页面域名
-
回调域名效果:
用户在网页授权页赞同授权给大众号后,微信会将授权数据传给一个回调页面,回调页面需在此域名下,以保证安全可靠。沙盒号回调地址支撑域名和ip,正式大众号回调地址只支撑域名
-
留意:此处填写域名,不是URL!无需https:// 等协议头
示例:
回调地址:63c27f47.r7.cpolar.top
7.2 完结细节
网页授权 | 微信敞开文档 (qq.com)
基本步骤:
网页授权流程分为四步:
- 引导用户进入授权页面赞同授权,获取code
- 授权页面能够以二维码或许前端恳求跳转的形式给用户
- 授权链接参数解释:网页授权 | 微信敞开文档 (qq.com)
- 经过code交换网页授权access token(与根底支撑中的access_token不同)
- 如果需求,开发者能够改写网页授权access_token,避免过期
- 经过网页授权access token和openid获取用户基本信息(支撑UnionID机制)
7.2.0 微信接口校验
编写微信验证的测验接口办法:
@Controller
@RequestMapping("/wechat")
public class WeChatController {
@GetMapping("/check")
@ResponseBody
public String WXCheck(@RequestParam("signature") String signature,
@RequestParam("timestamp") String timeStamp,
@RequestParam("nonce") String nonce,
@RequestParam("echostr") String echoStr){
System.out.println("hello");
System.out.println("echostr = " + echoStr);
return echoStr;
}
...
}
developers.weixin.qq.com/doc/offiacc…
完结 7.1 准备工作中的 URL,TOKEN,回调域名 的数据填写,装备后点击测验,显现 装备成功 则可进入下一步
示例:
URL : 63c27f47.r7.cpolar.top/wechat/chec…
Token :AASAdd
回调地址:63c27f47.r7.cpolar.top
7.2.1 进入授权页
用户点击授权之后,服务商服务器建议一个带着授权码code的Get恳求,指向设置的回调地址(../wechat/auth)
@Controller
@RequestMapping("/wechat")
public class WeChatController {
//登录二维码显现
@GetMapping("/login")
public void wxLogin(HttpServletResponse response) throws IOException {
response.setContentType("image/png");
QrCodeUtil.generate(WeChatUtil.getUrl(),400,400,"jpg",response.getOutputStream());
}
//回调接口
@GetMapping("/auth")
public Result callBack(String code, String state, HttpServletRequest request,
HttpServletResponse response, HttpSession session) throws IOException {
WeChatToken weChatToken = WeChatUtil.getToken(code);
System.out.println("token = " + weChatToken.getAccessToken() +"\n" +"getOpenId = " + weChatToken.getOpenid());
return weChatToken.getErrCode() == 40029?
new Result("fail", weChatToken.getErrMsg()):
new Result("success", weChatToken);
}
}
7.2.3 code换token
经过code交换token
//回调接口
@GetMapping("/auth")
public Result callBack(String code, String state, HttpServletRequest request,
HttpServletResponse response, HttpSession session) throws IOException {
WeChatToken weChatToken = WeChatUtil.getToken(code);
System.out.println("token = " + weChatToken.getAccessToken() +"\n" +"getOpenId = " + weChatToken.getOpenid());
return weChatToken.getErrCode() == 40029?
new Result("fail", weChatToken.getErrMsg()):
new Result("success", weChatToken);
}
7.2.4 token换用户数据
@GetMapping("/info")
public Result getInfo(String token,String openId) throws IOException {
WeChatUser user = WeChatUtil.getInfo(token, openId);
System.out.println("user = " + user);
return user.getErrCode()==40003?
new Result("fail","获取失利"):
new Result("success",user);
}
7.2.5 token改写
@GetMapping("/refresh")
public Result refresh(String refreshToken) throws IOException {
WeChatToken weChatToken = WeChatUtil.refreshToken(refreshToken);
return weChatToken.getErrCode()==40029?
new Result("fail","获取失利"):
new Result("success", weChatToken);
}
7.2.6 完整代码
Result
package com.example.domain;
import lombok.Data;
@Data
public class Result {
private String status;//恳求状况
private Object data;//数据
private String msg;//信息
public Result() {
}
public Result(String status, String msg) {
this.status = status;
this.msg = msg;
}
public Result(String status, Object data) {
this.status = status;
this.data = data;
}
}
WeChatToken
package com.example.domain;
import lombok.Data;
@Data
public class WeChatToken {
private String accessToken;//网页授权接口调用凭据,留意:此access_token与根底支撑的access_token不同
private String expiresIn;//access_token接口调用凭据超时时间
private String refreshToken;//用户改写access_token
private String openid;//用户仅有标识
private String scope;//用户授权的效果域
private String isSnapshotUser;//是否为快照页形式虚拟账号
private String unionId;//用户一致标识(针对一个微信敞开渠道帐号下的运用,同一用户的 unionid 是仅有的),只有当scope为"snsapi_userinfo"时回来
private Integer errCode;//过错码
private String errMsg;//过错信息
}
WeChatUser
package com.example.domain;
import lombok.Data;
@Data
public class WeChatUser {
private String openid;//用户仅有id
private String nickname;//微信昵称
private Integer sex;//性别
private String language;//语言
private String city;//城市
private String province;//省份
private String country;//国家
private String headImgUrl;//头像url
private String[] privilege;//特权
private String unionID;//用户综合id
private Integer errCode;//过错码
private String errMsg;//过错信息
}
WechatUtil
其间:RedirectUri是运用cpolar内网穿透形成的一个外网地址,微信无法验证localhost地址,请在微信敞开渠道和此次将域名和URL修改为自己的服务器指定地址或许内网穿透地址
public class WeChatUtil {
//常量区
public static final String AppId = "wxxx1234567";
public static final String AppSecret = "1122344555566678";
public static final String RedirectUri = "https://http://63c27f47.r7.cpolar.top//wechat/auth";63c27f47.r7.cpolar.top
//RedirectUri是运用cpolar内网穿透形成的一个外网地址,微信无法验证本地地址,请在微信敞开渠道和此次将域名和URL修改为自己的服务器指定地址或许内网穿透地址
//http恳求客户端
static CloseableHttpClient httpClient = HttpClientBuilder.create().build();
//办法区
/**
* Get encoded WeChat Authorization Url which embedded AppID and so on
* @return completed url
*/
public static String getUrl(){
//url要转为 UrlEncode编码格局
String CodedRedirectUri = URLEncoder.encode(RedirectUri, StandardCharsets.UTF_8);
return "https://open.weixin.qq.com/connect/oauth2/authorize?" +
"appid="+AppId+
"&redirect_uri="+CodedRedirectUri+
"&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect&forcePopup=true";
}
/**
* Get token object by code
* @param code 授权码
* @return 回来 WeChatToken 目标
* @throws IOException IO反常
*/
public static WeChatToken getToken(String code) throws IOException {
String tokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?"+
"appid="+AppId+
"&secret="+AppSecret+
"&code="+code+
"&grant_type=authorization_code";
//get恳求目标装入url
HttpGet httpGet = new HttpGet(tokenUrl);
String responseResult = "";
//建议恳求 如果恳求成功 则接收回来的数据转为UTF-8格局
HttpResponse response = httpClient.execute(httpGet);
if (response.getStatusLine().getStatusCode()==200) {
responseResult = EntityUtils.toString(response.getEntity(),"UTF-8");
}
//将结果封装到WechatToken目标 并回来
return JSON.parseObject(responseResult, WeChatToken.class);
}
/**
* Refresh token
* @param token:not accessToken,this is refresh token
* @return new Token Object
* @throws IOException IO反常
*/
public static WeChatToken refreshToken(String token) throws IOException {
String url = "https://api.weixin.qq.com/sns/oauth2/refresh_token?" +
"appid="+AppId+
"&grant_type=refresh_token" +
"&refresh_token="+token;
HttpGet httpGet =new HttpGet(url);
//履行改写
HttpResponse response = httpClient.execute(httpGet);
String jsonStr = "";
if (response.getStatusLine().getStatusCode()==200) {
jsonStr = EntityUtils.toString(response.getEntity());
}
return JSON.parseObject(jsonStr, WeChatToken.class);
}
/**
* Get user information by access_token and openID
* @param accessToken 用户拜访token
* @param openId 用户仅有id
* @return 微信用户目标
* @throws IOException IO反常
*/
public static WeChatUser getInfo(String accessToken,String openId) throws IOException{
String url = "https://api.weixin.qq.com/sns/userinfo?" +
"access_token="+accessToken+
"&openid=" +openId+
"&lang=zh_CN";
HttpGet httpGet = new HttpGet(url);
String jsonStr = "";
//履行恳求
CloseableHttpResponse response = httpClient.execute(httpGet);
if (response.getStatusLine().getStatusCode()==200) {
jsonStr = EntityUtils.toString(response.getEntity());
}
System.out.println("jsonStr = " + jsonStr);
return JSON.parseObject(jsonStr,WeChatUser.class);
}
}
WeChatController
@RestController
@RequestMapping("/wechat")
public class WeChatController {
/**
* check the link status to WeChat Public Platform
* @param signature signature
* @param timeStamp timeStamp
* @param nonce nonce
* @param echoStr echoStr
* @return the same echoStr
*/
@GetMapping("/check")
public String WXCheck(@RequestParam("signature") String signature,
@RequestParam("timestamp") String timeStamp,
@RequestParam("nonce") String nonce,
@RequestParam("echostr") String echoStr){
return echoStr;
}
/**
* Generate QRCode jumped to WeChat Authorization website
* @param response 回来图片流
* @throws IOException IO反常
*/
@GetMapping("/login")
public void wxLogin(HttpServletResponse response) throws IOException {
response.setContentType("image/png");
QrCodeUtil.generate(WeChatUtil.getUrl(),400,400,"jpg",response.getOutputStream());
}
/**
* Authorize code to get token
* @param code code
* @param state state
* @param request request
* @param response response
* @param session session
* @return result
* @throws IOException io
*/
@GetMapping("/auth")
public Result callBack(String code, String state, HttpServletRequest request,
HttpServletResponse response, HttpSession session) throws IOException {
WeChatToken weChatToken = WeChatUtil.getToken(code);
System.out.println("token = " + weChatToken.getAccessToken() +"\n" +"getOpenId = " + weChatToken.getOpenid());
return weChatToken.getErrCode() == 40029?
new Result("fail", weChatToken.getErrMsg()):
new Result("success", weChatToken);
}
/**
* Refresh token
* @param refreshToken refreshToken
* @return new token
* @throws IOException io
*/
@GetMapping("/refresh")
public Result refresh(String refreshToken) throws IOException {
WeChatToken weChatToken = WeChatUtil.refreshToken(refreshToken);
return weChatToken.getErrCode()==40029?
new Result("fail","获取失利"):
new Result("success", weChatToken);
}
/**
* Get user information
* @param token token
* @param openId openID
* @return user info
* @throws IOException io
*/
@GetMapping("/info")
public Result getInfo(String token,String openId) throws IOException {
WeChatUser user = WeChatUtil.getInfo(token, openId);
System.out.println("user = " + user);
return user.getErrCode()==40003?
new Result("fail","获取失利"):
new Result("success",user);
}
}
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>HELLO</title>
</head>
<body>
<h1>LOGIN</h1>
<a href="/wechat/login">微信登录</a>
</body>
</html>
8 OAuth2.0 – Gitee
8.1 准备工作
Gitee OAuth 文档
在Gitee官网登录后找到设置里边的第三方运用 创立第三方运用 – Gitee.com:
gitee.com/oauth/appli…
-
保存 ClientID 和 Client Secret
-
设置回调地址:Gitee和微信纷歧样,无需内网穿透,能够设置本地地址
http://127.0.0.1:8080/gitee/auth
-
主页地址效果不大,可随意填写
http://127.0.0.1:8080/page/main.html
-
权限:设置你的运用即将向用户讨取的权限
-
其余参数请自定义
8.2 完结细节
和 微信的OAuth2.0授权大致相同
Result
@Data
public class Result {
private String status;//恳求状况
private Object data;//数据
private String msg;//信息
public Result() {
}
public Result(String status, String msg) {
this.status = status;
this.msg = msg;
}
public Result(String status, Object data) {
this.status = status;
this.data = data;
}
}
GiteeUser
@Data
public class GiteeUser {
private String id;//id
private String name;//用户名
private String email;//邮箱
private String avatarUrl;//用户头像
private String url;//json-数据
private String htmlUrl;//json-用户主页
private String starredUrl;//json-用户保藏
private String blog;//用户博客衔接
private String weibo;//绑定微博
private String createdAt;//账号创立日期
private Date updatedAt;//最近项目活跃时间
}
GiteeToken
@Data
public class GiteeToken {
private String accessToken;//token
private String tokenType;//token类型
private String expiresIn;//token过期时长 86400s = 1day
private String refreshToken;//改写token
private String scope;//权限范围
private String createdAt;//token创立时间戳
private String error; //过错
private String errorDescription;//过错信息
}
GiteeUtil
public class GiteeUtil {
public static final String ClientID = "8e3exxxxxxxxxxxxxxxxxx";
public static final String ClientSecret = "88efc2c187exxxxxxxx";
public static final String RedirectUri = "http://127.0.0.1:8080/gitee/auth"; //回调地址
// public static final String RedirectUri = "https://2dbfb5d2.r7.cpolar.top/gitee/auth"; //回调地址
public static CloseableHttpClient httpClient = HttpClientBuilder.create().build();
/**
* 拼接 URL
* @return url
* @throws UnsupportedEncodingException Exception
*/
public static String getUrl() throws UnsupportedEncodingException {
String url = URLEncoder.encode(RedirectUri, StandardCharsets.UTF_8);
return "https://gitee.com/oauth/authorize?client_id=" + ClientID + "&redirect_uri=" + url + "&response_type=code";
}
/**
* 建议恳求获取Token
* @param code 校验码
* @return 回来数据
* @throws Exception exception
*/
public static GiteeToken getToken(String code) throws Exception {
//新建httpClient目标 新建post恳求目标
HttpPost postRequest = new HttpPost("https://gitee.com/oauth/token");
//post恳求目标传入值
StringEntity input = new StringEntity(
"grant_type=authorization_code&" +
"code=" + code +
"&client_id=" + ClientID +
"&redirect_uri=" + RedirectUri +
"&client_secret=" + ClientSecret);
input.setContentType("application/x-www-form-urlencoded");
postRequest.setEntity(input);
//httpClient履行 post恳求 并获取回来内容
HttpResponse response = httpClient.execute(postRequest);
HttpEntity entity = response.getEntity();
String jsonStr = EntityUtils.toString(entity);
System.out.println("JSONSTR: "+jsonStr);
//控制台
GiteeToken gt = JSON.parseObject(jsonStr,GiteeToken.class);
return gt;
}
/**
* 改写 Gitee 的 token
* @param refreshToken 从前获取到的refreshToken
* @return 回来新的 GiteeToken 目标
* @throws IOException exception
*/
public static GiteeToken RefreshToken(String refreshToken) throws IOException {
HttpPost postRequest = new HttpPost("https://gitee.com/oauth/token");
StringEntity input = new StringEntity("grant_type=refresh_token&refresh_token=" + refreshToken);
input.setContentType("application/x-www-form-urlencoded");
//数据传入办法体
postRequest.setEntity(input);
//履行恳求
HttpResponse response = httpClient.execute(postRequest);
HttpEntity entity = response.getEntity();
String jsonStr = EntityUtils.toString(entity);
System.out.println(jsonStr);
//将JSON数据实例化为GiteeToken目标
return JSON.parseObject(jsonStr, GiteeToken.class);
}
/**
* 依据用户的token获取用户的信息
* @param token access_token
* @return W
* @throws IOException exception
*/
public static GiteeUser getInfo(String token) throws IOException {
//装备
HttpGet emailGet = new HttpGet("https://gitee.com/api/v5/emails?access_token="+token);
HttpGet userGet = new HttpGet("https://gitee.com/api/v5/user?access_token="+token);
//履行恳求获取内容
HttpEntity entity1 = httpClient.execute(emailGet).getEntity();
HttpEntity entity2 = httpClient.execute(userGet).getEntity();
//获取邮箱
String jsonStr4email = EntityUtils.toString(entity1);
String substring = jsonStr4email.substring(1, jsonStr4email.length()-1);
String email = JSON.parseObject(substring).getString("email");
//获取用户
String jsonStr4User = EntityUtils.toString(entity2);
GiteeUser giteeUser = JSON.parseObject(jsonStr4User, GiteeUser.class);
giteeUser.setEmail(email);//将邮箱信息增加至用户
return giteeUser;
}
}
GiteeController
@Controller
@RequestMapping("/gitee")
public class GiteeController {
/**
* 拼接拜访地址
* @return 跳转到拼接了clientID的url
*/
@GetMapping("/login")
public String giteeLogin() throws UnsupportedEncodingException {
return "redirect:"+GiteeUtil.getUrl();
}
/**
* Gitee 登录校验
* @param code 授权校验码
* @param session session
* @return res
* @throws Exception io
*/
@GetMapping("/auth")
@ResponseBody
public Result giteeAuth(@RequestParam("code") String code, HttpSession session) throws Exception {
GiteeToken giteeToken = GiteeUtil.getToken(code);
String token = giteeToken.getAccessToken();
System.out.println("giteeToken.toString() = " + giteeToken.toString());
return giteeToken.getError() ==null ?
new Result("success",giteeToken):
new Result("fail",giteeToken.getErrorDescription());
}
/**
* Refresh token
* @param refreshToken 从前 GiteeToken的refreshToken
* @return 新 GiteeToken目标
* @throws IOException io
*/
@GetMapping("refresh")
@ResponseBody
public Result refreshToken(String refreshToken) throws IOException {
GiteeToken newGiteeToken = GiteeUtil.RefreshToken(refreshToken);
//回来改写状况
return newGiteeToken.getError()!=null?
new Result("fail",newGiteeToken.getErrorDescription()):
new Result("success",newGiteeToken);
}
/**
* Get gitee user information
* @param token token
* @return res
* @throws IOException io
*/
@GetMapping("/info")
@ResponseBody
public Result getInfo(String token) throws IOException {
return new Result("success",GiteeUtil.getInfo(token));
}
}
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>HELLO</title>
</head>
<body>
<h1>LOGIN</h1>
<a href="/gitee/login">Gitee登录</a>
</body>
</html>