& s& n1 Q; O- T: f6 \if ( !currentUser.isAuthenticated() ) { ( K+ R, Y7 b0 ^: ^; \& w: G: [9 s$ C* y
//collect user principals and credentials in a gui specific manner ' F/ d' i" T# ] " u6 ]/ G& G4 L) W% y! v/ d//such as username/password html form, X509 certificate, OpenID, etc.& z1 ^& g# N' B% p p5 s
1 G' t5 x7 }0 n8 A: O2 a i, T" R
//We'll use the username/password example here since it is the most common. C( O7 \7 Q9 } Y! U& \) |$ p% ^6 b3 q/ {5 ^# N
//(do you know what movie this is from? ;)9 G( x1 s& S* P! \+ m
. a5 P# u+ R1 {6 i+ ~! d
UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa"); s2 X7 c% J/ E8 k( |- A: U( _' W8 S, j. q( N$ G6 [
//this is all you have to do to support 'remember me' (no config - built in!): 2 E4 l6 H' X8 F: R) z* d+ B% r5 v" W9 n" @3 b- R
token.setRememberMe(true); " ~; I. _2 D9 ^- @1 I : i4 _- ]. \; P) p9 qcurrentUser.login(token);0 g$ ^% c2 b5 p: Y3 i% q+ \& \
* r4 B. ?! o+ E$ ScurrentUser.login( token );. x# @( u5 E% T$ r" i: r; P3 n
* r: h5 c! F; w//if no exception, that's it, we're done!6 V0 w5 K6 }, X- d' i
. o" W# v' i c. u} catch ( UnknownAccountException uae ) { 9 c3 |0 I* w ?2 w- O5 Y. ?' X3 r( u3 w* w* N
//username wasn't in the system, show them an error message?: c, a& n2 |- `( u8 O
; Q6 _1 c& }1 f} catch ( IncorrectCredentialsException ice ) { & f4 z2 z. k$ r% V6 ~ ; S+ j3 D+ N5 l, q+ Z5 D- ~8 s//password didn't match, try again?7 Y: J) q* i" C' [: g {
4 T. ]$ L4 F7 L5 [
} catch ( LockedAccountException lae ) { $ S s! ?/ r5 N$ ^' W4 G9 c8 Q 9 y" k9 i5 P$ Z$ r//account for that username is locked - can't login. Show them a message?3 i& E) l* B% P' C2 L
2 C. L2 C( v+ Y$ u9 n1 u+ t, A
} $ B: j ~3 S8 z/ u& S ; K: X3 ~9 f0 f... more types exceptions to check if you want ...5 K8 Z; M. F1 Q" p
9 x* H/ B3 g/ D7 U
} catch ( AuthenticationException ae ) {" T3 u' L1 n* D7 T* s
! `! Q9 M, A% T* X9 ]. X. \
//unexpected condition - error?* {/ m# C+ ^4 Z8 z4 d
% P* l. m6 E* \. c% j}$ ~- r! v! z& F( D( z$ C
7 Q8 v5 {, |1 d9 R, h
可以捕获Shiro提供的各种异常,也可以抛出自定义类异常用于处理Shiro未考虑到的情况。预知详情,可以去了解AuthenticationException JavaDoc。$ o. x4 K O5 Z( z$ d1 Z
6 \) m- O: v D& q q4 u4 l
提示:最安全的做法是将登录失败的消息告知用户,你总不会帮助攻击者入侵你的系统吧! 9 @; d/ o4 i5 K ~ ) \! Z% B+ E! N: fOK,现在已经拥有一个登录用户了,我们还能做点儿什么呢? 5 h7 E, j# n7 V1 |; ?9 }1 T5 I: O8 P& |, e0 S) U* m1 K
比方说,他们是谁: ; e; x$ q8 z9 A8 M4 e5 U! Y ?! _6 T0 U9 N$ J( ^//print their identifying principal (in this case, a username):, V! k" E" c+ g4 a
/ j( B2 |* K! ?0 Ulog.info( "User [" + currentUser.getPrincipal() + "] logged in successfully." ); ' B, Y3 h0 J! i$ I' c- k" U% m, q' M$ E7 V* [- y
也可以判断用户是否拥有特定的角色:3 [/ o2 y9 K/ V. r
: q; ~' a6 \- `+ j2 _
if ( currentUser.hasRole( "schwartz" ) ) {: R8 }" i# b# i5 S6 B
2 V. `. X- g- w4 c4 ]0 f7 V* i( olog.info("May the Schwartz be with you!" );0 q9 `3 S v; R ~6 C) F" ?
5 E' Z e* Z( x1 k: z7 m; U& `% V
} else {# S( w G3 G" F7 @) _
; E O) u! }/ z4 r0 b+ v
log.info( "Hello, mere mortal." ); : g5 `$ ]5 h) z s; c- t% {+ v4 x" W; c W8 l
} 0 |+ ~; C2 X! o7 q; Y6 @9 B3 z" z7 a) f: Y6 D/ Y* M% k- F
还可以判断用户是否对特定某实体有操作权限:; P# C+ g6 C, O2 C# G7 o
/ x1 m4 Z. X6 b6 ?
if ( currentUser.isPermitted( "lightsaber:weild" ) ) {6 j- ?; ?. `' b
/ i- P) M$ g; n, e D' V7 d
log.info("You may use a lightsaber ring. Use it wisely.");/ h T4 e9 r- `* }/ B4 K
4 n; ^. d8 K+ z+ W% s
} else { 0 b) W7 }' v: m+ [7 h. E( V2 E4 n; z ! j; I+ k, w# U& y! elog.info("Sorry, lightsaber rings are for schwartz masters only."); % _- p/ q3 I8 l' Y& z8 G + Y! J7 ~$ x" @4 l}. U1 Z S- b, ?8 j3 e4 ~
% m4 H5 _. Y+ C; |. J/ |" ?2 k$ R
当然,还可以进行功能强大的实例级别的权限验证。通过它可以判断用户是否有访问特定类型实例的权限:) K+ l: h5 a. e# K: X
5 c* Y7 s/ L+ T- m4 I6 \) E4 e
if ( currentUser.isPermitted( "winnebago:drive:eagle5" ) ) { + P& K% _ \# H6 {. j1 m& v4 W4 b1 C; `
log.info("You are permitted to 'drive' the 'winnebago' with license plate (id) 'eagle5'. " +"Here are the keys - have fun!");; S3 ?# w7 C$ {
; G1 n" p% |/ Q+ b3 m/ L6 y} else {& k# o( J5 A: x) |5 C
: I, o- V0 D( b9 c5 G& Y# ~ T
log.info("Sorry, you aren't allowed to drive the 'eagle5' winnebago!");3 z* W; v) l* {! J
1 j- R; p! W( c! L0 g}1 @) K$ B6 Y6 b6 P1 H- Q1 E
" N/ Y8 W, i* k0 o7 D& e" G! H
小菜一碟,对吧。5 Z: F2 _# V: |4 {/ T
/ Q! A) o j# m9 y+ L% o) O
最后,当用户使用完毕,还可以退出应用。1 |( n% G6 o& }/ I
2 m2 ?0 a* |, E
currentUser.logout(); //removes all identifying information and invalidates their session too. $ C' `! {8 V- _& L 0 u$ M6 ~: K; q& W( k6 l# ~这些就是使用Apache Shiro开发应用的核心了,当然,Apache Shiro已将将很多复杂的东西封装在内部了,但是现在它就是这么简单。 # E, {4 S- Q9 @3 E' [; d! q" d$ W + l$ f. B' i& E( h$ X你会有疑问吧,用户登录时,谁负责把用户信息(用户名、密码、角色、权限等)取出来,还有运行时,谁负责安全认证呢?当然由你决定了啊。通过将一个实现了Shiro中的Realm的Reaml配置到Shiro中即可。 ! p; v( P+ o4 H J1 a) H* Y) W# ^ + b* F* C0 W- j" m8 r8 |至于如何配置很大程度上取决于你的运行时环境,比如在单应用、web应用、基于spring或JEE 容器的应用或者组合模式中使用Shiro,配置都有所不同。如何配置已经超出QuickStart示例的范围,因为它的主要目的是帮助你熟悉Shiro的API和概念。: L, E0 W! g2 s1 ~/ ] k$ G6 T
5 m& p |' [6 j+ f. M如果想进一步了解Shiro,可以看看Authentication Guide和Authorization Guide。也可以查看其他文档(特别是Reference Manual),这里可以解决你的各种疑问。# q; g& F! z0 n( X) N- O6 V
9 c* C: A k7 O; t. `1 N7 k