开发之前

需求:网站接入qq,sina微博登录,本文最后付效果图:

说明:大部分网站本身是需要用户概念的,很多操作依附于用户,而qq或微博作为一种登录方式指向用户而已,我参考了一下其他网站的做法,

一般有如下两种做法:

1,强制绑定:用户第一次通过qq登录时必须与该网站账户绑定,也就是用户必须要先有一个此网站账户才能登录成功

2,互相独立,用户第一次通过qq登录时直接重新为用户注册一个账户,如以用户名为qq_123456直接注册一个账户,与其他账户无关;

站在用户角度考虑下,可能需要更多的选择性,因此我是如下考虑的:

用户登录后在个人中心中也可设置绑定。

---------------------------------------------------------------------------------------------------

文档说明

现在大部分第三方的登录OAuth2.0为标准,所以开发流程基本都一致,一般都是一下步骤:

1,申请接入,获取appid&appkey(接入后又第三方发放)

2,用户登录第三方下发token,

3,通过token获取用户唯一标示,一般是一个openId

api地址:

qq:http://wiki.connect.qq.com/api列表

sina:http://open.weibo.com/wiki/授权机制

qq&sina也提供了java sdk

https://github.com/sunxiaowei2014/weibo4j-oauth2-beta3.1.1/

http://qzonestyle.gtimg.cn/qzone/vas/opensns/res/doc/qqConnect_Server_SDK_java_v2.0.zip

sina的虽然开源了,但里面很多代码写的有问题,用的之后需要注意

------------------------------------------------------------------------------------------------------------

开发

数据结构方面需要加以一张表用来维护登录方式和用户关联(通过openId以及登录方式确定唯一性)

网站引入,appid,appkey,回调地址的配置有不再赘述了

代码基本上参照sdk中的demo就可以了,

简单贴一下controller(springMVC架构)中的代码吧

AUthController为父类,存放一些第三方登录的通用方法,BindController为用户绑定提供方法,第三方登录的controller基本上就是一个登录跳转方法,一个回调方法,以及一些接口api的调用

