文章目录

  • 实现思路
  • QQ登录
  • 总结

实现思路

创业初期
归结为创业初期是因为这个时候用户量比较少,甚至还没有接入上面所说的其他第三方的账户系统,只是自建的体系就可以满足,自建体系的话,目前常用的有

用户名密码注册登陆
这种方式在很多初期网站建设会使用,先注册,再进行登录,在老一点的cms中都能找到这个影子。

流程图:

流程说明:

前端将用户名、密码发送到服务器,服务器进行常规的判断,判断用户名、密码长度是否满足,用户名是否重复等条件,条件不通过直接返回对应错误码给到前端,这里密码字段,为了防止传输过程中被截胡,建议加密再上传,我们的传输密码默认都是会进行一个md5加密,然后记录到数据库再进行一层加密,就算是脱库也没事,密码不要明文存储。

校验通过后,就将用户名密码写入数据库,并进行后面积分发放等操作,这里不展开。

现在进行登录,前端将用户名,密码发送给到服务端,服务端首先会校验登录次数是否超过设置的阈值,如果超过只能继续等待被关小黑屋。

如果未超过继续登录逻辑,判断用户名、密码是否正确,不正确密码则进行阈值的判断,如果超过则关小黑屋,记住小黑屋必须设置过期时间,要不然就会永久关上了,这个可以用redis的过期来做。

登录成功后进行后续的一切后置逻辑,比如加积分。。。等操作。

手机号注册登陆
流程图:

流程说明:

首先输入手机号,然后发送到服务端,服务端将手机号记录在我们数据库中,然后生成随机验证码,并将手机号和验证码绑定到一个redis里面,然后记录过期时间,这个过期时间一般是10分钟左右,这就是我们一般手机验证码的有效期。

手机接收到手机短信后,那么就在界面填写验证码发送服务端,服务端收到验证码后就会在redis里面查询到这个手机号对应的验证码,失败就返回错误码。

成功后就进行登录操作。

这里看起来没有明确的注册登录操作,其实在发送手机号码就可以认为是一个常规的注册,然后后面的验证码输入就是一个登陆操作,

问: 那我要密码咋办?

答: 在后续产品里面增加一个 手机号码密码补录的功能 即可,这也是现在很常规的手法,但是现在移动互联网大爆炸时代,密码已经显得不是那么重要了,反正我从来记不住密码,如果手机号码能操作的app,绝对不用密码来操作。

数据库设计
表结构 :

自增id 用户名 密码 手机号 错误次数
1 user1 7fef6171469e80d32c0559f88b377245 13456789012 0
2 user2 7fef6171469e80d32c0559f88b377245 13456789013 0
说明 :

这里只是单纯说明需要用到的数据,没有扩展具体场景,这个表结构能够满足上面两个方案的设计。

引入第三方账户方案
这里是以QQ-SDK的登录逻辑, 我们先来一波时序图

说明:

客户端自己调起登录的界面,进行输入用户名、密码,这里的是第三方的用户名,密码,登录成功后,会返回access_token openid expire_in,这过程会使用到oauth2.0,不过在sdk里面进行内置回调获取了,后面我们会说明我们自身实现的oauth2.0

客户端拿到access_token、openid、login_type(qq、wechat…)请求应用服务器,应用服务器拿到这些数据后就会根据对应的login_type去对应的用户中心进行access_token和openid进行校验。校验不通过则返回对应错误码
校验通过后就会判断本地是否有这个login_type和openid是否存在,不存在则进行获取远程的用户名、头像等基础信息来作为本地基础数据,并且返回code值

如果已经存在,那就是进行登录操作,返回code值。

客户端拿到code值后进行token值的换取,这个完全遵照oauth2.0的协议来走的,后续每次请求必须带上token,token值在服务端的时间比较久,因为我们想要做的是那种永不下线的操作,所以每次请求我们都将token过期时间进行累加。

数据库设计
根据部分小伙伴的的建议,我这里做一下数据库的整理:


用户基础表(users)

字段 备注
user_id 用户id
token 用户登陆的token
expire_in token过期时间
try_times 登录失败次数


用户验证关联表(user_auth_rel)

