第三方登录实现

第三方登录

自建了一个网站,想要增加一个登录入口,但是自己实现登录又很麻烦, 那么就可以尝试使用第三方登录的方式。

谈到第三方登录就不得不提到OAuth,OAuth是Open Authorization的简写,它就是一种授权机制。数据的所有者告诉系统,同意授权第三方应用进入系统,获取这些数据。系统从而产生一个短期的进入令牌(token),用来代替密码,供第三方应用使用。
底层协议:
OAuth协议为用户资源的授权提供了一个安全、开放而又简易的标准。使用OAuth授权不会使第三方获取到到用户的帐号信息(如用户名与密码等),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此OAuth是安全的。

此处简单介绍下第三方登陆的实现,此处以QQ登录和GitHub登录为例,其他第三方登录大同小异。建议申请GitHub的方式, 这个可以不用申请域名进行本地测试,如果使用QQ作为第三方登录的话申请比较严格,需要先申请域名并且备案,而备案一般需要一周到两周的时间,比较麻烦。

QQ登录SDK方式

申请QQ互联

接入QQ互联,实现QQ一键登录。这个需要你提前备好域名,如果没有自己的网站的话,可以使用GitHub的测试,毕竟一个好的域名也挺贵的!!!
在这里插入图片描述

1 进入QQ互联官网点击头像创建提交申请
在这里插入图片描述

2 选择个人接入,按照步骤填写注册资料
在这里插入图片描述

创建成功通过后会显示接入的个人信息。

3 审核成功后点击下面的开始创建,按步骤完成创建过程。
开始创建

4 创建成功后可以查看APP IDAPP key,很重要
创建信息
在应用管理界面可以查看如上信息,点击查看就可以看到如下关键信息。
APP信息
下面的平台信息里可以看到网站地址和网站回调域,

QQ登录实现

  1. 新建登录页面
<a href"/login">qq登录</a>
  1. 配置qqconnectconfig.properties,与application.properties同一级
app_ID = 你的App ID
app_KEY = 你的App key
redirect_URI = 你的回调域
scope = get_user_info,add_topic,add_one_blog,add_album,upload_pic,list_album,add_share,check_page_fans,add_t,add_pic_t,del_t,get_repost_list,get_info,get_other_info,get_fanslist,get_idollist,add_idol,del_ido,get_tenpay_addr
baseURL = https://graph.qq.com/
getUserInfoURL = https://graph.qq.com/user/get_user_info
accessTokenURL = https://graph.qq.com/oauth2.0/token
authorizeURL = https://graph.qq.com/oauth2.0/authorize
getOpenIDURL = https://graph.qq.com/oauth2.0/me
addTopicURL = https://graph.qq.com/shuoshuo/add_topic
addBlogURL = https://graph.qq.com/blog/add_one_blog
addAlbumURL = https://graph.qq.com/photo/add_album
uploadPicURL = https://graph.qq.com/photo/upload_pic
listAlbumURL = https://graph.qq.com/photo/list_album
addShareURL = https://graph.qq.com/share/add_share
checkPageFansURL = https://graph.qq.com/user/check_page_fans
addTURL = https://graph.qq.com/t/add_t
addPicTURL = https://graph.qq.com/t/add_pic_t
delTURL = https://graph.qq.com/t/del_t
getWeiboUserInfoURL = https://graph.qq.com/user/get_info
getWeiboOtherUserInfoURL = https://graph.qq.com/user/get_other_info
getFansListURL = https://graph.qq.com/relation/get_fanslist
getIdolsListURL = https://graph.qq.com/relation/get_idollist
addIdolURL = https://graph.qq.com/relation/add_idol
delIdolURL = https://graph.qq.com/relation/del_idol
getTenpayAddrURL = https://graph.qq.com/cft_info/get_tenpay_addr
getRepostListURL = https://graph.qq.com/t/get_repost_list
version = 2.0.0.0
  1. 导入SDK依赖
