Solo 登录状态和会话

本贴最后更新于 2340 天前,其中的信息可能已经时移世异

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

Solo 的用户登录状态是依赖浏览器客户端 Cookie 的。服务端依赖容器提供的会话,如果会话没有过期,则直接使用,如果过期则通过 Cookie 进行验证,验证通过的话就再次创建会话。

方法 Solos#getCurrentUser

for (int i = 0; i < cookies.length; i++) { final Cookie cookie = cookies[i]; if (!COOKIE_NAME.equals(cookie.getName())) { continue; } final String value = Crypts.decryptByAES(cookie.getValue(), COOKIE_SECRET); final JSONObject cookieJSONObject = new JSONObject(value); final String userId = cookieJSONObject.optString(Keys.OBJECT_ID); if (StringUtils.isBlank(userId)) { break; } JSONObject user = userRepository.get(userId); if (null == user) { break; } final String userPassword = user.optString(User.USER_PASSWORD); final String token = cookieJSONObject.optString(Keys.TOKEN); final String hashPassword = StringUtils.substringBeforeLast(token, ":"); if (userPassword.equals(hashPassword)) { login(request, response, user); return currentUser(request); } }

方法 Solos#login

final JSONObject cookieJSONObject = new JSONObject(); cookieJSONObject.put(Keys.OBJECT_ID, user.optString(Keys.OBJECT_ID)); cookieJSONObject.put(User.USER_PASSWORD, user.optString(User.USER_PASSWORD)); final String random = RandomStringUtils.random(16); cookieJSONObject.put(Keys.TOKEN, user.optString(User.USER_PASSWORD) + ":" + random); final String cookieValue = Crypts.encryptByAES(cookieJSONObject.toString(), COOKIE_SECRET); final Cookie cookie = new Cookie(COOKIE_NAME, cookieValue); cookie.setPath("/"); cookie.setMaxAge(COOKIE_EXPIRY); cookie.setHttpOnly(COOKIE_HTTP_ONLY); response.addCookie(cookie);

可以看出,Cookie 通过 AES 加密后写回客户端,保证了一定的安全性。需要注意的是,密钥是配置在 latke.props 中的(cookieSecret),如果不配置则每次启动时生成随机密钥。

具体判断是否的点是通过 AOP 拦截器实现的,ConsoleAuthAdvice.javaConsoleAdminAuthAdvice.java 分别用于判断是否登录以及是否是管理员登录。

@Override public void doAdvice(final HTTPRequestContext context, final Map<String, Object> args) throws RequestProcessAdviceException { final HttpServletRequest request = context.getRequest(); if (!Solos.isAdminLoggedIn(request)) { final JSONObject exception401 = new JSONObject(); exception401.put(Keys.MSG, "Unauthorized to request [" + request.getRequestURI() + "]"); exception401.put(Keys.STATUS_CODE, HttpServletResponse.SC_UNAUTHORIZED); throw new RequestProcessAdviceException(exception401); } }

对了,在大多数情况下,我们不应该把 request 传到 service 层,因为这样做的话 service 层就变成有状态的了。这里的“状态”主要是用户会话状态。当然,这也不是绝对的,有的场景在服务层是需要获取用户状态的:

  • 根据 Cookie 服务统计服务,避免浏览数重复计数
  • 判断登录状态的服务,服务端会话不存在时需要用 Cookie 重登
  • Solo

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

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

    1438 引用 • 10067 回帖 • 490 关注
  • 设计
    117 引用 • 797 回帖 • 1 关注
  • 文档
    56 引用 • 1289 回帖 • 2 关注

相关帖子

欢迎来到这里!

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

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

    👍

  • EvilCodes

    D 哥这个用的是 SpringMVC 还是传统的 Servlet

    1 回复
  • 88250

    Latke 是基于 Servlet 的,SpringMVC 也是。

  • keifer12138

    请问这个具体注解对应的注解处理器在哪查看啊?

    1 回复
  • 88250

    在 Latke 框架里。

  • keifer12138

    就是需要下载 Latke 源码了嘛?通过 IDEA 在 solo 项目中没法定位过去

    1 回复
  • 88250

    如果 Maven 导入项目的话应该可以自动下载的,Latke 的源码 Maven 中央库里有的。

  • keifer12138

    那请问具体在哪个目录下呢?因为我找了段时间没找到。

    1 回复
  • 88250

    看下这里

  • keifer12138

    好的,找到了,谢谢了!!

请输入回帖内容 ...