字段 备注
id 自增id
user_id 用户id
auth_id 验证表id
auth_type 验证类型(local、third)


本地用户表(user_local_auth)

字段 备注
auth_id 认证id,自增id
user_name 用户唯一标识
password 用户密码
mobile 用户手机


第三方用户表(user_third_auth)

字段 备注
auth_id 用户id
openid 第三方用户唯一标识
login_type 第三方平台标识(qq、wechat…)
access_token 第三方获取的access_token,校验使用
说明

users表只是单纯针对我们业务侧的登录,主要是做自身业务的oauth2.0业务,
user_local_auth是做自己用户名、密码登录,手机号码登录信息记录,
user_third_auth是我们第三方用户体系的数据记录,
user_auth_rel是用来关联我们users表与user_local_auth、user_third_auth。
整个设计理念就是将自建用户与第三方在存储上区分,这在架构演进上也是合乎情理的,开始用户体系大多自建,而后才是对外接入。

QQ登录

QQ互联注册一个账号
网站地址:https://connect.qq.com/,添加一个应用,具体怎么申请以及需要填写的信息,腾讯官网有详细文档。注册并完成相应信息填写后,可以在应用管理中查到应用的APP ID和APP Key。(注,这个申请还是比较麻烦的,申请了好几次,可能是脸黑吧)成功后如下图:

还需要添加一个回调地址,如下图:

加入jar包

<!-- 第三方QQ登录 -->
<dependency><groupId>com.qq</groupId><artifactId>Sdk4J</artifactId><version>2</version>
</dependency>

登录页面

<button type="submit" class="btn btn-default" onclick="qqLogin()">qq登录</button>
function qqLogin() {window.open("/login/qqLogin","TencentLogin");
}

Controller编写

