第三方登录的原理
所谓第三方登录,实质就是 OAuth 授权。用户想要登录 A 网站,A 网站让用户提供第三方网站的数据,证明自己的身份。获取第三方网站的身份数据,就需要 OAuth 授权。
举例来说,A 网站允许 GitHub 登录,背后就是下面的流程。
- (1) A 网站让用户跳转到 Gitee。
- (2) Gitee 要求用户登录,然后询问"A 网站要求获得 xx 权限,你是否同意?"
- (3) 用户同意,Gitee 就会重定向回 A 网站,同时发回一个授权码。
- (4) A 网站使用授权码,向 Gitee 请求令牌。
- (5) Gitee 返回令牌.
- (6) A 网站使用令牌,向 Gitee 请求用户数据。
一、应用登记
一个应用要求 OAuth 授权,必须先到对方网站登记,让对方知道是谁在请求。
gitee的登记地址:https://gitee.com/oauth/applications/new
填写完毕后,Gitee 应该会返回客户端 ID(client ID)和客户端密钥(client secret),这就是应用的身份识别码。
二、编写流程代码
采用springboot+freemarker 写了一个简单的页面
1、index页面
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Title</title>
</head>
<body>
index 页面<br/>
<a href="/oauth/authorize">登录gitee</a>
</body>
</html>
2、sucess页面
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Title</title>
</head>
<body>
susss 页面<br/>
${userInfo}
</body>
</html>
3、controller
@Controller
public class Controller {
@Value("${gitee.client_id:9ba895b0ef1713d3394531613dd5a4501e934b7daa14260f815deb822708a204}")
private String client_id;
@Value("${gitee.client_secret:XXXX}")
private String client_secret;
@Value("${gitee.oauth.authorize:https://gitee.com/oauth/authorize}")
private String oauthAuthorize;
@Value("${gitee.redirect_uri:http://localhost:8080/oauth/redirect}")
private String redirect_uri;
@RequestMapping("/index")
public String index(){
return "index";
}
@RequestMapping("/oauth/authorize")
public String authorize(){
String path=oauthAuthorize+"?client_id="+client_id+"&redirect_uri="+redirect_uri+"&response_type=code";
return "redirect:"+path;
}
@RequestMapping("/oauth/redirect")
public String redirect(String code, HttpServletRequest request){
String redirectUri="http://localhost:8080/oauth/redirect";
System.out.println("code:"+code);
String url = "https://gitee.com/oauth/token?" + "grant_type=authorization_code" +
"&client_id=" + client_id +
"&redirect_uri=" + redirectUri +
"&code=" + code;
Map<String, Object> body = new HashMap<>();
body.put("client_secret", client_secret);
System.out.println(url);
String resp = HttpUtil.post(url, body);
System.out.println(resp);
JSONObject tokenResp = new JSONObject(resp);
String token = tokenResp.getStr("access_token");
System.out.println("token="+token);
String userInfo = HttpUtil.get("https://gitee.com/api/v5/user?access_token=" + token);
System.out.println("userInfo="+userInfo);
request.setAttribute("userInfo",userInfo);
return "sucess";
}
}
三、测试
1、启动项目
访问:http://localhost:8080/index
2、点击登录gitee
这个时候,调用后台接口:
http://localhost:8080/oauth/authorize
这个接口,将组装gitee的获取code的接口,重定向到gitee页面,等待我们授权。
https://gitee.com/oauth/authorize?client_id=9ba895b0ef1713d3394531613dd5a4501e934b7daa14260f815deb822708a204&redirect_uri=http://localhost:8080/oauth/redirect&response_type=code
3、我们授权后,他回调我们的接口(http://localhost:8080/oauth/redirect),带上code
后端实现
实现 /oauth/redirect 接口,从url取出授权码code之后,通过post请求到Gitee获取token
@RequestMapping("/oauth/redirect")
public String redirect(String code, HttpServletRequest request){
String redirectUri="http://localhost:8080/oauth/redirect";
System.out.println("code:"+code);
String url = "https://gitee.com/oauth/token?" + "grant_type=authorization_code" +
"&client_id=" + client_id +
"&redirect_uri=" + redirectUri +
"&code=" + code;
Map<String, Object> body = new HashMap<>();
body.put("client_secret", client_secret);
System.out.println(url);
String resp = HttpUtil.post(url, body);
System.out.println(resp);
JSONObject tokenResp = new JSONObject(resp);
String token = tokenResp.getStr("access_token");
System.out.println("token="+token);
String userInfo = HttpUtil.get("https://gitee.com/api/v5/user?access_token=" + token);
System.out.println("userInfo="+userInfo);
request.setAttribute("userInfo",userInfo);
return "sucess";
}
将code传入通过接口,获取token
https://gitee.com/oauth/token?grant_type=authorization_code&client_id=9ba895b0ef1713d3394531613dd5a4501e934b7daa14260f815deb822708a204&redirect_uri=http://localhost:8080/oauth/redirect&code=117eb3eff20d501c5080c2fa656e79ada10af4c16d3e8cfe14e937d408fbd004
4、我们获取到token后,就可以调用gitee的api获取相关的信息,例如用户信息
String userInfo = HttpUtil.get("https://gitee.com/api/v5/user?access_token=" + token);
System.out.println("userInfo="+userInfo);
5、这样我们就完成了登录授权,可以处理我们的业务,跳转到我们的成功页面。
gitee的接口文档:https://gitee.com/api/v5/oauth_doc#/
评论区