public abstract class AuthController extends BaseController {@Resourceprivate JavaMailSender mailSender;@Resourceprivate IBAuthService authService;protected LoginUser getU(BAuth auth){LoginUser loginUser= new LoginUser();loginUser.setAccessToken(auth.getAccessToken());loginUser.setIcon(auth.getIcon() == null ? IPortalConstants.defaultIconUrl: auth.getIcon());loginUser.setId(auth.getUser().getId());loginUser.setLoginType(auth.getType());loginUser.setNickName(auth.getNickName() == null ? auth.getUser().getNickName() : auth.getNickName());loginUser.setOpenId(auth.getOpenId());return loginUser;}protected LoginUser getU(User user){LoginUser loginUser= new LoginUser();loginUser.setIcon(user.getIcon() == null ? IPortalConstants.defaultIconUrl: user.getIcon());loginUser.setId(user.getId());loginUser.setLoginType(AuthType.bresume.getCode());loginUser.setNickName( user.getNickName());return loginUser;}protected boolean setUser2Session(BAuth auth){LoginUser loginuser = this.getU(auth);SessionContextHolder.getSession().setAttribute(IPortalConstants.SESSION_KEY_LOGIN_USER, loginuser);return true;}protected boolean setUser2Session(User user){LoginUser loginuser = this.getU(user);SessionContextHolder.getSession().setAttribute(IPortalConstants.SESSION_KEY_LOGIN_USER, loginuser);return true;}protected void sendRegisterMail(User user,String code) {PropertiesLoader loader = new PropertiesLoader("mail.properties");Map<String, Object> map = new HashMap<String, Object>();Email email = new Email();email.setSender(loader.getProperty("mail.from"));email.setAddress(user.getEmail());email.setSubject(loader.getProperty("mail.register.success.subject"));// 从模板生成HashMap<String, Object> param = new HashMap<String, Object>();param.put("userName", user.getUserName());param.put("userId", user.getId());param.put("code", code);email.setContent(MailUtils.getMailText(param,loader.getProperty("mail.register.success.content")));map.put("email", email);MailUtils.sendMailByAsynchronousMode(map, mailSender);}protected String callBack(Model model,BAuth newAuth){BAuth oldAuth = authService.findOne(newAuth.getOpenId(),newAuth.getType());if (oldAuth != null && oldAuth.getUser() != null) {// 判定有登录记录//刷新accessToken
            oldAuth.setAccessToken(newAuth.getAccessToken());oldAuth.setExpiresIn(newAuth.getExpiresIn());oldAuth.setIcon(newAuth.getIcon());oldAuth.setNickName(newAuth.getNickName());oldAuth.setRefreshAccessTime(new Date());authService.update(oldAuth);this.setUser2Session(oldAuth);return "redirect:/index";} else if(oldAuth==null) {// 判定首次登录,记录oldAuth = new BAuth();oldAuth.setAccessToken(newAuth.getAccessToken());oldAuth.setExpiresIn(newAuth.getExpiresIn());oldAuth.setCreatedTime(new Date());oldAuth.setIcon(newAuth.getIcon());oldAuth.setNickName(newAuth.getNickName());oldAuth.setOpenId(newAuth.getOpenId());oldAuth.setRefreshAccessTime(new Date());oldAuth.setType(newAuth.getType());authService.save(oldAuth);//用户绑定,跳转页面model.addAttribute("openId", newAuth.getOpenId());model.addAttribute("loginFrom", newAuth.getType());return "site/bindAuth.jsp";}else{// 登录过但因某种原因为绑定账户
            oldAuth.setAccessToken(newAuth.getAccessToken());oldAuth.setExpiresIn(newAuth.getExpiresIn());oldAuth.setIcon(newAuth.getIcon());oldAuth.setNickName(newAuth.getNickName());oldAuth.setRefreshAccessTime(new Date());authService.update(oldAuth);//用户绑定,跳转页面model.addAttribute("openId", newAuth.getOpenId());model.addAttribute("loginFrom", newAuth.getType());return "site/bindAuth.jsp";}}}

AuthController

@RequestMapping("/")
@Controller
public class BindController extends AuthController {@Resourceprivate IUserService userService;@Resourceprivate IBAuthService authService;@Resourceprivate IUserVerifiedService verifiedService;@Resourceprivate JavaMailSender mailSender;@RequestMapping("/ingore-bind")public String ingore_bind(@RequestParam(value = "loginFrom", required = true) Integer loginFrom,@RequestParam(value = "openId", required = true) String openId,ModelMap model, HttpServletResponse response) {BAuth auth = authService.findOne(openId, loginFrom);if (auth == null) {return "404";}if (auth.getUser() == null) {User user = new User();/** user.setUserName(userName); user.setPassword(password);*/// user.setEmail(email);
            user.setNickName(auth.getNickName());user.setIcon(auth.getIcon());user.setRegisterType(AuthType.fromCode(loginFrom).getRt().getType());user.setType(UserType.PERSIONAL.getCode());user.setLevel(0);userService.registerFromAuth(user);auth.setUser(user);authService.save(auth);}this.setUser2Session(auth);return "redirect:/index";}@RequestMapping("/login-bind")public @ResponseBody JSONObject bind(@RequestParam(value = "loginFrom", required = true) Integer loginFrom,@RequestParam(value = "openId", required = true) String openId,@RequestParam(value = "email", required = true) String email,@RequestParam(value = "password", required = true) String password,ModelMap model, HttpServletResponse response) {BAuth auth = authService.findOne(openId, loginFrom);if (auth == null) {return this.toJSONResult(false,"404");}if (auth.getUser() == null) {try {// 登陆校验User user = userService.loginCheck(email, password);auth.setUser(user);authService.update(auth);} catch (CoreException e) {if (e.getErrorCode() == PortalErrorCode.USER_PASSWORD_ERROR_TIMES_EXCEED_ERROR) {return this.toJSONResult(false,this.getMessage(e, e.getArgs()));} else {return this.toJSONResult(false, this.getMessage(e));}}}this.setUser2Session(auth);return this.toJSONResult(true);}@RequestMapping("/regist-bind")public @ResponseBody JSONObject registBind(@RequestParam(value = "loginFrom", required = true) Integer loginFrom,@RequestParam(value = "openId", required = true) String openId,@RequestParam(value = "email", required = true) String email,@RequestParam(value = "password", required = true) String password,ModelMap model, HttpServletResponse response) {BAuth auth = authService.findOne(openId, loginFrom);if (auth == null) {return this.toJSONResult(false);}if (auth.getUser() == null) {User user=new User();
//            user.setUserName(userName);
            user.setPassword(password);user.setEmail(email);try {user.setRegisterType(RegisterType.PORTAL_REGISTER.getType());user.setType(UserType.PERSIONAL.getCode());user.setLevel(0);user.setNickName(auth.getNickName());user.setIcon(auth.getIcon());userService.register(user);//生成邮箱验证码UserVerified uv = new UserVerified(user);verifiedService.save(uv);// 发送注册成功的邮件if (CommonUtils.isNotEmpty(user.getEmail())) {sendRegisterMail(user,uv.getCode());}} catch (CoreException e) {return this.toJSONResult(false, this.getMessage(e));}auth.setUser(user);authService.save(auth);}this.setUser2Session(auth);return this.toJSONResult(true);}}

BindController

@RequestMapping("/")
@Controller
public class QQController extends AuthController {@Resourceprivate IBAuthService authService;@Resourceprivate IUserService userService;@RequestMapping("/qqlogin")public void index(HttpServletRequest request, HttpServletResponse response,Model model) throws IOException {response.setContentType("text/html;charset=utf-8");try {response.sendRedirect(new Oauth().getAuthorizeURL(request));LOGGER.info("login by qq");} catch (QQConnectException e) {e.printStackTrace();}}@RequestMapping("/qq_callback")public String callback(HttpServletRequest request,HttpServletResponse response, Model model) {try {AccessToken accessTokenObj = (new Oauth()).getAccessTokenByRequest(request);String accessToken = null, openID = null;long tokenExpireIn = 0L;if (accessTokenObj.getAccessToken().equals("")) {LOGGER.error("QQ Login failed,caused by 没有获取到响应参数");return "404";}accessToken = accessTokenObj.getAccessToken();tokenExpireIn = accessTokenObj.getExpireIn();LOGGER.info("Get accessToken from qq,accessToken:" + accessToken+ ",tokenExpireIn" + tokenExpireIn);// 利用获取到的accessToken 去获取当前用的openidOpenID openIDObj = new OpenID(accessToken);openID = openIDObj.getUserOpenID();LOGGER.info("利用获取到的accessToken:" + accessToken+ ", 去获取到当前用户openid:" + openID + ".");String icon = null, nickName = null;// 去获取用户在Qzone的昵称等信息UserInfo qzoneUserInfo = new UserInfo(accessToken, openID);UserInfoBean userInfoBean = qzoneUserInfo.getUserInfo();if (userInfoBean.getRet() == 0) {nickName = userInfoBean.getNickname();// userInfoBean.getGender();
icon = userInfoBean.getAvatar().getAvatarURL30();// userInfoBean.getAvatar().getAvatarURL50();// userInfoBean.getAvatar().getAvatarURL100();} else {LOGGER.error("很抱歉,我们没能正确获取到您的信息,原因是:" + userInfoBean.getMsg());}BAuth newAuth = new BAuth();newAuth.setAccessToken(accessToken);newAuth.setExpiresIn(tokenExpireIn);newAuth.setIcon(icon);newAuth.setNickName(nickName);newAuth.setOpenId(openID);newAuth.setType(AuthType.QQ.getCode());return this.callBack(model, newAuth);// 通过openid判断首次登录与否/*    BAuth bauth = authService.findOne(openID, AuthType.QQ.getCode());if (bauth != null && bauth.getUser() != null) {// 判定有登录记录//刷新accessTokenbauth.setAccessToken(accessToken);bauth.setExpiresIn(tokenExpireIn);bauth.setIcon(icon);bauth.setNickName(nickName);bauth.setRefreshAccessTime(new Date());authService.update(bauth);this.setUser2Session(bauth);return "redirect:/index";} else if(bauth==null) {// 判定首次登录,记录bauth = new BAuth();bauth.setAccessToken(accessToken);bauth.setCreatedTime(new Date());bauth.setExpiresIn(tokenExpireIn);bauth.setIcon(icon);bauth.setNickName(nickName);bauth.setOpenId(openID);bauth.setRefreshAccessTime(new Date());bauth.setType(AuthType.QQ.getCode());authService.save(bauth);//用户绑定,跳转页面model.addAttribute("openId", openID);model.addAttribute("loginFrom", AuthType.QQ.getCode());return "site/bindAuth.jsp";}else{// 登录过但因某种原因为绑定账户bauth.setAccessToken(accessToken);bauth.setExpiresIn(tokenExpireIn);bauth.setIcon(icon);bauth.setNickName(nickName);bauth.setRefreshAccessTime(new Date());authService.update(bauth);//用户绑定,跳转页面model.addAttribute("openId", openID);model.addAttribute("loginFrom", AuthType.QQ.getCode());return "site/bindAuth.jsp";}*/} catch (QQConnectException e) {e.printStackTrace();}return "redirect:/index";}@RequestMapping("/qqss")public void talk(HttpServletRequest request, HttpServletResponse response,Model model) throws IOException {response.setContentType("text/html;charset=utf-8");request.setCharacterEncoding("utf-8");String con = request.getParameter("con");HttpSession session = request.getSession();String accessToken = (String) session.getAttribute("demo_access_token");String openID = (String) session.getAttribute("demo_openid");System.out.println(accessToken);System.out.println(openID);// 请开发者自行校验获取的con值是否有效if (con != "") {Topic topic = new Topic(accessToken, openID);try {GeneralResultBean grb = topic.addTopic(con);if (grb.getRet() == 0) {response.getWriter().println("<a href=\"http://www.qzone.com\" target=\"_blank\">您的说说已发表成功,请登录Qzone查看</a>");} else {response.getWriter().println("很遗憾的通知您,发表说说失败!原因: " + grb.getMsg());}} catch (QQConnectException e) {System.out.println("抛异常了?");}} else {System.out.println("获取到的值为空?");}}
}

QQController

@RequestMapping("/")
@Controller
public class SinaController extends AuthController {@Resourceprivate IBAuthService authService;@Resourceprivate IUserService userService;@RequestMapping("/sinalogin")public void index(HttpServletRequest request, HttpServletResponse response,Model model) throws IOException {response.setContentType("text/html;charset=utf-8");try {response.sendRedirect(new Oauth().authorize("code"));LOGGER.info("login by weibo");} catch (WeiboException e) {e.printStackTrace();}}@RequestMapping("/weibo_callback")public String callback(HttpServletRequest request,HttpServletResponse response, Model model) throws IOException {try {Oauth oauth = new Oauth();String code = request.getParameter("code");LOGGER.info("code: " + code);AccessToken accessTokenObj = oauth.getAccessTokenByCode(code);if (accessTokenObj == null) {LOGGER.error("AccessToken 获取失败,code:" + code);}String accessToken = accessTokenObj.getAccessToken();String openId = accessTokenObj.getUID();String expireInStr = accessTokenObj.getExpireIn();Users um = new Users(accessToken);User user = um.showUserById(openId);LOGGER.info(user.toString());BAuth newAuth = new BAuth();newAuth.setAccessToken(accessToken);newAuth.setExpiresIn(expireInStr != null ? Long.parseLong(expireInStr) : 3600);newAuth.setIcon(user.getAvatarLarge());newAuth.setNickName(user.getScreenName());newAuth.setOpenId(openId);newAuth.setType(AuthType.SINA.getCode());return this.callBack(model, newAuth);} catch (WeiboException e) {if (401 == e.getStatusCode()) {LOGGER.error("Unable to get the access token.");} else {e.printStackTrace();}}return "redirect:/index";}}

SinaController

-------------------------------------------------------------------------------------------------------------

页面效果

注:该流程为用户首次使用第三方登录时流程

1,登录页面放置第三方登录图标

2,点击图标接入第三方接口,可跳转至第三方登录界面

3,第三方登录完成,用户账户绑定

4,用户登录后,可在个人设置中管理第三方登录的绑定

转载于:https://www.cnblogs.com/china2k/p/4217108.html

第三方登录接入-qq,weibo-java相关推荐

  1. java第三方登录接口_第三方登录接入-qq,weibo-java

    开发之前 需求:网站接入qq,sina微博登录,本文最后付效果图: 说明:大部分网站本身是需要用户概念的,很多操作依附于用户,而qq或微博作为一种登录方式指向用户而已,我参考了一下其他网站的做法, 一 ...

  2. 个人博客系统开发总结之 第三方登录(QQ、微博)

    当别人访问我的博客系统时,如果需要评论,就需要登录.如果此时要求注册,就比较麻烦,并且会引起访问者的反感.于是就采用第三方登录.目前支持QQ.微博登录. QQ登录 QQ互联开放平台为第三方网站提供了丰 ...

  3. dedecms织梦第三方登录插件-QQ登录、微博登录、微信登录

    织梦程序集成第三方QQ登录.微博登录.微信登录,获取QQ.微博.微信,并存储至数据库,一键注册为网站会员,不用再次填写绑定信息,方便粘贴用户更强. 织梦第三方登录效果 第三方登录插件特点 1.所有文件 ...

  4. Java第三方登录(QQ,微博,微信)

    第三方登录_新浪微博 1.   在微博开发平台,注册开发者用户并填写相关信息和创建应用信息,等待审核通过,然后进行下一步编码操作http://open.weibo.com/,具体操作可在微博开发平台观 ...

  5. PHP 接入(第三方登录)QQ 登录 OAuth2.0 过程中遇到的坑

    前言 绝大多数网站都集成了第三方登录,降低了注册门槛,增强了用户体验.最近看了看 QQ 互联上 QQ 登录的接口文档.接入 QQ 登录的一般流程是这样的:先申请开发者 -> 然后创建应用(拿到一 ...

  6. java 第三方登录之QQ登录

    刚刚做了一个第三方登录的网站,之前没有做过,在网上找前辈们的杰作,但都没有找到,只好自己摸索,做出来QQ第三方登录. 1.要做QQ第三方登录,首先得在QQ互联(http://wiki.connect. ...

  7. Spring Boot开发之使用JustAuth组件实现第三方登录(QQ、微博等)

    在我们的项目开发中,使用第三方登录(如QQ登录.微信登录等)可以更加方便.轻松地实现用户登录. 在以往的开发过程中,如果要使项目实现第三方登录功能,一般过程是阅读官网的开发文档,并下载其JDK(或者依 ...

  8. 第三方登录(QQ登录)开发流程详解

    一.准备工作 接入QQ登录前,网站需首先进行申请,获得对应的appid与appkey,以保证后续流程中可正确对网站与用户进行验证与授权. 申请appid和appkey的用途 appid :应用的唯一标 ...

  9. php中qq授权登录,ThinkPHP利用QQ互联实现网站第三方登录(QQ登录)

    接入QQ互联平台后,我们就可以让用户通过QQ帐号登录来登陆我们的网站,这样减少了注册的繁琐,可以更快 .更便捷的为了我带来更多的用户,下面我们一一起来看下如何通过QQ互联来实现第三方登录. ####申 ...

最新文章

  1. 《基于MFC的OpenGL编程》Part 1 A Primer
  2. springboot学习笔记:12.解决springboot打成可执行jar在linux上启动慢的问题
  3. 【文档】七、Mysql Binlog不同事件类型的事件内容
  4. thinkphp5是不是php,我对ThinkPHP5和Laravel5的一些看法
  5. python量化投资必背代码-量化投资:用Python实现金融数据的获取与整理
  6. java clob存储_java oracle clob string 大字符串存储
  7. java学习5-jar包的下载以及导入
  8. 处理SQL Server中的重复行
  9. 我是如何2小时弄出房产网站小程序的?
  10. mysql意外关闭xampp_错误:MySQL意外关闭xampp 3.2.4
  11. activity 和service通信,调用service方法
  12. 30 个数据工程必备的Python 包
  13. 逆水寒服务器维护多长时间,逆水寒11月8日更新维护 更新时间内容介绍
  14. Wasserstein距离 和 Lipschitz连续
  15. 2015网页导航设计趋势案例大搜罗
  16. gif图像分解、gif图像制作
  17. 关于数学分支与数学家的一个故事
  18. 分享20份小升初超实用简历模板,每套都有自己的风格,可选取适合孩子的
  19. 手把手教你安装nvidia显卡驱动
  20. 测试工程师的明天在哪里

热门文章

  1. android 八核手机,八核手机
  2. 【图像超分辨率】Meta-SR: A Magnification-Arbitrary Network for Super-Resolution
  3. mysql的索引的作用_数据库索引的作用,优点和缺点
  4. matlab 定义一个有自变量的方程_Eviews、Stata、Python、Matlab、R描述+相关+回归分析教程汇总...
  5. springcloud 之服务注册与发现 Eureka Client
  6. linux安装mysql出错( file /usr/share/mysql/czech/errmsg.sys from install of MySQL-server-5.5.31-2.el6.i6)
  7. TensorFlow 2.0快速上手指南12条:“Keras之父”亲授 | 高赞热贴
  8. python3(三)Matplotlib
  9. 机器学习 可视化_机器学习-可视化
  10. 【Android 修炼手册】常用技术篇 -- Android 自定义 View