package com.gbq.boot.web.controller;import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.gbq.boot.web.bean.User;
import com.gbq.boot.web.comment.qqLoginComment.AuthComment;
import com.gbq.boot.web.service.UserService;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;/*** 登录Controller*/
@RestController
@RequestMapping("/login")
public class LoginController {@Resourceprivate UserService userService;@Resourceprivate AuthComment authComment;@RequestMapping("/index")public ModelAndView index(@ModelAttribute("user") User user) {return new ModelAndView("/shop/index","user",user);}@RequestMapping("/login.html")public ModelAndView toLogin() {return new ModelAndView("login");}@RequestMapping("/qqLogin")public void qqLogin(HttpServletResponse response)throws Exception{//随机产生字符串String state = StrUtil.uuid();String url = authComment.getAuthUrl(state);System.out.println(url);//重定向response.sendRedirect(url);}@GetMapping("/redirect")public ModelAndView getData(@RequestParam(value = "code") String code, RedirectAttributes model){//获取tokenString accessToken = authComment.getAccessToken(code);System.out.println("accessToken"+accessToken);//获取openIdString openId = authComment.getOpenId(accessToken);System.out.println("openId"+openId);//获取用户信息JSONObject userInfo = authComment.getUserInfo(accessToken, openId);String myName = userInfo.getString("nickname");User user = new User(null, "","111111",myName, System.currentTimeMillis(),"是",userInfo.getString("figureurl_2"), userInfo.getString("gender"),1,1,"", "", openId);//通过openId查询User usr = userService.findUsrByOpenId(openId);if (null != usr){user.setId(usr.getId());userService.updateById(user);}else {userService.insert(user);}model.addFlashAttribute("user", user);//重定向return new ModelAndView("redirect:/login/index");}}

AuthComment类编写

package com.gbq.boot.web.comment.qqLoginComment;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.stereotype.Component;import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;import static org.apache.commons.io.IOUtils.toByteArray;@Component
public class AuthComment {//QQ 登陆页面的URLprivate final static String AUTHORIZATION_URL ="https://graph.qq.com/oauth2.0/authorize?response_type=code&client_id=%s&redirect_uri=%s&scope=%s";//获取token的URLprivate final static String ACCESS_TOKEN_URL = "https://graph.qq.com/oauth2.0/token?grant_type=authorization_code&client_id=%s&client_secret=%s&code=%s&redirect_uri=%s";// 获取用户 openid 的 URLprivate static final String OPEN_ID_URL = "https://graph.qq.com/oauth2.0/me?access_token=%s";// 获取用户信息的 URL,oauth_consumer_key 为 apiKeyprivate static final String USER_INFO_URL = "https://graph.qq.com/user/get_user_info?access_token=%s&oauth_consumer_key=%s&openid=%s";// 下面的属性可以通过配置读取// QQ 在登陆成功后回调的 URL,这个 URL 必须在 QQ 互联里填写过private static final String CALLBACK_URL = "http://127.0.0.1:8080/login/redirect";// QQ 互联应用管理中心的 APP IDprivate static final String APP_ID = "你的id";// QQ 互联应用管理中心的 APP Keyprivate static final String APP_SECRET = "你的key";/*** QQ 登陆页面的URL* @param scope* @return*/public String getAuthUrl(String scope) {return String.format(AUTHORIZATION_URL, APP_ID, CALLBACK_URL, scope);}/*** 获取Access Token值*/public String getAccessToken(String code){String ur = String.format(ACCESS_TOKEN_URL, APP_ID, APP_SECRET,code, CALLBACK_URL);String compile = "access_token=(\\w*)&";String result = this.getUrl(ur);return this.getMatcher(result,compile);}/*** 获取openId* @param accessToken* @return*/public String getOpenId(String accessToken) {String url = String.format(OPEN_ID_URL, accessToken);String compile = "openid\":\"(\\w*)\"";String result = this.getUrl(url);return this.getMatcher(result,compile);}/*** 获取qq用户信息* @param accessToken* @param openId* @return*/public JSONObject getUserInfo(String accessToken, String openId) {String url = String.format(USER_INFO_URL, accessToken, APP_ID, openId);String result = this.getUrl(url);return JSON.parseObject(result);}private String getMatcher(String result,String compile) {//使用正则表达式解析网址Pattern p = Pattern.compile(compile);Matcher m = p.matcher(result);m.find();return m.group(1);}//解析urlprivate String getUrl(String ur) {try {URL url = new URL(ur);HttpURLConnection conn = null;conn = (HttpURLConnection) url.openConnection();conn.setConnectTimeout(5 * 1000);conn.setRequestMethod("GET");InputStream inStream = conn.getInputStream();byte[] data = toByteArray(inStream);String result = new String(data, "UTF-8");System.out.println(result);return result;} catch (IOException e) {e.printStackTrace();}return  null;}}

此处不再编写userService

成功会返回json串

其中主要需要的是,nickname——qq名称,figureurl_qq_x——不同尺寸的qq头像,等等等等!

登录成功跳转到页面

成功后的页面index

注意我使用的是freemarker模板,给大家贴上freemarker配置,已经mvc配置

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>freemarker:template-loader-path: classpath:/templates/# 是否启用模板缓存。suffix: .ftlcache: false# 模板编码。charset: UTF-8# 是否检查模板位置是否存在。check-template-location: truecontent-type: text/html#是否启用freemarkerenabled: truemvc:view:prefix: /templates/suffix: .htmlstatic-path-pattern: /static/**

总结

总的来讲,第三方用户的接入技术上来讲是比较简单的,这里设计多一个user_thirds是可以支持足够多的第三方接入,当然一般我们也就两三个登录就好,太多登录方不仅自身维护成本,界面摆盘也不好看不是。

希望大家能够通过以上学习,能够对于我们多账户登录有一个比较好的认知,这里设计方案不包含分表分库、没有服务化,就是简单直接的设计,当然用户量和需要的不一样,在这个基础上还要加很多东西,谢谢大家阅读

Java实现了第三方qq账号登录...相关推荐

  1. java string转jsonobject_超赞!终于有网友用Java实现了第三方qq账号登录

    Java面试笔试面经.Java技术每天学习一点 Java面试 关注不迷路 整理 | Java面试那些事儿 来源 | http://www.zuidaima.com/ 网站地址:https://conn ...

  2. Java 实现第三方 QQ 账号登录

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 来源 | uidaima.com/blog/472561 ...

