您现在的位置是:网站首页>>信息浏览 文章详情

SpringBoot配置整合第三方QQ登陆以及返回登陆前的页面
2019-01-03 17:04 许多年以后 925

目前各种网站登陆都有QQ登陆方式,那我们这篇文章就是教如何QQ登陆和登陆成功后返回登陆前的页面

思路:对于QQ登陆,目前是这样的,我们组成信息登陆信息,发给QQ互联,然后QQ互联返回来,我们验证发回来的信息并保存数据库,登陆成功返回登陆前的页面,登陆失败,在提示失败。

前端的代码:

  1. function goto() {
  2. //获取当前位置
  3. var url=window.location.href;
  4. //访问后台接口
  5. window.open('/api/qq?url='+url,'_self');
  6. }

后台代码

  1. @Controller
  2. @RequestMapping("/api")
  3. public class QqLoginController extends BaseController {
  4. @Autowired
  5. private NBContext blogContext;
  6. @Autowired
  7. private ParamRepository paramRepository;
  8. @Autowired
  9. private QqLoginService qqLoginService;
  10. @GetMapping("/qq")
  11. public void qqLogin(HttpServletRequest request,HttpServletResponse response,String url) throws IOException {
  12. //保存登陆前的地址到response的cookie中
  13. CookieUtils.setCookie(response, "backUrl",url, -1);
  14. String callbackDomain = basePath(request).concat("api/qqCallback");
  15. String appId ="XXXXXXX"; //QQ互联注册的APPID
  16. response.sendRedirect("https://graph.qq.com/oauth2.0/authorize?response_type=code&client_id=" + appId + "&redirect_uri=" + callbackDomain + "&state=" + System.currentTimeMillis());//用上面的response重定向访问
  17. }
  18. @GetMapping("/qqCallback")
  19. public String qqCallback(HttpServletRequest request, HttpServletResponse response, String code) {
  20. //QQ互联回调回来的接口,我们可以获取刚才访问给QQ互联的Cookie,拿到登陆前的地址
  21. Cookie cookie = CookieUtils.getCookie(request, "backUrl");
  22. String url="frontend/succes";
  23. if (cookie != null) {
  24. url=cookie.getValue(); //获取
  25. }
  26. String callbackDomain = basePath(request).concat("api/qqCallback");
  27. NBR r = qqLoginService.login(callbackDomain, code);
  28. if (r.get(NBR.CODE).equals(NBR.SUCCESS)) {
  29. blogContext.setSessionUser(request, response, (NBSysUser) r.get(NoteBlogV4.Session.LOGIN_USER));
  30. long masterRoleId = blogContext.getApplicationObj(NoteBlogV4.Session.WEBMASTER_ROLE_ID);
  31. if ( ((NBSysUser) r.get(NoteBlogV4.Session.LOGIN_USER)).getDefaultRoleId() == masterRoleId)
  32. return NoteBlogV4.Session.MANAGEMENT_INDEX;
  33. else
  34. return "redirect:" + url;//如果成功,重定向到登陆前的地址
  35. } else {
  36. return "error/page";
  37. }
  38. }
  39. }

qqLoginService.login(callbackDomain, code)的代码如下

  1. public NBR login(String callbackDomain, String code) {
  2. try {
  3. String appId = "XXXXXXX";
  4. String appKey = "XXXXXXXXX"
  5. Map<String, Object> p1 = Maps.hashMap("grant_type", "authorization_code", "client_id", appId, "client_secret", appKey, "code", code, "redirect_uri", callbackDomain);
  6. String resp1 = HttpUtil.get("https://graph.qq.com/oauth2.0/token", p1);
  7. String accessToken = resp1.substring(13, resp1.length() - 66);
  8. String callback = HttpUtil.get("https://graph.qq.com/oauth2.0/me", Maps.hashMap("access_token", accessToken));
  9. String openId = callback.substring(45, callback.length() - 6);
  10. Map<String, Object> p2 = Maps.hashMap("access_token", accessToken, "oauth_consumer_key", appId, "openid", openId);
  11. JSONObject json2 = JSONUtil.parseObj(HttpUtil.get("https://graph.qq.com/user/get_user_info", p2));
  12. if (json2.getInt("ret") == 0) {
  13. NBSysUser user = userRepository.findByQqOpenIdAndEnable(openId, true);//查看数据库是否有这openId的用户 if (user != null) {
  14. return NBR.ok("授权成功!", "/").put(NoteBlogV4.Session.LOGIN_USER,user); //非空,则之前有登陆过
  15. } else {
  16. NBSysUser lockedUser = userRepository.findByQqOpenIdAndEnable(openId, false);
  17. if (lockedUser != null) {
  18. return NBR.error("QQ登录授权失败,原因:用户已被锁定!");
  19. }
  20. String nickname = json2.getStr("nickname");
  21. String avatar = json2.getStr("figureurl_qq_2").replace("http://", "https://");
  22. NBSysUser registerUser = NBSysUser.builder().nickname(nickname).avatar(avatar).qqOpenId(openId).build();
  23. NBSysUser afterRegisterUser = userRepository.save(registerUser);
  24. if (afterRegisterUser != null) {
  25. return NBR.ok("授权成功!", "/").put(NoteBlogV4.Session.LOGIN_USER,afterRegisterUser);
  26. } else {
  27. return NBR.error("QQ登录授权失败,原因:注册失败!");
  28. }
  29. }
  30. } else {
  31. String errorMsg = json2.getStr("msg");
  32. log.error("QQ登录授权失败,原因:{}", errorMsg);
  33. return NBR.error("QQ登录授权失败,原因:{}", errorMsg);
  34. }
  35. } catch (StringIndexOutOfBoundsException e) {
  36. log.error("[accessToken] 返回值有误!");
  37. return NBR.error("请求重复或返回 [accessToken] 值有误!");
  38. } catch (Exception e) {
  39. log.error("QQ登录授权失败,原因:{}", e);
  40. return NBR.error("QQ登录授权失败,原因:{}", e.getMessage());
  41. }
  42. }

