2 D# x' J) [0 _实际上,Shiro的主要功能是管理应用程序中与安全相关的全部,同时尽可能支持多种实现方法。Shiro是建立在完善的接口驱动设计和面向对象原则之上的,支持各种自定义行为。Shiro提供的默认实现,使其能完成与其他安全框架同样的功能,这不也是我们一直努力想要得到的吗! , X9 | n* ~1 A* K5 k- ~$ C! E( R, _5 W0 ]
那么Apache Shiro能用来做什么呢? 1 |7 ?: C7 B. C- C+ `# F: H7 s 2 v; [* e; O2 p# v1 X, n很多,很多,嘿嘿。但是不在快速指南中做介绍,如果你想知道,那怎么办呢?去这里找寻你的答案吧。当然如果你还想知道我们什么时候,以及为什么要"创造"Shiro,去看看Shrio的历史和使命吧。& u/ ~6 T: g g: v/ Y0 y
! @% Z- a5 _! k" J+ y
OK,现在让我们动手做点儿什么吧。 0 Z b& c/ ~0 p. `' z! W * ]& U; m4 e" J; O2 u1 e; y注:Shiro可以在任何环境下运行,小到最简单的命令行应用,大到大型的企业应用以及集群应用。但是我们准备在快速指南中使用最最简单的main方法的方式,让你对Shiro的API有个感官的认识。 9 [/ |: t6 h# k1 a; `: S+ t8 u 3 O7 [6 D+ T6 Y! {( h下载 : G) A; m4 {1 z0 U / l# w; s' u) w8 `确保已经安装了JDK1.5+和Maven2.2+, k& g; u5 ?% X$ |8 F0 \
去这里下载最新已发布的源码。例子中我们使用1.1.0发布版本。 / B: M+ Y/ f$ D解压源代码 H* P: w- R1 q \进入快速指南文件夹 3 d+ f6 T% P, [cd shiro-root-1.1.0/samples/quickstart % |$ a& S2 X/ t7 H1 o' d3 b' [' ^5 a1 k8 i7 J0 Q2 t
运行快速指南 ) x/ S( @6 k8 P2 ?( ?( v3 jmvn compile exec:java . Q6 `* X& k( i+ Y& w $ { U- U5 o1 l f1 e过程中会输出日志信息,用来告诉你正在进行的是什么,最后退出执行。可以在这里"samples/quickstart/src/main/java/Quickstart.java "找到源码,也可以进行修改,记得修改后运行"mvn compile exec:java "即可。 ) O2 z5 H S( }6 v# K5 G3 p7 W# [ ; S/ K3 M. S$ VQuickstart.java& R: n/ d u+ z# q+ s }& Q8 a
$ |) e: O& x* _) i% b0 x
Quickstart.java中包含刚刚我们提到的所有内容(认证、授权等等),通过这个简单的示例可以让你轻松的熟悉Shiro的API。那么,让我们把Quickstart.java中的代码,一点一点剖析,这样便于理解它们的作用。 几乎所有的环境下,都可以通过这种方式获取当前用户:) _: [4 j( X) @4 g
r1 x* ?3 D- n. B2 [Subject currentUser = SecurityUtils.getSubject(); 1 s* X& Q4 w6 e; F j / k& q! G; Q4 k; |, c' x5 z8 @通过SecurityUtils.getSubject(),就可以获取当前Subject。Subject是应用中用户的一个特定安全的缩影,虽然感觉上直接使用User会更贴切,但是实际上它的意义远远超过了User。而且每个应用程序都会有自己的用户以及框架,我们可不想和它们混淆在一起,况且Subject就是安全领域公认的名词。OK,我们继续。' a9 l8 Z/ r8 A7 }1 `7 p) [
- w. x: z1 r1 B( W4 d# x6 a
在单应用系统中,调用getSubject()会返回一个Subject,它是位于应用程序中特定位置的用户信息;在服务器中运行的情况下(比如web应用),getSubject会返回一个位于当前线程或请求中的用户信息。 现在你已经得到了Subject对象,那么用它可以做什么呢? ( X* ^- D$ y1 K( y" W + x5 s' G6 U. f- D9 s0 M如果你想得到应用中用户当前Session的其他参数,可以这样获取Session对象:: w8 }7 K: ^2 Y- s
- u$ Z k1 w: U* y4 H0 k. m" FSession session = currentUser.getSession();. h& S2 d3 b) \( F
8 H2 M# n: o2 D4 R9 e9 E
session.setAttribute( "someKey", "aValue" );1 }# N& s+ x4 D* h, `8 X9 J
3 ]" }& p/ v7 f" b6 M8 }
这个Session对象是Shiro中特有的对象,它和我们经常使用的HttpSession非常相似,但还提供了额外的东西,其中与HttpSession最大的不同就是Shiro中的Session不依赖HTTP环境(换句话说,可以在非HTTP 容器下运行)。 6 j4 J" s$ M- |& U, g. r, \3 q) r% C S3 ?
如果将Shiro部署在web应用程序中,那么这个Session就是基于HttpSession的。但是像QuickStart示例那样,在非web环境下使用,Shiro则默认使用EnterpriseSessionManagment。也就是说,不论在应用中的任何一层使用同样的API,却不需要考虑部署环境,这一优点为应用打开一个全新的世界,因为应用中要获取Session对象再也不用依赖于HttpSession或者EJB的会话Bean。而且任何客户端技术都可以共享session 数据。- Z$ s0 b1 e% N1 G3 m. L% `3 {, d
* |8 t4 M3 M( c+ ^1 D5 l
现在你可以得到当前Subject和它的Session对象。那么我们如何验证比如角色和权限这些东西呢? + B- O4 q1 o6 O* u: C6 h 3 s8 m9 c8 h9 v6 ]很简单,可以通过已得到的user对象进行验证。Subject对象代表当前用户,但是,谁才是当前用户呢?他们可是匿名用户啊。也就是说,必须登录才能获取到当前用户。没问题,这样就可以搞定:1 U7 F$ b7 h( h5 p
% N* m0 d0 z0 X3 S/ T2 C# aif ( !currentUser.isAuthenticated() ) {2 H3 S& F0 L3 a
# u9 L' j' |& s# `7 k
//collect user principals and credentials in a gui specific manner' m7 H+ B1 `: j2 H+ j
) D* h1 m. Y0 O) p5 h
//such as username/password html form, X509 certificate, OpenID, etc. ; C1 Z7 i: w( M. e' f6 w# Q# W' ]) ]- ~; p" U4 J, @+ i# x6 a- c" T2 @
//We'll use the username/password example here since it is the most common. 0 g a2 J. g) p( a3 H% L/ n9 l3 X1 v6 V, j! J8 e" w. g
//(do you know what movie this is from? ;)" u/ {# g- a+ p; e! Y
4 P- M E* s' kUsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa"); ! m! @5 o: b7 y, l) P- u! t! y c ; u/ g. T4 b! M$ g4 ^//this is all you have to do to support 'remember me' (no config - built in!):+ G! y% I2 t" I" {/ D
1 P% w$ H: ]" d' F# E
token.setRememberMe(true);0 g$ w. Y3 R9 S @$ R
, @' C( d- n9 }) {
currentUser.login(token);7 X/ g1 u8 t' y# d2 W; V4 w& N# D
p, N+ a/ g0 a' K8 \; g' ^ ]
}, ~; w: i h" V* ]9 } e