推荐标签 标签

  • RYMCU

    RYMCU 致力于打造一个即严谨又活泼、专业又不失有趣,为数百万人服务的开源嵌入式知识学习交流平台。

    4 引用 • 6 回帖 • 53 关注
  • DevOps

    DevOps(Development 和 Operations 的组合词)是一组过程、方法与系统的统称,用于促进开发(应用程序/软件工程)、技术运营和质量保障(QA)部门之间的沟通、协作与整合。

    55 引用 • 25 回帖 • 5 关注
  • Hprose

    Hprose 是一款先进的轻量级、跨语言、跨平台、无侵入式、高性能动态远程对象调用引擎库。它不仅简单易用,而且功能强大。你无需专门学习,只需看上几眼,就能用它轻松构建分布式应用系统。

    9 引用 • 17 回帖 • 616 关注
  • Rust

    Rust 是一门赋予每个人构建可靠且高效软件能力的语言。Rust 由 Mozilla 开发,最早发布于 2014 年 9 月。

    58 引用 • 22 回帖 • 1 关注
  • Firefox

    Mozilla Firefox 中文俗称“火狐”(正式缩写为 Fx 或 fx,非正式缩写为 FF),是一个开源的网页浏览器,使用 Gecko 排版引擎,支持多种操作系统,如 Windows、OSX 及 Linux 等。

    7 引用 • 30 回帖 • 409 关注
  • Mobi.css

    Mobi.css is a lightweight, flexible CSS framework that focus on mobile.

    1 引用 • 6 回帖 • 752 关注
  • MongoDB

    MongoDB(来自于英文单词“Humongous”,中文含义为“庞大”)是一个基于分布式文件存储的数据库,由 C++ 语言编写。旨在为应用提供可扩展的高性能数据存储解决方案。MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似 JSON 的 BSON 格式,因此可以存储比较复杂的数据类型。

    90 引用 • 59 回帖 • 2 关注
  • 996
    13 引用 • 200 回帖 • 8 关注
  • Openfire

    Openfire 是开源的、基于可拓展通讯和表示协议 (XMPP)、采用 Java 编程语言开发的实时协作服务器。Openfire 的效率很高,单台服务器可支持上万并发用户。

    6 引用 • 7 回帖 • 99 关注
  • 数据库

    据说 99% 的性能瓶颈都在数据库。

    345 引用 • 724 回帖 • 1 关注
  • WebComponents

    Web Components 是 W3C 定义的标准,它给了前端开发者扩展浏览器标签的能力,可以方便地定制可复用组件,更好的进行模块化开发,解放了前端开发者的生产力。

    1 引用 • 4 关注
  • OpenStack

    OpenStack 是一个云操作系统,通过数据中心可控制大型的计算、存储、网络等资源池。所有的管理通过前端界面管理员就可以完成,同样也可以通过 Web 接口让最终用户部署资源。

    10 引用
  • 脑图

    脑图又叫思维导图,是表达发散性思维的有效图形思维工具 ,它简单却又很有效,是一种实用性的思维工具。

    31 引用 • 96 回帖
  • 书籍

    宋真宗赵恒曾经说过:“书中自有黄金屋,书中自有颜如玉。”

    76 引用 • 389 回帖
  • OpenShift

    红帽提供的 PaaS 云,支持多种编程语言,为开发人员提供了更为灵活的框架、存储选择。

    14 引用 • 20 回帖 • 643 关注
  • 国际化

    i18n(其来源是英文单词 internationalization 的首末字符 i 和 n,18 为中间的字符数)是“国际化”的简称。对程序来说,国际化是指在不修改代码的情况下,能根据不同语言及地区显示相应的界面。

    8 引用 • 26 回帖 • 1 关注
  • flomo

    flomo 是新一代 「卡片笔记」 ,专注在碎片化时代,促进你的记录,帮你积累更多知识资产。

    6 引用 • 140 回帖
  • 工具

    子曰:“工欲善其事,必先利其器。”

    295 引用 • 749 回帖
  • jQuery

    jQuery 是一套跨浏览器的 JavaScript 库,强化 HTML 与 JavaScript 之间的操作。由 John Resig 在 2006 年 1 月的 BarCamp NYC 上释出第一个版本。全球约有 28% 的网站使用 jQuery,是非常受欢迎的 JavaScript 库。

    63 引用 • 134 回帖 • 730 关注
  • Node.js

    Node.js 是一个基于 Chrome JavaScript 运行时建立的平台, 用于方便地搭建响应速度快、易于扩展的网络应用。Node.js 使用事件驱动, 非阻塞 I/O 模型而得以轻量和高效。

    139 引用 • 269 回帖
  • B3log

    B3log 是一个开源组织,名字来源于“Bulletin Board Blog”缩写,目标是将独立博客与论坛结合,形成一种新的网络社区体验,详细请看 B3log 构思。目前 B3log 已经开源了多款产品:SymSoloVditor思源笔记

    1063 引用 • 3455 回帖 • 172 关注
  • 思源笔记

    思源笔记是一款隐私优先的个人知识管理系统,支持完全离线使用,同时也支持端到端加密同步。

    融合块、大纲和双向链接,重构你的思维。

    24299 引用 • 99232 回帖
  • 人工智能

    人工智能(Artificial Intelligence)是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门技术科学。

    144 引用 • 267 回帖
  • 友情链接

    确认过眼神后的灵魂连接,站在链在!

    24 引用 • 373 回帖 • 4 关注
  • Flutter

    Flutter 是谷歌的移动 UI 框架,可以快速在 iOS 和 Android 上构建高质量的原生用户界面。 Flutter 可以与现有的代码一起工作,它正在被越来越多的开发者和组织使用,并且 Flutter 是完全免费、开源的。

    39 引用 • 92 回帖 • 3 关注
  • IPFS

    IPFS(InterPlanetary File System,星际文件系统)是永久的、去中心化保存和共享文件的方法,这是一种内容可寻址、版本化、点对点超媒体的分布式协议。请浏览 IPFS 入门笔记了解更多细节。

    21 引用 • 245 回帖 • 238 关注
  • 持续集成

    持续集成(Continuous Integration)是一种软件开发实践,即团队开发成员经常集成他们的工作,通过每个成员每天至少集成一次,也就意味着每天可能会发生多次集成。每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽早地发现集成错误。

    15 引用 • 7 回帖 • 1 关注