Spring Security(一)--Architecture Overview
一直以来我都想写一写 Spring Security 系列的文章,但是整个 Spring Security 体系强大却又繁杂。陆陆续续从最开始的 guides 接触它,到项目中看了一些源码,到最近这个月为了写一写这个系列的文章,阅读了好几遍文档,最终打算尝试一下,写一个较为完整的系列文章。
较为简单或者体量较小的技术,完全可以参考着 demo 直接上手,但系统的学习一门技术则不然。以我的认知,一般的文档大致有两种风格:Architecture First 和 Code First。前者致力于让读者先了解整体的架构,方便我们对自己的认知有一个宏观的把控,而后者以特定的 demo 配合讲解,可以让读者在解决问题的过程中顺便掌握一门技术。关注过我博客或者公众号的朋友会发现,我之前介绍技术的文章,大多数是 Code First,提出一个需求,介绍一个思路,解决一个问题,分析一下源码,大多如此。而学习一个体系的技术,我推荐 Architecture First,正如本文标题所言,这篇文章是我 Spring Security 系列的第一篇,主要是根据 Spring Security 文档选择性 ~~ 翻译 ~~ 整理而成的一个架构概览,配合自己的一些注释方便大家理解。写作本系列文章时,参考版本为 Spring Security 4.2.3.RELEASE。
[TOC]
1 核心组件
这一节主要介绍一些在 Spring Security 中常见且核心的 Java 类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。
1.1 SecurityContextHolder
SecurityContextHolder
用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限… 这些都被保存在 SecurityContextHolder 中。SecurityContextHolder
默认使用 ThreadLocal
策略来存储认证信息。看到 ThreadLocal
也就意味着,这是一种与线程绑定的策略。Spring Security 在用户登录时自动绑定认证信息到当前线程,在用户退出时,自动清除当前线程的认证信息。但这一切的前提,是你在 web 场景下使用 Spring Security,而如果是 Swing 界面,Spring 也提供了支持,SecurityContextHolder
的策略则需要被替换,鉴于我的初衷是基于 web 来介绍 Spring Security,所以这里以及后续,非 web 的相关的内容都一笔带过。
获取当前用户的信息
因为身份信息是与线程绑定的,所以可以在程序的任何地方使用静态方法获取用户信息。一个典型的获取当前登录用户的姓名的例子如下所示:
1 | Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); |
getAuthentication()返回了认证信息,再次 getPrincipal() 返回了身份信息,UserDetails 便是 Spring 对身份信息封装的一个接口。Authentication 和 UserDetails 的介绍在下面的小节具体讲解,本节重要的内容是介绍 SecurityContextHolder 这个容器。