github认证登陆
使用github OAuth实现用户登录
做登录功能时,允许使用第三方网站的身份,这称为"第三方登录"。
原理
github内的认证方法
在github上申请OAuth App,进入个人的Github首页,Settings->Applications->Developer applications->Register a new application
注册这个app的目的:You can enable other users to authorize your OAuth App.
您可以让其他用户授权您的OAuth应用程序。
获取code和state
<a href="https://github.com/login/oauth/authorize?client_id=1d1f99e3efc33edcbf45&redirect_uri=http://localhost:8080/callback&scope=user&state=1">登陆</a>
scope
属性列出了用户授予的附加到令牌的范围。通常,这些范围将与您要求的范围相同。但是,用户可以编辑其范围,从而有效地授予您的应用程序比您最初请求的访问权限少的权限。此外,用户可以在OAuth流完成后编辑令牌作用域。您应该意识到这种可能性,并相应地调整应用程序的行为。
处理用户选择授予您的访问权限比您最初请求的权限少的错误情况非常重要。例如,应用程序可以警告其用户或以其他方式与其用户进行通信,告知他们功能将减少或无法执行某些操作。
此外,应用程序始终可以再次将用户发送回流程,以获取其他权限,但是请不要忘记用户总是可以拒绝。
client_id就是注册给的那个,redirect_uri就是你写的回调地址,通过访问这个地址获取令牌
Name | Type | Description |
---|---|---|
client_id |
string |
Required. The client ID you received from GitHub when you registered 必需的。注册时从GitHub收到的客户端ID。 |
redirect_uri |
string |
The URL in your application where users will be sent after authorization. See details below about redirect urls应用程序中的URL,用户将在授权后发送到该URL。请参阅下面关于重定向url的详细信息。 |
login |
string |
Suggests a specific account to use for signing in and authorizing the app.建议使用一个特定的帐户来登录和授权应用程序。 |
scope |
`string | 以空格分隔的范围列表。如果没有提供作用域,对于没有为应用程序授权任何作用域的用户,作用域默认为空列表。对于已经为应用程序授权了范围的用户,不会显示带有范围列表的OAuth授权页面。相反,流的这一步将使用用户为应用程序授权的范围集自动完成。例如,如果用户已经执行了两次web流,并且授权了一个具有用户范围的令牌和另一个具有回购范围的令牌,则第三个web流不提供sc |
state |
string |
An unguessable random string. It is used to protect against cross-site request forgery attacks.不可猜测的随机字符串。它用于防止跨站点请求伪造攻击。 |
allow_signup |
string |
Whether or not unauthenticated users will be offered an option to sign up for GitHub during the OAuth flow. The default is true . Use false in the case that a policy prohibits signups.在OAuth流期间,是否会为未经身份验证的用户提供一个注册GitHub的选项。默认值为true。在策略禁止注册的情况下使用false。 |
通过获取的code和state,利用httpclient来获取AccessToken
java代码callback接口如下:
@Value("${github.client.id}")
private String id;
@Value("${github.client.secret}")
private String secret;
@Value("${github.redirect.uri}")
private String uri;
@RequestMapping("/callback")
public String callback(@RequestParam(name = "code") String code,
@RequestParam(name = "state") String state,
HttpServletResponse response) {
//通过一个DTO对象封装,接收的code state
AccessTokenDTO accessTokenDTO = new AccessTokenDTO();
accessTokenDTO.setCode(code);
accessTokenDTO.setClient_id(id);
accessTokenDTO.setClient_secret(secret);
accessTokenDTO.setState(state);
accessTokenDTO.setRedirect_uri(uri);
//得到github传回来的数据 code + Client Secret+Client id来获取token
String accessToken = githubProvider.getAccessToken(accessTokenDTO);
//通过解析封装成一个对象
GithubUser githubUser = githubProvider.getUser(accessToken);
if (githubUser != null) {
//写入数据库 }
//login success
// request.getSession().setAttribute("user",githubUser);
return "redirect:/";
} else { return "redirect:/";
}
利用获取过来的AccessToken来再次访问github来获取用户信息
其中githubprovider代码如下:
public String getAccessToken(AccessTokenDTO accessTokenDTO) {
//设置从GitHub那里获取的数据设置成josn格式
MediaType mediaType = MediaType.get("application/json; charset=utf-8");
OkHttpClient client = new OkHttpClient();
//通过okhttclient来获取github传过来的用户信息,要利用到AceessTokenDTO内的数据!
//将传过来的accesstokendto转化为json格式,通过post形式传给github
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();
//把传过来的token解析
String token = string.split("&")[0].split("=")[1];
return token;
} catch (Exception e) {
//log.error("getAccessToken error,{}", accessTokenDTO, e);
}
return null;
}
public GithubUser getUser(String accessToken) {
//通过得到的token获取user
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("https://api.github.com/user?access_token=" + accessToken)
.build();
try {
Response response = client.newCall(request).execute();
String string = response.body().string();
//封装
GithubUser githubUser = JSON.parseObject(string, GithubUser.class);
//System.out.println(string);
return githubUser;
} catch (Exception e) {
// log.error("getUser error,{}", accessToken, e);
}
return null;
}
获取的json内容如下:
//封装
JSON.parseObject(string, GithubUser.class); {
"login": "Diamondtest",
"id": 28478049,
"avatar_url": "https://avatars0.githubusercontent.com/u/28478049?v=3",
"gravatar_id": "",
"url": "https://api.github.com/users/Diamondtest",
"html_url": "https://github.com/Diamondtest",
"followers_url": "https://api.github.com/users/Diamondtest/followers",
"following_url": "https://api.github.com/users/Diamondtest/following{/other_user}",
"gists_url": "https://api.github.com/users/Diamondtest/gists{/gist_id}",
"starred_url": "https://api.github.com/users/Diamondtest/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/Diamondtest/subscriptions",
"organizations_url": "https://api.github.com/users/Diamondtest/orgs",
"repos_url": "https://api.github.com/users/Diamondtest/repos",
"events_url": "https://api.github.com/users/Diamondtest/events{/privacy}",
"received_events_url": "https://api.github.com/users/Diamondtest/received_events",
"type": "User",
"site_admin": false,
"name": null,
"company": null,
"blog": "",
"location": null,
"email": null,
"hireable": null,
"bio": null,
"public_repos": 0,
"public_gists": 0,
"followers": 0,
"following": 0,
"created_at": "2017-05-06T08:08:09Z",
"updated_at": "2017-05-06T08:16:22Z"
}
授权之后,每次登陆都不需要再次授权,可更换浏览器或者选择revoke all user tokens 就可以了!
okhttpclient的用例与介绍
介绍
OkHttp是一个HTTP客户机,默认情况下是高效的:
http/2支持允许对同一主机的所有请求共享套接字。
连接池可以减少请求延迟(如果HTTP/2不可用)。
透明GZIP缩小下载大小。
响应缓存完全避免了重复请求的网络。
OkHttpClient client = new OkHttpClient();
//获取URL
//访问URL并获取该网站返回过来的字符串
String run(String url) throws IOException {
Request request = new Request.Builder()
.url(url)
.build();
try (Response response = client.newCall(request).execute()) {
return response.body().string();
}
} public static final MediaType JSON
= MediaType.get("application/json; charset=utf-8");
OkHttpClient client = new OkHttpClient();
//发送到服务器
//通过build一个request 并将需要的参数封装到body 访问url,执行client.newCall(request).execute(),得到返回值,一般是一个json格式的字符串,当然也可以自己选择它的返回数据格式!
String post(String url, String json) throws IOException {
RequestBody body = RequestBody.create(json, JSON);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
try (Response response = client.newCall(request).execute()) {
return response.body().string();
}
}
详情参见:okhttp
github认证登陆的更多相关文章
- Liferay7 BPM门户开发之32: 实现自定义认证登陆(定制Authentication Hook)
第一步:修改liferay-hook.xml <?xml version="1.0"?> <!DOCTYPE hook PUBLIC "-//Lifer ...
- 2)实现github自动登陆获取信息
# -*- coding:utf-8 -*- # __author__ = 'lixiang' # 实现github自动登陆和获取数据 import requests from bs4 import ...
- 我了解到的新知识之—Apple Captive Portal 网页认证登陆公共Wifi
因为今天一个用户遇到选择公司WiFi后,无法弹出网页认证登陆界面的问题,随即上网搜索相关信息,因为公司内没有VPN,无法FQ,只能用bing来搜索一下相关信息了. Captive Portal听起来好 ...
- 04 自学Aruba之定制AC的protal认证登陆页面
点击返回:自学Aruba之路 04 自学Aruba之定制AC的protal认证登陆页面 方法一: 使用Aruba控制器中内置的网页界面 Configuration下MANAGEMENT>Capt ...
- Github第三方登陆详细流程
一. 流程图 二.具体实现步骤 Ⅰ.创建OAuth App 我们首先需要创建一个OAuth App,根据下图的步骤点击即可 依次填写信息,然后点Register application 然后我们可以看 ...
- JMeter CSRFToken认证登陆(正则提取器的使用)
转自:http://blog.csdn.net/lion19930924/article/details/51189210 前几天用JMeter模拟登陆,但是这个网站开启了csrf认证,因此在post ...
- linux SecureCRT ssh key认证登陆
转自:http://blog.chinaunix.net/uid-20639775-id-3207171.html 通过SecureCRT创建key登录认证 一.生成公钥/密钥对 使用SecureCR ...
- SharePoint2013基于Form(FBA)的AD认证登陆
来源于:http://www.haogongju.net/art/1964313 1. 使用SharePoint2013实现基于AD的Form认证,首先创建一个Web Application,步骤如下 ...
- asp.net core 基于角色的认证登陆
一.登陆页面的Controller [Authorize(Roles = "Admin,SuperAdmin")] public class ManageController : ...
随机推荐
- input样式重置(outline:none)
我们在写表单的时候,经常需要自定义表单的样式,当然input输入框也不例外,那么如何能写出好看一点的输入框呢? 例如简单的三个空按钮: <input type="button" ...
- SpringBoot进阶教程(六十一)intellij idea project下建多个module搭建架构(下)
在上一篇文章<SpringBoot进阶教程(六十)intellij idea project下建多个module(上)>中,我们已经介绍了在intellij idea中创建project之 ...
- Linux下各目录及其作用
目录及其作用 /:根目录,一般根目录下只存放目录,不要存放件,/etc./bin./dev./lib./sbin应该和根目录放置在一个分区中 /bin: /usr/bin: 可执行二进制文件的目录,如 ...
- 深刻剖析spring三种注入方式以及使用注解的原理
概述 注释配置相对于 XML 配置具有很多的优势: 它可以充分利用 Java 的反射机制获取类结构信息,这些信息可以有效减少配置的工作.如使用 JPA 注释配置 ORM 映射时,我们就不需要指定 PO ...
- Python Web Flask源码解读(一)——启动流程
关于我 一个有思想的程序猿,终身学习实践者,目前在一个创业团队任team lead,技术栈涉及Android.Python.Java和Go,这个也是我们团队的主要技术栈. Github:https:/ ...
- Java集合框架之TreeMap浅析
Java集合框架之TreeMap浅析 一.TreeMap综述: TreeMap在Map中的结构如下:
- 关于Springboot+thymeleaf +MybatisPlus 报错Error resolving template [index], template might not exist的问题解决
这个问题困扰了我整整一上午,各种方式,什么返回路径 ,静态资源啊 什么的,能想到的都去搞了,可是问题还是解决不了!!!我查看了一下编译文件的[target]文件夹!发现了问题所在!根本就没有编译进去! ...
- [python]打开文件操作open用法
1. 格式 handle = open(file_name, access_mode = 'r') file_name: 希望打开的文件名 access_mode: 'r'表示读取,'w'表示写入,' ...
- hdu6356 Glad You Came 杭电多校第五场 RMQ ST表(模板)
Glad You Came Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others) ...
- 深入浅出TypeScript(4)- 使用接口和类型别名
在TypeScript中,为了可以约束对象定义,提供了两个新的特性,接口和类型别名. TypeScript中的接口 在强类型语言中,都有接口的概念,那么TypeScript中的接口是如何使用的呢? 接 ...