前言
在前面项目的学习中用来练手的都是本地的项目,进行一个用户名和密码登录即可,也做过一些的限制操作等,比如在登录时候对于用户名(电话号码的验证等等)详情见秒杀项目登录设计,但也都是本地的登录,不需要验证码,也不需要授权等,也就没有上线的可能性。所以就想着来记录和写一些关于第三方授权登录的文章。之前也做过关于短信验证码的登录,但是短信验证购买的是腾讯一年的短信验证服务(后续会出一个教程和demo),这里就不作具体的介绍。今天这里来介绍一下Github第三方验证登录,后续的还有gitee,QQ和邮箱验证登录。我也会做成小的demo放在Github
,供大家学习。
首先来看一下自己的社区登录图,其中有注册邮箱登录,和第三方登录。
正文
既然学习到如何使用Github来做第三方登录,就需要我们先去官网查看文档,一般对于网站可以用来接入第三方的登录,在网站下方都会有一个API其中有一个具体的授权登录等,这里就直接贴出具体的地址Github第三方登录文档英文好的小伙伴可以直接观看原生文档,就是一个单点登录,有学习和了解过基础的原理的看起来应该不算是困难。
在大致完成了文档的阅读之后,下面就直接开始介绍具体的流程:
创建App
这里就不再具体贴图如何进入到这个页面(Settings->Developer Settings->Oauth Apps)
进入之后,点击新建,填写下面的信息:
解释:Homepage URl 就是我们网站后续上线之后的上线地址,下面的Authorization callback URL
原本填写应该是https://community.maycope.cn/callback
,但是现在没有服务器用来部署项目,我们就可以写成本地项目地址和端口号,在调用时候,就会调用本地进行验证登录。
点击Register application,上传自己的app的头像即可,注意可以先将ID和 Secret复制下来。
若是以上图片可能讲解不是很清楚可以查看如下具体创建app创建app
图解流程:
- 首先我们用户访问网站首页,点击登录时候进行的是
1.1
就是自己逻辑的构造,将那些client ID
和redirect_uri
进行一个处理,然后才会发送到Github上的https://github.com/login/oauth/authorize
(这些信息文档里都有写到),进行验证授权,这个时候,Github会回调我们的redirect-uri,携带code信息,如1.2.1
- 本地收到地址之后,解析出code,然后再度调用
https://github.com/login/oauth/access_token
携带code
和secret
和下面的所有信息,这里进行了一个封装的处理。
- 在完成了调用之后,如果携带的
access_token
是正确的,Github会返回这个具体的access_token
,网站(我们的)就可以根据这个返回回来的进行调用用户的具体信息,这里我们可以进行模拟生成一个access_token
看看网站会给我们返回什么信息:
1.如下我们生成一个access_token,选择下方的user,这里没有截图完整。
- 将生成的进行复制。
- 访问如下网址,并且携带上自己的token信息。可以看到返回给我们的信息1,有id,name等。
- 将生成的进行复制。
- 前面返回的access_token,就可以用来调用user信息。
- 就可以将用户的信息存入到数据库里面并且对用户的状态进行更新处理。
- 返回给用户,登录成功,进入到系统中。
- 以上就是全部的流程处理信息。具体变成如下。
编程实现
以上完成了讲解之后,其实发现并不难理解,就是第一次接触可能会有一些困难,这里就将这部分代码集成到miaosha_2
模块,因为对于模块二也是登录设置,可以进行同时的学习,这部分代码会放到我的个人仓库,地址如下【超链接】,先暂时完成一个小模块(对于数据库模块,可以保存到数据库中,表的设计也有实现,但是就是对于用户信息更改的情况,这里暂时没有做一个编写,大家可以自行对用户数据更改的情况进行设计)
授权登录获取access_token
首先来看具体的登录按钮设计,就如我们前面所讲,访问authorize
时候携带上code和redirect_uri
<div style="margin-top: 25px">
<h4>第三方账号登录</h4>
<a th:href="@{https://github.com/login/oauth/authorize(client_id=${@environment.getProperty('github.client_id')},redirect_uri=${@environment.getProperty('github.redirect_uri')},scope='user',state='githublogin')}"
class="login-style">
<img src="/images/github.svg" style="width: 20px;height: 20px">
Github登录
</a>
</div>
然后github会回调我们的地址,这里先行贴出在配置文件中的内容,就可以回调如下地址,我们再来看该接口下是如何对参数进行接收和验证。
github:
client_id: 63fcee0c9a2ad4f0XXXX
client_secret: XXXXX685e5db5cd0320ad12331e9e1772ceXXXXX
redirect_uri: http://localhost:8887/githubCallback
githubCallback
- 首先对数据进行封装,因为需要一些
id
和secret
和redirect_uri
,然后获取到access_token
@GetMapping("/githubCallback")access_token
public String callback(@RequestParam("code")String code,
@RequestParam("state") String state,
HttpServletResponse response,
Model model) {
setAccessTokenDto(code,state,githubConfig.getClient_id(),githubConfig.getClient_secret(),githubConfig.getRedirect_uri());
String accessToken= githubProvider.getAccessToekn(accessTokenDto);// 获取access_toke
}
private void setAccessTokenDto(String code, String state, String clientId, String clientSecret, String redirectUri) {
accessTokenDto.setClient_id(clientId);
accessTokenDto.setClient_secret(clientSecret);
accessTokenDto.setCode(code);
accessTokenDto.setRedirect_uri(redirectUri);
accessTokenDto.setState(state);
}
getAccessToken对于如何发送请求这里使用到了Okhttp,具体学习见okhttp官网文档对请求的参数和需要什么配置讲解都很清楚了。
可以看到发送到https://github.com/login/oauth/access_token
获取token信息。
public String getAccessToekn(AccessTokenDto accessTokenDto){
MediaType mediaType = MediaType.parse("application/json; charset=utf-8");
OkHttpClient client = new OkHttpClient();
//将accessTokenDto转为json字符串传入参数
RequestBody body = RequestBody.create(mediaType, JSON.toJSONString(accessTokenDto));
Request request = new Request.Builder()
.url("https://github.com/login/oauth/access_token")
.post(body)
.build();
try (Response response = client.newCall(request).execute()) {
String string = response.body().string();
//得到的是类似这样的字符串,我们需要将它分割,只要access_token部分
//access_token=9566ba3483a556c610be42d44338f3fd16a3b8d1&scope=&token_type=bearer
return string.split("&")[0].split("=")[1];
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
根据获取到的token信息请求用户信息
在上面获取到token以后,再度请求https://api.github.com/user获取用户信息。
@GetMapping("/githubCallback")
public String callback(@RequestParam("code")String code,
@RequestParam("state") String state,
HttpServletResponse response,
Model model)
{
setAccessTokenDto(code,state,githubConfig.getClient_id(),githubConfig.getClient_secret(),githubConfig.getRedirect_uri());
String accessToken= githubProvider.getAccessToekn(accessTokenDto);
// 获取用户信息。
GithubUser githubUser=githubProvider.getGithubUser(accessToken);
}
void setUserInfo(String token, String name, String avatarUrl, String accountId, String bio) {
GithubUsers user = new GithubUsers();
user.setToken(token);
user.setName(name);
user.setAvatarUrl(avatarUrl);
user.setAccountId(accountId);
user.setBio(bio);
githubUserService.createOrUpdateUser(user);
}
githubProvider
/**
* 根据access_token获取用户信息
*
* @param access_token
* @return
*/
public GithubUser getGithubUser(String access_token) {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("https://api.github.com/user")
.header("Authorization", "token " + access_token)
.build();
try (Response response = client.newCall(request).execute()){
//得到的是json字符串,因此需要转为GithubUser对象
String str = response.body().string();
return JSON.parseObject(str, GithubUser.class);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
将用户信息存储到cookie中:
@GetMapping("/githubCallback")
public String callback(@RequestParam("code")String code,
@RequestParam("state") String state,
HttpServletResponse response,
Model model)
{
setAccessTokenDto(code,state,githubConfig.getClient_id(),githubConfig.getClient_secret(),githubConfig.getRedirect_uri());
String accessToken= githubProvider.getAccessToekn(accessTokenDto);
GithubUser githubUser=githubProvider.getGithubUser(accessToken);
//用户信息不为空 存储起来
if(githubUser!=null && githubUser.getId()!=null)
{
String token= UUID.randomUUID().toString();
setUserInfo(token, githubUser.getName(), githubUser.getAvatarUrl(), "Github-" + githubUser.getId(), githubUser.getBio());
// 存储。
CookieUtils.setCookie(response, "token", token, COOKIE_EXPIRY);
model.addAttribute("name",githubUser.getName());
return "goods_list";
} else {
throw new GlobalException(CodeMsg.LOGIN_ERROR);
}
}
setCookie
以下代码的讲解可以见获取cookie信息
public static void setCookie(HttpServletResponse response, String name, String value, int expiry){
Cookie cookie=new Cookie(name,value);
cookie.setMaxAge(expiry);
response.addCookie(cookie);
}
以上就是对主题部分的学习与讲解,这里有想要进行深入视频学习的可以参见B站8-14p里有具体的讲解。
测试
完成之后我们来看对于我的示例,我们不仅可以使用到我们原来的手机号码登录的方式,还可以使用到github第三方登录。
登录成功之后页面,可以看到显示出我的GitHub名称。
后记
以上就是关于github授权登录的学习与讲解,也算是我第二次学习的记录。有什么具体的问题欢迎私信。文章看起来虽然不是很长,但是要自己全部明白其中的意思,我还是写了很久的。
下面贴出Github地址源码地址,若是大家觉得还行,欢迎大家给一个小小star和关注(虽然很菜),后续也会推出更多有价值的实例。