' K+ ^2 s+ A, }+ [$ ]3 x$ @; t+ _//collect user principals and credentials in a gui specific manner " l1 P* P/ f( w$ g& k1 c2 K# W& ?5 { u
//such as username/password html form, X509 certificate, OpenID, etc. , _% P! j+ O, `# u3 G2 J9 }. Q
//We'll use the username/password example here since it is the most common.7 y) y# N H6 X
, r) o7 f. X' O//(do you know what movie this is from? ;) 9 L2 [/ r/ A3 X5 p! ?' r/ q4 p# {7 v& n, n* j
UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");' c1 Z) b s( \6 y: P/ S
/ V1 f, _) S0 w2 y. U
//this is all you have to do to support 'remember me' (no config - built in!):9 D- d8 O% c4 F2 d# Q
, @' W8 |4 j' K9 @
token.setRememberMe(true); 7 e. Y: B' s0 x5 U% L4 } + ?9 b" u6 }9 \- J( x$ e/ V8 ecurrentUser.login(token); ! K6 H# f, {3 H' a- P% Y& c3 p$ m3 Q9 k2 i( C# o5 b0 i! \/ H+ v
} $ {) N) N; n! |3 e: X. h' T! J! s( p2 ^- F% t1 c y: z
就是这样,太简单了吧!! A) G! U7 \3 y" O! {& ]
1 U/ t7 G# G o4 X0 l
那登录失败了怎么处理呢?可以通过捕获各类异常,根据不同类型的异常做出不同的处理: ! R/ ~7 S* y+ K2 x5 A ( H$ s# M E8 Vtry { i7 P& P% Y& u' b0 x& j
+ b% R% \, A& v$ k( X8 O
currentUser.login( token );" [9 h9 d5 C. z6 H
5 X1 t/ Q% M; @1 E
//if no exception, that's it, we're done! , E, p, P' t4 k; d3 _0 V ? 4 J. l; `, A) x7 C% r& e} catch ( UnknownAccountException uae ) {& @% `2 a, T$ Z
' _/ b' B7 L7 x) x/ O1 J//username wasn't in the system, show them an error message? , k2 `3 _; K) B4 A7 O3 P ; ]" I$ c: r, o, a% b} catch ( IncorrectCredentialsException ice ) {( c% E% [ p. s5 n. |4 ^5 ^8 z
, u6 Z! m9 H$ Y5 u& R& f
//password didn't match, try again? ) V+ z4 f' A. A O/ @, X 1 }% R. M' g; ~} catch ( LockedAccountException lae ) {' b8 p/ E4 k0 K2 k, v) Q
- n, f% h- }! E* ~//account for that username is locked - can't login. Show them a message?' C0 E9 L& J9 I
4 R. ]( L) o$ I& k- [2 o5 k' o
}6 x3 _9 y4 Y e% F% c9 i1 f
+ Q2 }. s/ ~! g& G* x... more types exceptions to check if you want ... ' j6 M7 H. \( B& j7 Q: V# O# c) t: Q7 f
} catch ( AuthenticationException ae ) { 9 U- k1 A% C; l$ m4 s, o% ?, ^: v! D2 H. C4 [' F
//unexpected condition - error?2 P# [* G u: J5 T; A/ D9 @2 W9 @0 K7 a, l
0 _+ r9 F7 T6 U
} 8 a9 A* ]! d5 q/ `! \2 [( I4 ]# d, [$ `
可以捕获Shiro提供的各种异常,也可以抛出自定义类异常用于处理Shiro未考虑到的情况。预知详情,可以去了解AuthenticationException JavaDoc。 0 F/ f# \+ N0 }' v$ ^/ V, q& @8 u) }9 E: @
提示:最安全的做法是将登录失败的消息告知用户,你总不会帮助攻击者入侵你的系统吧! G8 h8 R( b) M' V ' d5 T$ l: M! j/ aOK,现在已经拥有一个登录用户了,我们还能做点儿什么呢? 2 U5 X$ N k3 b9 r, c9 b0 i$ n / z( a F% X5 U0 V# S% N比方说,他们是谁:: O, u" k5 y: G5 l1 G; K
. s4 E- H T9 _4 `2 Y3 h
//print their identifying principal (in this case, a username):% a0 H P/ U) e/ O! a1 G4 G
% g1 D9 s0 t* q9 T还可以判断用户是否对特定某实体有操作权限:: s X2 P N, h' O8 [! V
7 Q6 ^( ]; i2 {1 E, A' L
if ( currentUser.isPermitted( "lightsaber:weild" ) ) {- T% ~9 W' f+ A/ Q
3 }3 Z# q" X/ k& j; B
log.info("You may use a lightsaber ring. Use it wisely."); ; U7 P; U: \, E, v( Z' j+ X0 h& u* m( I6 g7 g3 ]& X
} else {% P4 V0 R+ {* `; b& W, K
) J2 U C9 N6 t, c* k/ Z+ V( Zlog.info("Sorry, lightsaber rings are for schwartz masters only.");$ V0 ~0 T8 l) b( I" u6 E$ f
2 ?% s/ E. V0 R6 C& ^- ~}6 ?+ F( S- z1 k8 H/ ?
: M. R) S9 P# T; x3 V& v
当然,还可以进行功能强大的实例级别的权限验证。通过它可以判断用户是否有访问特定类型实例的权限: ' X: E# i- x$ K4 n! L6 a& t' {; J - r" C3 }/ W: _$ a( H) vif ( currentUser.isPermitted( "winnebago:drive:eagle5" ) ) { ( A$ x, i e) ]: m/ N) {0 ] 9 U& y: G6 j) s/ [) G0 e" q3 {log.info("You are permitted to 'drive' the 'winnebago' with license plate (id) 'eagle5'. " +"Here are the keys - have fun!"); : i, g: E2 z/ b* H. H; m; [; p7 v9 j# T/ R; _1 o* p) @2 }2 U; n
} else {. E6 @3 B$ K! V+ d
6 }! A1 v$ l$ d9 ?
log.info("Sorry, you aren't allowed to drive the 'eagle5' winnebago!"); 8 w, b& f7 i# w- O! ]4 C' e ( y" Z8 c9 }. I( ]' J! X}. V i9 s1 y+ |) z5 S# y- B' g
9 _" Y2 }% d" K/ _9 e. V
小菜一碟,对吧。( H" I; X% j# b- b
# _4 Z: l0 C5 e+ O! v, u. ^, D {
最后,当用户使用完毕,还可以退出应用。 1 f% i6 u$ h* L) O! g2 M5 F * e8 ?6 S$ K3 U% C7 d- x7 L' p" ^currentUser.logout(); //removes all identifying information and invalidates their session too. q* `0 q" |0 {
% v: P! T) i/ Z! s! d' [
这些就是使用Apache Shiro开发应用的核心了,当然,Apache Shiro已将将很多复杂的东西封装在内部了,但是现在它就是这么简单。 3 N" ~3 [& d7 _( r" D" E7 R2 d8 N" _* d
你会有疑问吧,用户登录时,谁负责把用户信息(用户名、密码、角色、权限等)取出来,还有运行时,谁负责安全认证呢?当然由你决定了啊。通过将一个实现了Shiro中的Realm的Reaml配置到Shiro中即可。 ( e/ H% Q1 m/ D+ R' _9 S. j4 E 8 C+ I9 W. w. g至于如何配置很大程度上取决于你的运行时环境,比如在单应用、web应用、基于spring或JEE 容器的应用或者组合模式中使用Shiro,配置都有所不同。如何配置已经超出QuickStart示例的范围,因为它的主要目的是帮助你熟悉Shiro的API和概念。 : Z3 P7 D6 \- O& Y/ c - E( t" B1 E' s' S- F/ w0 m如果想进一步了解Shiro,可以看看Authentication Guide和Authorization Guide。也可以查看其他文档(特别是Reference Manual),这里可以解决你的各种疑问。9 P T' \( |4 v8 r! Z2 Z
1 K4 J, r: u" U3 q