# E& } C0 u4 }$ V* L过程中会输出日志信息,用来告诉你正在进行的是什么,最后退出执行。可以在这里"samples/quickstart/src/main/java/Quickstart.java "找到源码,也可以进行修改,记得修改后运行"mvn compile exec:java "即可。 6 u0 v7 _$ z5 F# m" M- g' w: ^& D7 H$ l( C% w- s7 n. [" B' a
Quickstart.java) o" @+ F+ {5 \7 e& j. `- p5 H
4 [8 {# u: x0 j5 u5 cQuickstart.java中包含刚刚我们提到的所有内容(认证、授权等等),通过这个简单的示例可以让你轻松的熟悉Shiro的API。那么,让我们把Quickstart.java中的代码,一点一点剖析,这样便于理解它们的作用。 几乎所有的环境下,都可以通过这种方式获取当前用户: . D+ }- p6 t$ r* m4 U+ I 2 A5 {2 d, J5 |, `Subject currentUser = SecurityUtils.getSubject(); p! q2 K1 x+ U2 @/ x- N* [. t
) k6 r* F6 |$ t# [5 U
通过SecurityUtils.getSubject(),就可以获取当前Subject。Subject是应用中用户的一个特定安全的缩影,虽然感觉上直接使用User会更贴切,但是实际上它的意义远远超过了User。而且每个应用程序都会有自己的用户以及框架,我们可不想和它们混淆在一起,况且Subject就是安全领域公认的名词。OK,我们继续。 8 k3 M; R3 ~5 b" X$ X% X6 N! g/ J) ?4 S2 j" J
在单应用系统中,调用getSubject()会返回一个Subject,它是位于应用程序中特定位置的用户信息;在服务器中运行的情况下(比如web应用),getSubject会返回一个位于当前线程或请求中的用户信息。 现在你已经得到了Subject对象,那么用它可以做什么呢?2 l g! r4 z |$ w$ C
( O- j. |( w4 I$ a1 l% {5 b
如果你想得到应用中用户当前Session的其他参数,可以这样获取Session对象:" {( D5 y; z! s# B$ X
8 ~9 t( K& T" |! {6 b+ qSession session = currentUser.getSession();' | C" ~2 w$ D1 s' j/ W* d5 m, k
% k) ]) |9 a9 I/ s A( f( Y; Qsession.setAttribute( "someKey", "aValue" ); & ]* G, Z4 O+ o$ O# L0 S 4 D% \' ~. Q9 t3 w% y5 S1 x6 `4 N这个Session对象是Shiro中特有的对象,它和我们经常使用的HttpSession非常相似,但还提供了额外的东西,其中与HttpSession最大的不同就是Shiro中的Session不依赖HTTP环境(换句话说,可以在非HTTP 容器下运行)。 ' \8 \" `, s# @9 L, q" O8 e% t / {4 d( b' I k* T6 U, c如果将Shiro部署在web应用程序中,那么这个Session就是基于HttpSession的。但是像QuickStart示例那样,在非web环境下使用,Shiro则默认使用EnterpriseSessionManagment。也就是说,不论在应用中的任何一层使用同样的API,却不需要考虑部署环境,这一优点为应用打开一个全新的世界,因为应用中要获取Session对象再也不用依赖于HttpSession或者EJB的会话Bean。而且任何客户端技术都可以共享session 数据。 1 `& m' \, |6 r+ K& c! `; k& K T6 k# a/ Z; q
现在你可以得到当前Subject和它的Session对象。那么我们如何验证比如角色和权限这些东西呢?4 p" {3 x: s2 Q @( G2 R
2 S) S/ X2 h' g- H3 |2 K很简单,可以通过已得到的user对象进行验证。Subject对象代表当前用户,但是,谁才是当前用户呢?他们可是匿名用户啊。也就是说,必须登录才能获取到当前用户。没问题,这样就可以搞定: ! K- k/ ?/ N, ^! {% y6 {# A / l$ B/ g3 j$ y5 s6 Cif ( !currentUser.isAuthenticated() ) { 9 a# ~5 e b8 n 2 j/ ]! s1 G/ ~. ]: K4 Z//collect user principals and credentials in a gui specific manner. X$ s. Z- n n5 h) Z! Q
3 D1 d3 ~( v( j: U
//such as username/password html form, X509 certificate, OpenID, etc.; ^. a5 M5 \3 M( ^' W
6 \- p' k$ e% b+ v. @//We'll use the username/password example here since it is the most common. F0 ]' s; C6 m; Q, s ! |9 f6 m0 C' Z8 c7 d//(do you know what movie this is from? ;)6 P$ f2 Z1 w% D4 W9 X
2 ]9 N' p0 g5 ?( d0 z p; E
UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa"); # h3 v" o7 U; X- b/ g3 {- A $ M$ ?& i- P* ^8 \! L" c* V# ^/ ^//this is all you have to do to support 'remember me' (no config - built in!): . \+ t' U# x3 M# N$ S! o! R8 b) K7 ~2 j6 ^0 U( d4 o* ~' T
token.setRememberMe(true); - N) g* o7 V0 p a0 c5 Y, P ' f! k. q- \3 X8 XcurrentUser.login(token); 7 H2 p6 t* l' k" d; L 3 e) g6 d# T; ^}: J* G' j2 g& Q9 d y2 p8 L J. L
: D* x4 I a% c2 e! l0 R$ r8 [就是这样,太简单了吧! 8 }8 T1 I, Z5 ]3 k% \% g 7 c$ v* c2 Q# H1 y0 S那登录失败了怎么处理呢?可以通过捕获各类异常,根据不同类型的异常做出不同的处理: 5 d, e3 S: J: g4 `7 o' {. B( O4 e9 O$ @* K& E
try {% c0 n! K2 U! w9 X& O
7 w% c5 O) O, Q) F# h1 m: k" qif ( currentUser.isPermitted( "winnebago:drive:eagle5" ) ) {# w1 p i) m: `7 R+ B$ M0 X
) V3 F! n5 @) [+ w& ylog.info("You are permitted to 'drive' the 'winnebago' with license plate (id) 'eagle5'. " +"Here are the keys - have fun!"); 7 A% ~2 G4 p+ S6 L . g) v; {) W# ` S( M. Y} else {" k( Z# S/ O' U# T! i: h
# ^9 h# P, D3 B+ M {! I+ plog.info("Sorry, you aren't allowed to drive the 'eagle5' winnebago!");- f( ^" O/ J4 Y5 r& R2 I
# ~7 j$ s4 y# S( g/ `} g6 F' z. m1 c5 C; E4 a2 t
; t7 x4 w& h$ ^+ c' g# ~- R2 P. g( M( r小菜一碟,对吧。 + ]8 o9 A1 \# O+ f1 }* t2 M! v' F7 G' ^3 T, ]
最后,当用户使用完毕,还可以退出应用。 : g* W+ Q; R# G% F6 W8 Y3 a) {( X4 G0 a" _; P- m
currentUser.logout(); //removes all identifying information and invalidates their session too.4 K$ }, j! n8 I2 u- A$ ~
' {, ]. J% k) D- t! V3 Z4 M6 D
这些就是使用Apache Shiro开发应用的核心了,当然,Apache Shiro已将将很多复杂的东西封装在内部了,但是现在它就是这么简单。 ' d# P; ?$ ]6 s# D4 J" G3 n - W: _- `1 h( Z6 ~7 K: F& e4 Q你会有疑问吧,用户登录时,谁负责把用户信息(用户名、密码、角色、权限等)取出来,还有运行时,谁负责安全认证呢?当然由你决定了啊。通过将一个实现了Shiro中的Realm的Reaml配置到Shiro中即可。4 h9 b. S% p# S$ M
/ a+ L2 F( C" G4 \
至于如何配置很大程度上取决于你的运行时环境,比如在单应用、web应用、基于spring或JEE 容器的应用或者组合模式中使用Shiro,配置都有所不同。如何配置已经超出QuickStart示例的范围,因为它的主要目的是帮助你熟悉Shiro的API和概念。7 A3 X3 A! X; g7 _' b
, B0 T8 `4 _4 I1 W4 V
如果想进一步了解Shiro,可以看看Authentication Guide和Authorization Guide。也可以查看其他文档(特别是Reference Manual),这里可以解决你的各种疑问。+ O: V4 K, ^ @; o1 z9 F9 h