Solo 登录验证社区账号

本贴最后更新于 1747 天前,其中的信息可能已经渤澥桑田

本文是《Solo 从设计到实现》的一个章节,该系列文章将介绍 Solo 这款 Java 博客系统是如何从无到有的,希望大家能通过它对 Solo 从设计到实现有个直观地了解、能为想参与贡献的人介绍清楚项目,也希望能为给重复发明重新定义博客系统的人做个参考 ❤️

社区登录重定向

Solo 是通过黑客派社区账号实现登录验证的,用户登录时重定向到社区登录页面,登录完成以后重定向回 Solo。

方法 OAuthProcessor#redirectAuth

/** * Redirects to HacPai auth page. * * @param context the specified context */ @RequestProcessing(value = "/login/redirect", method = HttpMethod.GET) public void redirectAuth(final RequestContext context) { String referer = context.param("referer"); if (StringUtils.isBlank(referer)) { referer = Latkes.getServePath(); } final String state = RandomStringUtils.randomAlphanumeric(16); STATES.put(state, referer); final String loginAuthURL = "https://hacpai.com/login?goto=" + Latkes.getServePath() + "/login/callback"; final String path = loginAuthURL + "&state=" + state + "&v=" + Server.VERSION; context.sendRedirect(path); }

登录后重定向回调

  1. 验证 state 防止重放攻击
  2. 处理 Referer 获取参数以及后续跳转
  3. 根据 Open Id(HacPai User Id)查库,并根据系统状态处理(初始化、添加访客用户等)

方法 OAuthProcessor#authCallback

/** * OAuth callback. * * @param context the specified context */ public synchronized void authCallback(final RequestContext context) { String state = context.param("state"); final String referer = STATES.get(state); if (null == referer) { context.sendError(400); return; } STATES.remove(state); final Response response = context.getResponse(); final Request request = context.getRequest(); final String accessToken = context.param("access_token"); final JSONObject userInfo = Solos.getUserInfo(accessToken); if (null == userInfo) { LOGGER.log(Level.WARN, "Can't get user info with token [" + accessToken + "]"); context.sendError(401); return; } final String userId = userInfo.optString("userId"); final String userName = userInfo.optString(User.USER_NAME); final String userAvatar = userInfo.optString("avatar"); JSONObject user = userQueryService.getUserByGitHubId(userId); if (null == user) { if (!initService.isInited()) { final JSONObject initReq = new JSONObject(); initReq.put(User.USER_NAME, userName); initReq.put(UserExt.USER_AVATAR, userAvatar); initReq.put(UserExt.USER_B3_KEY, userName); initReq.put(UserExt.USER_GITHUB_ID, userId); initService.init(initReq); } else { final JSONObject addUserReq = new JSONObject(); addUserReq.put(User.USER_NAME, userName); addUserReq.put(UserExt.USER_AVATAR, userAvatar); addUserReq.put(User.USER_ROLE, Role.VISITOR_ROLE); addUserReq.put(UserExt.USER_GITHUB_ID, userId); addUserReq.put(UserExt.USER_B3_KEY, userName); try { userMgmtService.addUser(addUserReq); } catch (final Exception e) { LOGGER.log(Level.ERROR, "Registers via oauth failed", e); context.sendError(500); return; } } } else { user.put(User.USER_NAME, userName); user.put(UserExt.USER_AVATAR, userAvatar); try { userMgmtService.updateUser(user); } catch (final Exception e) { LOGGER.log(Level.ERROR, "Updates user name failed", e); context.sendError(500); return; } } user = userQueryService.getUserByName(userName); if (null == user) { LOGGER.log(Level.WARN, "Can't get user by name [" + userName + "]"); context.sendError(404); return; } Solos.login(user, response); Statics.clear(); context.sendRedirect(referer); LOGGER.log(Level.INFO, "Logged in [name={}, remoteAddr={}] with oauth", userName, Requests.getRemoteAddr(request)); }

关于 GitHub Id

以前的版本是使用 GitHub OAuth 登录的,后来切换为社区登录了。但是数据库字段还有实现方面没有做迁移,依然保留 GitHub Id 命名,现在这个字段存储的是黑客派用户 id。

  • Solo

    Solo 是一款小而美的开源博客系统,专为程序员设计。Solo 有着非常活跃的社区,可将文章作为帖子推送到社区,来自社区的回帖将作为博客评论进行联动(具体细节请浏览 B3log 构思 - 分布式社区网络)。

    这是一种全新的网络社区体验,让热爱记录和分享的你不再感到孤单!

    1440 引用 • 10067 回帖 • 489 关注
  • 设计
    117 引用 • 797 回帖 • 1 关注
  • 文档
    56 引用 • 1289 回帖 • 2 关注
2 操作
88250 在 2020-06-10 11:23:32 更新了该帖
88250 在 2020-01-14 09:21:42 更新了该帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • 88250

    我又改回去了,因为只有 OAuth 流程(第一步通过重定向获取 token,第二步在服务端使用 token 获取 user)才能避免安全问题 🤣

  • 其他回帖
  • jetablezhu via macOS

    不明白,参数可以 post 甚至简单加密。其实社区充当的是代理角色,即使非博客端伪造 oauth 授权请求,社区还是正常接收,然后回调传递映射 token,我拿到这个 token 一样可以再去社区换回用户信息,所以我不认为规避了什么安全问题吧,倒是可以节省一步请求。

    2 回复
  • 88250

    GitHub 可以改名的,改好以后社区这边私信我你的新用户名。博客端需要你自己手动修改数据库。

  • jetablezhu

    我想问个问题,在社区服务器置换映射 token 后,为什么不能一同将用户信息回调给博客端,还得多一步拿 token 去换回用户信息这一步?

    1 回复
  • 查看全部回帖