  3. 【Android】第三方QQ账号登录的实现

    在APP开发过程中,时常会用到第三方账号登录体系. 下面,简要说明QQ的第三方登录体系在Android平台上的运用. 申请APPID 进入QQ互联的官网,http://connect.qq.com/ ...

  4. python的flask实现第三方登录怎么写_Python语言的Flask框架应用程序实现使用QQ账号登录的方法...

    本文主要向大家介绍了Python语言的Flask框架应用程序实现使用QQ账号登录的方法,希望对大家学习Python语言有所帮助. Flask-OAuthlib是OAuthlib的Flask扩展实现, ...

  5. Python学习笔记7:实操案例四(支付密码的验证,模拟QQ账号登录,商品价格竞猜,星座看运势)

    Python学习笔记7:实操案例四(支付密码的验证,模拟QQ账号登录,商品价格竞猜,星座看运势) 1.支付密码的验证: 这个主要就是调用isdigit()函数判断字符串是不是全是数字组成. pwd=i ...

  6. tp框架实现第三方QQ快捷登录

    最近公司更新商城网站平台,原来基础上新增许多功能,接到任务实现第三方QQ快捷登录,功能已实现,今天特梳理一下.大致流程首先在开发者开放平台QQ互联注册应用,把你的域名空间注册,一般域名空间备过案的比较 ...

  7. JAVA Spring Security对接QQ快速登录(web应用)

    阅读此文需要对Security有大概的了解,了解其运行流程 security对接QQ互联jssdk快速登录 前端使用的是vue.js 1.首先在QQ互联申请一个应用,得到appid和设置好回调地址 2 ...

  8. Java MD5加密实战(账号登录注册系统)

    程序框架 程序框架如图所示: 代码展示: Main方法: package com.jd.test;import java.util.ArrayList; import java.util.Scanne ...

  9. 实现app第三方QQ授权登录

    关于QQ授权登录的实现,官网有详细描述,点击链接 . 这里根据自己的实现过程简单介绍一下整个过程: 1. 注册成为开发者,创建应用,获取appid,这个appid后面要用到.详情步骤请查看官网链接 2 ...

最新文章

  1. 独家 | NLP详细教程:手把手教你用ELMo模型提取文本特征(附代码论文)
  2. Swift实战-豆瓣电台(六)视图跳转,传参及回跳
  3. wpf中xaml的类型转换器与标记扩展
  4. 启动mysql会遇到的问题_MySQL学习(一)——启动和登录MySql遇到的问题及解决
  5. 二叉堆(最小堆)(数据结构与算法分析的代码实现)
  6. 最完整的时间序列分析和预测(含实例及代码)
  7. Nodejs Guides(四)
  8. mysql 三级联动_c#+Mysql 实现三级联动
  9. Atitit usrQBM2331 参数格式化规范
  10. 读取没开计算机硬盘,电脑磁盘读取错误开不了机怎么办
  11. afc系统线路中心计算机系统,青岛地铁线网AFC系统建设探讨
  12. golang_微信公众号网页授权
  13. vue页面跳转打开新的窗口
  14. oracle中删除表的四种基本操作 2021-11-03
  15. Verilog状态机详述
  16. 集合多种功能的转录调控数据库:hTFtarget,介绍及使用教程
  17. int数据类型的取值范围是多少?怎么计算的?
  18. HTML静态网页作业:使用html+css制作北京黎红学院学校网站 (4个页面)
  19. matlab中imagesc函数基本学习
  20. 突发!OpenAI 重磅发布 ChatGPT iOS 客户端!无须手续费,直接开通Plus。

热门文章

  1. 流式处理 术语解释 Exactly-once与Effectively-once
  2. 52-jQuery删除节点相关方法
  3. Windows文件名长度限制
  4. python设置文件名长度对齐
  5. Spring 时间戳(日期)格式转换问题
  6. 安卓项目不能调起微信,qq,支付宝
  7. HTTP的血泪进化史
  8. wind7nbsp;安装IIS教程
  9. Python爬虫——京东商品信息 前期准备
  10. .\venv\Scripts\activate : 无法加载文件 ...因为在此系统上禁止运行脚本。