NBR 类是内部的通信类,如下:

  1. public class NBR extends ConcurrentHashMap<String, Object> {
  2. public static final String CODE = "code";
  3. public static final String MESSAGE = "message";
  4. public static final String DATA = "data";
  5. public static final int SUCCESS = 200;
  6. public static final int SERVER_ERROR = 500;
  7. private NBR() {
  8. put(CODE, SUCCESS);
  9. }
  10. @Override
  11. public NBR put(String key, Object value) {
  12. super.put(key, value);
  13. return this;
  14. }
  15. /**
  16. * 返回默认的成功响应的实体
  17. *
  18. * @return
  19. */
  20. public static NBR ok() {
  21. return new NBR();
  22. }
  23. /**
  24. * 返回默认的成功响应的实体,只带文本信息
  25. *
  26. * @param msg 文本信息
  27. * @return
  28. */
  29. public static NBR ok(String msg) {
  30. NBR nbr = new NBR();
  31. nbr.put("message", msg == null || "".equals(msg) ? "success!" : msg);
  32. return nbr;
  33. }
  34. /**
  35. * 返回默认的成功响应的实体,只带文本信息
  36. *
  37. * @param msg 文本信息
  38. * @param param 替换为本占位符参数
  39. * @return
  40. */
  41. public static NBR formatOk(String msg, Object... param) {
  42. NBR nbr = new NBR();
  43. //noinspection ConfusingArgumentToVarargsMethod
  44. nbr.put("message", msg == null || "".equals(msg) ? "success!" : StrUtil.format(msg, param));
  45. return nbr;
  46. }
  47. /**
  48. * 自定义成功响应数据,包含额外的返回数据
  49. *
  50. * @param data 额外的数据
  51. * @return 返回响应正确的实体
  52. */
  53. public static NBR ok(Object data) {
  54. return ok(null, data);
  55. }
  56. /**
  57. * 自定义成功响应数据,包含响应信息以及额外的返回数据
  58. *
  59. * @param msg 响应信息
  60. * @param data 额外的西湖局
  61. * @return 返回响应正确的实体
  62. */
  63. public static NBR ok(String msg, Object data) {
  64. return ok(msg).put(DATA, data);
  65. }
  66. /**
  67. * 自定义返回成功信息,带额外的map信息
  68. *
  69. * @param jsonMap map信息
  70. * @return
  71. */
  72. public static NBR ok(Map<String, Object> jsonMap) {
  73. NBR nbr = new NBR();
  74. nbr.putAll(jsonMap);
  75. return nbr;
  76. }
  77. /**
  78. * 自定义错误响应数据,带额外的数据(指定类型,默认状态码为500
  79. *
  80. * @param message 错误信息
  81. * @param <T> 额外数据指定的类型
  82. * @return 返回响应错误的实体
  83. */
  84. public static <T> NBR error(String message, T data) {
  85. return error(message).put(DATA, data);
  86. }
  87. /**
  88. * 自定义错误响应数据,默认状态码为500
  89. *
  90. * @param message 错误信息
  91. * @return 返回响应错误的实体
  92. */
  93. public static NBR error(String message) {
  94. return Objects.requireNonNull(ok().put(CODE, SERVER_ERROR)).put(MESSAGE, message);
  95. }
  96. /**
  97. * 自定义响应数据,不带额外的参数
  98. *
  99. * @param code 状态码
  100. * @param data 额外数据
  101. * @return 静态方法,返回响应实体JSON数据
  102. */
  103. public static <T> NBR custom(int code, T data) {
  104. return Objects.requireNonNull(ok().put(CODE, code)).put(DATA, data);
  105. }
  106. /**
  107. * 自定义响应数据,不带额外的参数
  108. *
  109. * @param code 状态码
  110. * @param message 响应信息
  111. * @return 静态方法,返回响应实体JSON数据
  112. */
  113. public static NBR custom(int code, String message) {
  114. return Objects.requireNonNull(ok().put(CODE, code)).put(MESSAGE, message);
  115. }
  116. /**
  117. * 自定义响应数据,不带额外的参数
  118. *
  119. * @param code 状态码
  120. * @return 静态方法,返回响应实体JSON数据
  121. */
  122. public static NBR custom(int code) {
  123. return custom(code, "");
  124. }
  125. /**
  126. * 自定义响应数据,带额外的参数(指定类型)
  127. *
  128. * @param code 状态码
  129. * @param message 响应信息
  130. * @param data 额外的数据
  131. * @param <T> 额外数据的指定类型
  132. * @return 静态方法,返回响应实体JSON数据
  133. */
  134. public static <T> NBR custom(int code, String message, T data) {
  135. return custom(code, message).put(DATA, data);
  136. }
  137. }
赞 (45)
文章出处:书生个人博客          转载注明下哦!o(≧v≦)o~~

标签: QQ登陆springboot系列原创

相似文章:


随便说两句
请先登录
遵守国家法律法规,请勿回复无意义内容,请不要回复嵌套过多的楼层!