<!--QQ登录-->
<!-- https://mvnrepository.com/artifact/net.gplatform/Sdk4J -->
<dependency><groupId>net.gplatform</groupId><artifactId>Sdk4J</artifactId><version>2.0</version>
</dependency>
  1. 登录请求与回调请求
	 //获取用户当前页面的url,方便返回登录之前的页面,private static String returnUrl = ""	/*** @Description: qq登录的入口*/@GetMapping("/login")public ResponseEntity<Void> loginByQQ(HttpServletRequest request, HttpServletResponse response){returnUrl = request.getParameter("returnUrl");response.setContentType("text/html,charset=utf-8");try {response.sendRedirect(new Oauth().getAuthorizeURL(request));return ResponseEntity.ok().build();} catch (IOException | QQConnectException e) {LOGGER.warn("请求QQ登录失败, {}",e.getMessage());}return ResponseEntity.badRequest().build();}/**** 此处的qqlogin必须与你的网站回调域一致* @Description: 登录获取数据*/@RequestMapping("/qqlogin")public String login(HttpServletRequest request,HttpServletResponse response){User user = new User();try {AccessToken accessTokenObj = (new Oauth()).getAccessTokenByRequest(request);//用来或用户信息,get_user_info参数String accessToken   = null;String openID = null;long tokenExpireIn = 0L;if (accessTokenObj.getAccessToken().equals("")) {LOGGER.error("没有获取到响应参数");}else {accessToken = accessTokenObj.getAccessToken();tokenExpireIn = accessTokenObj.getExpireIn();System.out.println(String.valueOf(tokenExpireIn));// 利用获取到的accessToken 去获取当前用的openid -------- startOpenID openIDObj =  new OpenID(accessToken);openID = openIDObj.getUserOpenID();UserInfo userInfo = new UserInfo(accessToken, openID);UserInfoBean userInfoBean = userInfo.getUserInfo();/** 此处获取用户信息后可以重新保存用户部分信息用作登录展示* 比如写一个UserInfo类用于信息展示,将UserInfo对应的用户信息通过加密的方式保存到* Cookie中,由于每次请求都会携带Cookie,然后解密重新设置过期时间再进行加密保存。* 用户退出就可以将Cookie信息删除,这样就不需要依赖QQ登录本身保存的信息了。*/if (userInfoBean.getRet()==0){//获取qq空间头像,暂不知怎么获取qq头像user.setAvatar(userInfoBean.getAvatar().getAvatarURL50());//用户openId,唯一标识user.setOpenId(openID);//用户qq昵称user.setNickName(userInfoBean.getNickname());//用户性别user.setGender(userInfoBean.getGender());}else {LOGGER.warn("很抱歉,我们没能正确获取到您的信息,原因是:{} ", userInfoBean.getMsg());}}} catch (QQConnectException e) {LOGGER.error("qq连接发生异常 {}",e.getMessage());}return "redirect:"+returnUrl;}

获取用户信息API

get_user_info

通过上面的方法可以获取的用户信息较少,并且获取的头像是QQ空间的头像而不是QQ头像,如果没有QQ空间的话,那么就没有用户头像了。可以通过get_user_info获取用户更多的信息,比如QQ头像!

新建一个用户信息实体类

在这里插入图片描述

根据返回的json创建用户对象
return用户信息

用户信息获取测试

构建用户信息实体类

/***@JsonIgnoreProperties(ignoreUnknown = true) 忽略部分不能匹配的字段*@JsonProperty(value = "***"),因为获取的用户信息json不符合命名规范,所有需要添加字段映射* @author 苍晓*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class ResultInfo {private int ret;private String msg;@JsonProperty(value = "is_lost")private boolean isLost;private String nickname;private String gender;@JsonProperty(value = "gender_type")private String genderType;private String province;private String city;private String year;private String constellation;private String figureurl;@JsonProperty(value = "figureurl_1")private String figureUrl1;@JsonProperty(value = "figureurl_2")private String figureUrl12;@JsonProperty(value = "figureurl_qq_1")private String figureUrlQq1;@JsonProperty(value = "figureurl_qq_2")private String figureUrlQq2;@JsonProperty(value = "figureurl_qq")private String figureUrlQq;@JsonProperty(value = "figureurl_type")private String figureUrlType;@JsonProperty(value = "is_yellow_vip")private String isYellowVip;private int vip;@JsonProperty(value = "yellow_vip_level")private int yellowVipLevel;private int level;@JsonProperty(value = "is_yellow_year_vip")private String isYellowYearVip;}

RestTemplate配置

/*** @author 苍晓*/
@Configuration
public class RestTemplateConfig {@Beanpublic RestTemplate getRestTemplate(){RestTemplate restTemplate = new RestTemplate();MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();/**经过尝试,此处需要加一个MediaType.TEXT_HTML的返回类型,否则一直报错,解析不了返回信息。*/mappingJackson2HttpMessageConverter.setSupportedMediaTypes(Arrays.asList(MediaType.APPLICATION_JSON,MediaType.TEXT_HTML));restTemplate.getMessageConverters().add(mappingJackson2HttpMessageConverter);return restTemplate;}
}

