Java实现Google第三方登录
其实所有的第三方登录都是基于OAuth协议的,大多数平台都支持OAuth2.0,只有Twitter的是基于OAuth1.0来做的。所以只要弄明白一个,其他的什么qq、微信、微博的第三方登录也都一样。上一篇写的Facebook,现在再写一个Google,两篇都看完的同学就会明白“道理都是相通的”这句话的意思了!
我做第三方登录的目的仅仅是获取到用户信息,然后将用户信息和本地程序的某一部分绑定,保存到数据库,如果有同学要获取其他的信息,那就获取到accessToken后去找API即可。
下面依然是demo,只提供思路,代码写的比较简单,都写到一个类中,方便同学理解。
开发流程:
1、了解OAuth2.0
2、到Google官网注册开发者账号,创建凭据(就是应用)
3、代码实现
下面逐步介绍
1、了解OAuth2.0(非常重要)
因为第三方登录离不开OAuth协议,了解这个是必要的。
【摘自Google官网】
注:有英语基础的同学强烈建议看原文,千万不要用Google翻译,翻译完了全是坑,更糊涂!(我的英语不太好,只限于理解但是翻译不出来,所以具体的流程看下面的流程图就可以了,或者看上一篇的facebook的OAuth介绍)
算了,我还是丢回人吧,大概翻译一下流程(纯人工翻译,可能不准确,但是不会影响你的理解):
Google的OAuth2.0支持多种语言PHP, Java, Python, Ruby, ASP.NET.
这个授权从你的应用重定向到Google的url开始,你请求url时携带的参数要标明你想获取的参数类型。Google来处理用户的身份验证、session、还有用户是否授权,当用户授权成功后Google会给你返回一个授权的code(通过在应用里定义好的回调地址传回code参数),然后你就可以用这code(临时令牌)调Google API来换取access_Token(授权令牌)和refresh_Token(刷新令牌)。
你的应用需要存储这个refresh_Token(刷新令牌)留着以后你的access_Token(授权令牌)过期的时候使用,然后就可以用access_Token(授权令牌)来访问Google API 获取用户信息了。
(我去:翻译完感觉自己不会说人话了,英语不好的同学凑合着看吧,重要的理解下面的流程图)
2、到Google官网注册开发者账号,创建凭据(就是应用)
①登录Google的开发者平台,创建账号 https://developers.google.com/
②创建应用https://console.developers.google.com/apis/credentials
<1>创建凭据
创建完成后会看到客户端id和客户端秘钥(妥善保存,代码中要用)
如果那个重定向的地址没看懂的话往后看代码就理解了,然后定义同意屏幕,是用户授权登录时看到的页面
到此,应用就创建完成了
3、代码实现(分为两类同学,分别找对应自己的实现方式)
【靠自己】想自主实现的同学,我截图具体位置,慢慢摸索同样可以做出来
登录开发者平台 https://developers.google.com/ 然后跟着截图一步一步往下走
https://developers.google.com/identity/choose-auth
先照着官网写个页面体验一下,直接复制粘贴就可以https://developers.google.com/identity/sign-in/web/
体验完之后到guides页面,将基本的四部参照文档完成https://developers.google.com/identity/sign-in/web/devconsole-project
上面的四步是web页面,下面做后台验证https://developers.google.com/identity/choose-auth
上面的5步做完之后来这找获取用户信息的API(我做的时候这个接口找的很费劲)
获取用户信息选这个
想查询请求url点第二个红框,requestUrl会自动填充(这一步就是想找到获取用户信息的Url,获取到url就可以在后台调用接口了)
到此,获取到用户信息之后就可以和自己的程序进项绑定了,后面的登录逻辑视业务要求而定。
【无力者】不想自己找文档,不想思考,着急做的同学,看我上传的代码,复制粘贴就可以了
①google.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="en">
<head>
<meta name="google-signin-scope" content="profile email">
<meta name="google-signin-client_id"content='客户端ID'>
<script src="https://apis.google.com/js/platform.js" async defer></script>
</head>
<body><div class="g-signin2" data-onsuccess="onSignIn"></div><a href="#" οnclick="signOut();">Sign out</a><script>function signOut() {var auth2 = gapi.auth2.getAuthInstance();auth2.signOut().then(function() {console.log('User signed out.');});}function onSignIn(googleUser) {//跳转到http://gntina.iok.la/sendRedirect(获取用户信息)location.href = "http://gntina.iok.la/sendRedirect";//获取用户基本信息,但是此id不能给后台用,不安全,改用id_token/*从这往下的代码都不需要,因为是在后台验证,后台获取用户信息var profile = googleUser.getBasicProfile();console.log('google自己封装好的获取用户信息');console.log('ID: ' + profile.getId()); // Do not send to your backend! Use an ID token instead.console.log('Name: ' + profile.getName());console.log('Image URL: ' + profile.getImageUrl());console.log('Email: ' + profile.getEmail()); // This is null if the 'email' scope is not present.//将id_token发送给后台进行验证var id_token = googleUser.getAuthResponse().id_token;var xhr = new XMLHttpRequest();xhr.open('POST', 'http://gntina.iok.la/idToken');xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');xhr.onload = function() {console.log('Signed in as: ' + xhr.responseText);};xhr.send('idtoken=' + id_token);*/}</script>
</body>
</html>
②controller
package com.lenovo.login.controller;import java.util.HashMap;
import java.util.Map;
import java.util.UUID;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import net.sf.json.JSONObject;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;/*** @ClassName: LoginController* @Description: Google第三方登录* @author gaona* @param* @date Mar 13, 2017*/
@Controller
public class LoginController {private static String client_id = "客户端id";private static String client_secret = "客户端秘钥";private static String scope = "https://www.googleapis.com/auth/drive.metadata.readonly";private static String redirect_url = "http://gntina.iok.la/GoogleUserInfo";private static String code_url = "https://accounts.google.com/o/oauth2/v2/auth";private static String token_url = "https://www.googleapis.com/oauth2/v4/token";private static String user_url = "https://www.googleapis.com/oauth2/v2/userinfo";private static String verify_url = "https://www.googleapis.com/oauth2/v3/tokeninfo";//第一步:跳转到登录页面@RequestMapping(value = "/login")public String toIndex(HttpServletRequest request) {return "google";}/*** @Title: Login* @Description: google登录验证后会重定向到此地址,并附带访问授权码,不能为公开的ip地址* @author 此方法是用带回的code换取accessToken,然后用accessToken换取用户信息,这个地址就是在创建应用时定义的重定向地址* @return Object* @date Mar 23, 2017 10:37:38 AM* @throws*/@RequestMapping(value = "/GoogleUserInfo")@ResponseBodypublic static Object Login(HttpServletRequest request) {String code = request.getParameter("code");System.out.println(code);// String idToken = getGoogleAccessToken(code);
// System.out.println(idToken);
// JSONObject verifyToken = verifyToken(idToken);
// System.out.println(verifyToken);String accessToken = getGoogleAccessToken(code);System.out.println(accessToken);JSONObject userInfo = getUserInfo(accessToken);System.out.println(userInfo);return userInfo;}/*** @throws Exception* @throws IOException* @Title: sendRedirect* @Description:发送授权请求* @author 第二步,在google.jsp中用户登录成功以后回跳转到这个路径,发送请求让用户授权,授权成功后重定向到/GoogleUserInfo,也就是创建应用时定义的重定向地址* @return String* @date Mar 24, 2017 3:11:36 PM* @throws*/@RequestMapping(value = "/sendRedirect")public void sendRedirect(HttpServletResponse response) throws Exception {// 随机字符串,防止csrf攻击String state = UUID.randomUUID() + "";Map<String, String> params = new HashMap<String, String>();params.put("client_id", client_id);params.put("redirect_uri", redirect_url);params.put("response_type", "code");params.put("scope", scope);params.put("access_type", "offline");params.put("state", state);params.put("include_granted_scopes", "true");String url = HttpClientUtil.getUrl(code_url, params);response.sendRedirect(url);}/*** @Title: getGoogleAccessToken* @Description: 获取accessToken* @author 第三步,用重定向带回来的code换取accessToken* @return String* @date Mar 25, 2017 10:25:00 AM* @throws*/public static String getGoogleAccessToken(String code) {HashMap<String, String> params = new HashMap<String, String>();params.put("client_id", client_id);params.put("redirect_uri", redirect_url);params.put("client_secret", client_secret);params.put("grant_type", "authorization_code");params.put("code", code);String[] responseResult = null;String accessToken =null;String idToken=null;try {responseResult = HttpClientUtil.getStringByPost(token_url, params,null);} catch (Exception e) {e.printStackTrace();}if (null != responseResult && responseResult[0].equals("200")) {String result = responseResult[1];JSONObject jsonObject = JSONObject.fromObject(result);accessToken = jsonObject.getString("access_token");idToken=jsonObject.getString("id_token");}return accessToken;
// return idToken;}/*** @Title: getUserInfo* @Description: 获取用户信息* @author第四步,用accessToken获取用户信息* @return String* @date Mar 25, 2017 11:50:23 AM* @throws*/public static JSONObject getUserInfo(String accessToken) {HashMap<String, String> params = new HashMap<String,String>();params.put("access_token", accessToken);String[] responseResult =null;JSONObject userInfo=null;try {responseResult = HttpClientUtil.getStringByGet(user_url, params);} catch (Exception e) {e.printStackTrace();}if (null != responseResult && responseResult[0].equals("200")) {String result = responseResult[1];userInfo = JSONObject.fromObject(result); }return userInfo;}/*** @Title: verifyToken * @Description:验证用户token是否是来自本应用的请求,校验aud和clientID是否相同 * @author第五步,验证用户是否来自你的应用,防刷,根据需要加到逻辑里* @return String* @date Mar 25, 2017 7:36:33 PM* @throws*/public static JSONObject verifyToken(String idToken){HashMap<String, String> params = new HashMap<String,String>();params.put("id_token", idToken);String[] responseResult =null;JSONObject verifyInfo=null;try {responseResult = HttpClientUtil.getStringByGet(verify_url, params);} catch (Exception e) {e.printStackTrace();}if (null != responseResult && responseResult[0].equals("200")) {String result = responseResult[1];verifyInfo = JSONObject.fromObject(result); }return verifyInfo;}}
流程明白了以后代码就简单了,实际上一共就3个接口,接口调用的方式用的http
③httpClienUtil(没有截取全,只是部分代码供参考,怕同学们因为调接口看晕了)
/*** 返回结果说明:* String[] result* result[0] = responseCode * result[1] = responseBody* @param url* @param params* @return UTF-8* @throws Exception*/public String[] getByUtf(String url, Map<String, String>params) throws Exception {if(params != null){StringBuffer buf = new StringBuffer();for(String key : params.keySet()){buf.append(key);buf.append("=");buf.append(URLEncoder.encode(params.get(key),"UTF-8"));buf.append("&");}String bufStr = buf.toString();if(StringUtils.isNotEmpty(bufStr)){String param = bufStr.substring(0, bufStr.lastIndexOf("&"));if (-1 == url.indexOf("?")) {url += "?" + param;} else {url += "&" + param;}}}GetMethod getmethod = new GetMethod(url);getmethod.getParams().setContentCharset(UTF_CHARSET);return httpRequest(getmethod,UTF_CHARSET);}
希望可以帮助到有需要的同学,有些东西了解个大概就往下走,不要深入,不然很容易陷进去出不来,我就是不幸的那个,陷进去出不来,出来了之后才发现看了一些没用的浪费时间。
=====================================补充========================================
直接调用googleSDK的方式更简单,直接上代码:
google.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head><meta name="google-signin-scope" content="profile email"><meta name="google-signin-client_id" content="应用编号"><script src="https://apis.google.com/js/platform.js" async defer></script></head><body><div class="g-signin2" data-onsuccess="onSignIn" data-theme="dark"></div><a href="#" οnclick="signOut();">Sign out</a><script>function onSignIn(googleUser) {// 客户端如果有需要的话可以通过profile来获取用户信息var profile = googleUser.getBasicProfile();// 传回后台验证,并获取useridvar id_token = googleUser.getAuthResponse().id_token;console.log("ID Token: " + id_token);var xhr = new XMLHttpRequest();xhr.open('POST', 'http://gntina.iok.la/googleVerify');xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');xhr.onload = function() {console.log('Signed in as: ' + xhr.responseText);};xhr.send('idtokenstr=' + id_token);};function signOut() {var auth2 = gapi.auth2.getAuthInstance();auth2.signOut().then(function () {console.log('User signed out.');});}</script></body>
</html>
Controller:验证,获取用户信息
@RequestMapping(value = "/googleVerify", method = RequestMethod.POST)public void verifyToken(String idtokenstr) {System.out.println(idtokenstr);GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(new NetHttpTransport(), JacksonFactory.getDefaultInstance()).setAudience(Collections.singletonList(client_id)).build();GoogleIdToken idToken = null;try {idToken = verifier.verify(idtokenstr);} catch (GeneralSecurityException e) {System.out.println("验证时出现GeneralSecurityException异常");} catch (IOException e) {System.out.println("验证时出现IOException异常");}if (idToken != null) {System.out.println("验证成功.");Payload payload = idToken.getPayload();String userId = payload.getSubject();
// System.out.println("User ID: " + userId);
// String email = payload.getEmail();
// boolean emailVerified = Boolean.valueOf(payload.getEmailVerified());
// String name = (String) payload.get("name");
// String pictureUrl = (String) payload.get("picture");
// String locale = (String) payload.get("locale");
// String familyName = (String) payload.get("family_name");
// String givenName = (String) payload.get("given_name");} else {System.out.println("Invalid ID token.");}}
Java实现Google第三方登录相关推荐
- Java实现Facebook第三方登录
第一次接触Facebook第三方登录,可能有些地方做的并不全面,只是尝试着做了一个小demo,因为国内接入Facebook的项目并不多,并且多数都是Android或IOS的实现,所以资料也特别少,在此 ...
- Google第三方登录的实现
谷歌第三方登录实现 Controller类的实现 import cn.stylefeng.guns.core.util.HttpClientUtil; import net.sf.json.JSONO ...
- Facebook和Google第三方登录
我做的是一个web网站,需要用到facebook和google登录,在经历头铁踩了好几个坑之后,终于找到了facebook和google的第三方登录方法,顺便总结一下问题 首先总结一下具体流程:(fa ...
- Vue + Java 实现QQ第三方登录授权
一.前言 Vue 实现QQ第三方登录授权需要获取到 APP_ID和回调域地址,关于这2个的获取方式可以参考小编的另外一篇文章 Java 实现QQ第三方登录 温馨小提示: 本文基于springboot+ ...
- Java 实现QQ第三方登录
前言:很多时候我们都需要如下的第三方登录,用QQ帐号快速登录你的网站,降低注册门槛,为你的网站带来海量新用户. 下面让我们来实现吧,可以参考官网文档,也可以看我下面的操作说明 QQ第三方登录接入指 ...
- Java实现GitHub第三方登录详解
GitHub第三方登录实现效果如下: 实现流程如下: 1.注册一个GitHub账号 2.注册一个授权的网站保存一个你的Client ID和Client Secret 3.准备一个页面,有一个链接跳转到 ...
- Facebook、Google第三方登录(vue)
哎呀,好久没写blog啦,嘻嘻嘻.最近公司接触到了海外的项目所以在登录时除了用邮箱注册之后还能使用第三方登录.现在系统暂有的就是Facebook.Google和WeChat .今天主要是讲解faceb ...
- 最详细Java实现支付宝第三方登录
文章目录 概要 流程 代码 小结 概要 分享最新Java实现支付宝登录.(注:支付宝登入用个人账号登录(不非得用企业账号)即可测试,如果用沙箱环境进行测试可能会有Bug,建议用个人用户进行测试❤)如果 ...
- java实现支付宝第三方登录_Java 实现QQ第三方登录(附赠:完整代码)
老铁,转发+关注+私信 获取完整代码 前言:很多时候我们都需要如下的第三方登录,用QQ帐号快速登录你的网站,降低注册门槛,为你的网站带来海量新用户. 下面让我们来实现吧,可以参考官网文档,也可以看我下 ...
最新文章
- php 魔术方法 多继承,day23:单继承多继承菱形继承__init__魔术方法
- 什么是restful风格?
- 周志华《机器学习》课后习题(第七章):贝叶斯分类
- 横向全屏滑动插件_【案例】JQuery横向手风琴图片轮播切换代码
- java 定义和导入包
- Docker容器虚拟化技术---Docker运维管理(Swarm集群管理)3
- Entity Framework加载相关实体——Eager Loading
- 多进程和多线程的区别_关于多进程和多线程的那些事儿
- Atitit sql的执行功能 目录 1. 主要流程	1 1.1. 获取conn,执行sql取得结果,	1 1.2. Orm类的执行(hb mybatis为例	1 2. 常见sql执行框架与类库	1
- python文本筛选html,从html页面的列表元素中筛选数据
- npcap关闭_Npcap.资料
- 红外遥控接收发射原理及ESP8266实现
- dfuse API 添加新分类查询,为您提供更多细化的搜索
- 使用CSS完成用户注册页面;
- logback高级特性使用(一)
- surface pen未接触屏幕就有反应 解决办法
- mkfs fat32 卷标 linux,fdisk_mkfs分区格式化课件.pdf
- Xposed指纹支付插件 安卓版
- 【产业互联网周报】互联网集体进入调整期:张勇兼任阿里云总裁,卢伟冰晋升小米集团总裁,小鹏组织架构调整;...
- 百度离破产只有30天