测试获取用户信息

@Autowired
private RestTemplate restTemplate;private final String preUrl="https://graph.qq.com/user/get_user_info?" +"access_token=获取的登录用户AccessToken" +"&oauth_consumer_key=你的AppID" +"&openid=获取的登录用户的openID";
@Test
void qqInfo() {String object = this.restTemplate.getForObject(preUrl, String.class);ObjectMapper objectMapper = new ObjectMapper();try {ResultInfo resultInfo = objectMapper.readValue(object,ResultInfo.class);System.out.println(resultInfo);} catch (JsonProcessingException e) {e.printStackTrace();}
}

GitHub登录非SDK方式

申请GitHub第三方登录

  1. 登录后找到头像下的setting,然后选择Developer setting

setting

  1. 选择New GitHub App 填写相关信息

在这里插入图片描述

  1. 点击new client secret生成client secret,记住Client ID和 Client Secret

GitHub登录实现

@Controller
public class GitHubLoginController {private static String CLIENT_ID = "申请的GitHub clientID";private static String CLIENT_SECRET = "申请的CLIENT_SECRET";private static String REDIRECT_URL = "http://127.0.0.1:8080/githubCallback";@Autowiredprivate RestTemplate skipRestTemplate;private String state;@GetMapping("/githubLogin")public String  login() throws IOException {// Github认证服务器地址String url = "https://github.com/login/oauth/authorize";// 随机字符串,用于防止CSRF攻击state = String.valueOf(UUID.randomUUID()).replaceAll("-","");// 传递参数String param = "client_id=" + CLIENT_ID + "&state=" + state + "&redirect_uri=" + REDIRECT_URL;//请求Github认证服务器url = url + "?" + param;return "redirect:"+url;}/*** GitHub回调方法* @param code 授权码* @param state 发送时的随机字符串*/@GetMapping("/githubCallback")public String  githubCallback(@RequestParam("code") String code, @RequestParam("state") String state) throws Exception {//1 验证state,如果不一致,可能被CSRF攻击if(!this.state.equals(state)) {throw new Exception("State验证失败");}// 2、向GitHub认证服务器申请令牌String tokenUrl = "https://github.com/login/oauth/access_token";// 申请令牌,Map<String,String> paramMap = new HashMap<>();paramMap.put("client_id",CLIENT_ID);paramMap.put("client_secret",CLIENT_SECRET);paramMap.put("code",code);String result = skipRestTemplate.postForObject(tokenUrl,paramMap,String.class);//3 申请资源String userUrl = "https://api.github.com/user";HttpHeaders headers = new HttpHeaders();//认证token放在报文头headers.set("Authorization", "token "+result.split("=")[1].split("&")[0]);HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<>(null, headers);ResponseEntity<String> responseEntity = skipRestTemplate.exchange(userUrl, HttpMethod.GET, httpEntity, String.class);// 4、输出用户信息String userInfo = responseEntity.getBody();System.out.println(userInfo);return "index.html";}
}

SSL异常处理

参考链接https://www.cnblogs.com/qq931399960/p/11904157.html

因认证服务器是https请求,可能会报SSLException错误或报如下错误,请使用忽略SSL验证的方式请求

Unexpected error: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty

@Component
public class SecondSkipVerifyRestTemplateBuilder {@Bean("skipRestTemplate")public RestTemplate verifyCaRestTemplate() {RestTemplate rest = new RestTemplate();SSLConnectionSocketFactory ssLSocketFactory = null;try {ssLSocketFactory = sslFactory("PKCS12", "abc123");} catch (Exception e) {e.printStackTrace();}HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory(HttpClients.custom().setSSLSocketFactory(ssLSocketFactory).build());// 设置传递数据超时时长httpRequestFactory.setReadTimeout(3000);rest.setRequestFactory(httpRequestFactory);return rest;}public SSLConnectionSocketFactory sslFactory(String keyStoreType, String keyPassword) {SSLConnectionSocketFactory sslConnectionSocketFactory = null;try {SSLContext sslcontext = SSLContexts.custom()// //忽略掉对服务器端证书的校验.loadTrustMaterial((TrustStrategy) (chain, authType) -> true).build();sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1.2" }, null,SSLConnectionSocketFactory.getDefaultHostnameVerifier());} catch (Exception e) {e.printStackTrace();}return sslConnectionSocketFactory;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/59448.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

登录等第三方认证-outh2原理与分析

看了很多关于outh2应用文章&#xff0c;介绍都比较晦涩难懂&#xff0c;同时没有一个实际案例说明&#xff0c; 下面&#xff0c;我将使用securityouth2简单案例讲解&#xff0c;并通过微信认证流程解释为什么这种实现方式是最佳的。 1. Security实现Outh2登录 1.1 项目环境搭…

论文管理系统(登录功能)

目录 一、后端部分 1.1 实体类 1.2 UserMapper类 1.3 Service层 接口 实现类 1.4 controller层 1.5 拦截器 二、前端部分 效果图 源码如下 代码讲解 准备工作和数据库都已经准备好了,接下来我们来写登录功能,登录功能我们通过mybatisplus来码写,所以不需要在UserMapper.…

行人仿真仿而不真——基于Unity将外部仿真数据可视化

0 前言 Unity作为一款生态成熟、扩展性强、学习成本较低的三维引擎&#xff0c;近年来受到各领域研究者的青睐。具体到行人仿真领域&#xff0c;相较于传统的C/Python平台&#xff0c;Unity在效果呈现及数据交互方面具备无可比拟的优势&#xff0c;国外开发者基于Unity已经实现…

教你怎样用Python画了一棵圣诞树,快来学习

本文的文字及图片来源于网络,仅供学习、交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理。 以下文章来源于IT入门 分享给大家一篇文章&#xff0c;教你怎样用Python画了一棵圣诞树&#xff0c;快来学习。 如何用Python画一个圣诞树呢&#xff1f; 最简单&…

分享10个Python绘制圣诞树的源码,拿来即用

大家好&#xff0c;我是丁小杰。 圣诞节就要到了&#xff0c;作为一个的“程序猿”&#xff0c;怎么能够少得了绘制圣诞树呢&#xff0c;今天就和大家分享 10 个圣诞树的绘制源码&#xff0c;拿来即用&#xff01; 搞笑版 height 5 stars 1 for i in range(height):print((…

Python代码画圣诞树--turtle绘图

效果图 代码如下 import turtle as t import random import pygame import threading import time import tkinter as tkt.screensize(bgblack) # 定义背景颜色&#xff0c;可以自己换颜色def loving_heart(r):l 2 * rt.left(45)t.forward(l)t.circle(r, 180)t.right(90)t.c…

教你用 python 画圣诞树

圣诞节快到了&#xff0c;教你用 python 画圣诞树&#xff0c;送给你女朋友&#xff0c;博主给了三个版本的圣诞树。 博主没有下载专门写 python 的 pycharm&#xff0c;用 VSCode 替代&#xff0c;因为 VSCode 也可以运行 python 代码。 还需要下载一个 python 运行环境&…

用python画圣诞树-使用python图形模块turtle库绘制樱花、玫瑰、圣诞树代码实例

今天为大家介绍几个Python"装逼”实例代码&#xff0c;python绘制樱花、玫瑰、圣诞树代码实例&#xff0c;主要使用了turtle库 Python绘制樱花代码实例 动态生成樱花 效果图&#xff08;这个是动态的&#xff09;&#xff1a; 实现代码 import turtle as T import ra…

【圣诞快乐】如何用代码画一颗圣诞树?

文章目录 一、前言二、创意角度三、java swing版 效果展示四、java swing版 实现步骤&代码五、springboot项目banner版 效果展示六、springboot项目banner版 实现步骤七、 linux shell界面打印版 效果展示八、 linux shell界面打印版 实现步骤 一、前言 一年一度的圣诞节来…

美美的圣诞树画出来-CoCube

2022年圣诞节到来啦&#xff0c;很高兴这次我们又能一起度过~ CSDN诚邀各位技术er分享关于圣诞节的各种技术创意&#xff0c;展现你与众不同的精彩&#xff01;参与本次投稿即可获得【话题达人】勋章【圣诞快乐】定制勋章&#xff08;1年1次&#xff0c;错过要等下一年喔&#…

圣诞树【Python版】小刘教你画圣诞树

平台准备&#xff1a; 首先安装Python及其编写平台&#xff1a; 此处小刘选择的是Python3.6版本以及PyCharm编写平台 其次安装Python所需的相关包“turtle”以及“random” Python相关包安装&#xff1a; 首先查看Python是否安装&#xff1a; 打开PyCharm在Terminal窗口输…

Python画圣诞树和烟花源代码

最近一直想让女朋友开心开心&#xff0c;眼看就到圣诞了&#xff0c;就想着来个不一样的&#xff0c;给她画个圣诞树玩一玩&#xff0c;也算是自己亲手做的&#xff0c;用了心思了。看了关于画圣诞树的很多博客&#xff0c;人才确实很多啊&#xff0c;鄙人不才&#xff0c;也加…

用python画圣诞树的代码

如何用python画一个圣诞树呢&#xff1f; 一、最简单的绘制圣诞树 代码也特别简单&#xff1a; # 最简单的绘制圣诞树height 5 # 树的高度 stars 1 # 树的雪花数&#xff0c;初始为1 for i in range(height): #…

【送给她的圣诞礼物】尝试用turtle画圣诞树

尝试用turtle画圣诞树 前言开发环境步骤一&#xff1a;加载bgm所念皆星河步骤二&#xff1a;窗口界面初始化步骤三&#xff1a;turtle初始化步骤四&#xff1a;画树的外轮廓步骤五&#xff1a;画雪花步骤六&#xff1a;画花朵步骤七&#xff1a;画五角星开源 前言 今天就是平安…

用 Python 画圣诞树的 N 种玩法

作者 | 写代码的明哥 来源 | Pyhton编程时光 马上就是圣诞节了&#xff0c;先提前祝大家圣诞快乐&#xff01; 今天来给大家分享一波如何使用 Python 来画一颗圣诞节树&#xff0c;包含多种版本&#xff0c;从平民版到豪华版&#xff0c;像极了一个程度员从入门到高级秃头程序员…

圣诞节到了,教大家用 Python 绘制几棵圣诞树~

大家好&#xff0c;我是大飞 今天是圣诞节&#xff0c;先在这里祝大家圣诞节快乐~~&#xff0c;用英语来表达就是 Merry Christmas ~~&#xff0c; 为了贴合这个氛围&#xff0c;今天分享五种用 Python 绘制圣诞树的方法&#xff0c;从基础到高级&#xff0c;效果也不断攀升分…

【圣诞来了】3分钟教你用java画一颗彩色圣诞树,送给别人作为圣诞礼物吧

⭐️写在前面 这里是温文艾尔の学习之路&#x1f44d;如果对你有帮助&#xff0c;给博主一个免费的点赞以示鼓励把QAQ&#x1f44b;博客主页&#x1f389; 温文艾尔の学习小屋⭐️更多文章&#x1f468;‍&#x1f393;请关注温文艾尔主页&#x1f345;文章发布日期&#xff1a…

如何用python画圣诞树(附圣诞树代码)

python圣诞树代码 1、简单的绘制圣诞树 新建tree1.py或者直接输入下面代码运行 #声明树的高度 height 5 #树的雪花数&#xff0c;初始为1 stars 1 #以数的高度作为循环次数 for i in range(height): print((’ ’ * (height - i)) (’*’ * stars)) stars 2 #输…

【AI金融】Can ChatGPT Forecast Stock Price Movements? Return Predictability and Large Language Models

titleChatGPT能够预测股票走势吗&#xff1f;回到可预测性与大预言模型出版时间2023年4月6日doiarXiv:2304.07619v3 [q-fin.ST]期刊arXiv类别Null关键词Statistical Finance (q-fin.ST); Computation and Language (cs.CL)文章链接https://arxiv.org/abs/2304.07619 ChatGPT可以…

AIGC—— 内容生产力革命的起点

作者简介&#xff1a;一名云计算网络运维人员、每天分享网络与运维的技术与干货。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 目录 前言 一.AIGC 1.什么是AIGC? 2.AIGC有哪些优势与挑战 &#xff08;1&#xff0…