3.1.1例
サブジェクトを検証するShiroのプロセスは、次の3つの異なるステップに分けることができます。
1.サブジェクトから提出されたプリンシパルと資格情報を収集します。
2. ID検証のためにプリンシパル(ID)と資格情報(証明書)を送信します。
3.送信が成功した場合は、アクセスを許可します。それ以外の場合は、再認証するか、アクセスをブロックします。
ID /資格情報を収集する
//ユーザー名/パスワードペアの最も一般的なシナリオを使用した例: UsernamePasswordTokentoken = newUsernamePasswordToken(username、password); //「RememberMe」組み込み: token.setRememberMe(true); |
UsernamePasswordTokenは、最も一般的なユーザー名/パスワード認証メカニズムをサポートしています。同時に、RememberMeAuthenticationTokenインターフェースを実装しているため、トークンを介して「rememberme」関数を設定できます。
エンティティ/資格情報を送信する
SubjectcurrentUser = SecurityUtils.getSubject(); currentUser.login(token); |
ID /資格情報を収集した後、SecurityUtilsツールクラスを介して現在のユーザーを取得し、loginメソッドを呼び出して認証を送信できます。
認証処理
試してみてください{ currentUser.login(token); } catch(UnknownAccountExceptionuae){..。 } catch(IncorrectCredentialsExceptionice){..。 } catch(LockedAccountExceptionlae){..。 } catch(ExcessiveAttemptsExceptioneae){..。 } ... catchyourown .. .. } catch(AuthenticationExceptionae){ //予期しないエラー? } |
ログインメソッドが実行され、例外メッセージがスローされない場合、ユーザー認証は渡されたと見なされます。その後、アプリケーションの任意の場所でSecurityUtils.getSubject()を呼び出して、現在の認証済みユーザーインスタンスを取得し、subject.isAuthenticated()を使用して、ユーザーが認証されているかどうかを判断してtrueを返すことができます。逆に、loginメソッドの実行中に例外がスローされた場合、認証は失敗と見なされます。
3.1.2手順
以下では、ID認証を行う際のShiroの内部処理について詳しく説明します。
上の図に示すように、Shiroアーキテクチャ図の認証部分を使用して、Shiro認証の内部処理シーケンスを示します。
1.アプリケーションは、ターミナルユーザー認証情報のAuthenticationTokenインスタンスを作成した後、Subject.loginメソッドを呼び出します。AuthenticationTokenインスタンスには、エンドユーザーのプリンシパルと資格情報が含まれています。
2. Sbujectのインスタンスは通常、DelegatingSubjectクラス(またはサブクラス)のインスタンスオブジェクトです。認証の開始時に、アプリケーションによって設定されたsecurityManagerインスタンスは、securityManager.login(token)メソッドの呼び出しを委託されます。
3. SecurityManagerは、トークン(トークン)情報を受信すると、組み込みのAuthenticatorインスタンス(通常はModularRealmAuthenticatorクラスのインスタンス)にauthenticator.authenticate(token)の呼び出しを委託します。ModularRealmAuthenticatorは、認証プロセス中に設定された1つ以上のレルムインスタンスを適応させます。実際には、Shiroにプラグ可能な認証メカニズムを提供します。
4.アプリケーションで複数のレルムが構成されている場合、ModularRealmAuthenticatorは、構成されたAuthenticationStrategy(認証戦略)に従って複数のレルムの認証プロセスを実行します。レルムが呼び出された後、AuthenticationStrategyは各レルムの結果に応答します。
注:アプリケーションでレルムが1つだけ構成されている場合、認証ポリシーを構成しなくても、レルムが直接呼び出されます。
5.各レルムが送信されたトークンをサポートするかどうかを判断します。サポートする場合、レルムはgetAuthenticationInfo(token)を呼び出します。getAuthenticationInfoメソッドは実際の認証プロセスです。レルムのdoGetAuthenticationInfoメソッドをオーバーライドしてカスタム認証プロセスを記述します。
3.1.3構成
オーセンティケーター
ShiroSecurityManagerの実装では、デフォルトでModularRealmAuthenticatorのインスタンスが使用されます。単一のレルムと複数のレルムの両方をサポートします。レルムが1つだけ構成されている場合、ModularRealmAuthenticatorは直接レルムを呼び出して認証情報を処理します。複数のレルムが構成されている場合、認証戦略に従ってレルムを適応させ、認証情報を実行するのに適したレルムを見つけます。
カスタムオーセンティケーターを介して実装されるようにSecurityManagerを構成する場合は、shiro.iniで以下を設定できます。
[メイン] … オーセンティケーター= com.foo.bar.CustomAuthenticator securityManager.authenticator = $ authenticationator |
AuthenticationStrategy(認証戦略)
アプリケーションが2つ以上のレルムで構成されている場合、ModularRealmAuthenticatorは内部AuthenticationStrategyコンポーネントに依存して、認証の成功または失敗を判別します。
AuthenticationStrategyは、認証の試行中に4回要求されるステートレスコンポーネントです(これらの4つの対話に必要なすべての状態がメソッドパラメーターとして使用されます)。
1.レルムが呼び出される前に尋ねられます。
2.単一のレルムのgetAuthenticationInfoメソッドが呼び出される直前に尋ねられます。
3.単一のレルムのgetAuthenticationInfoメソッドが呼び出された直後に尋ねられます。
4.すべてのレルムが呼び出された後に尋ねます。
認証戦略のもう1つのタスクは、レルムのすべての結果情報を集約してAuthenticationInfoインスタンスにカプセル化し、この情報をサブジェクトのID情報として返すことです。
Shiroは、次の3つの認証戦略の実現を定義しています。
AuthenticationStrategyクラス |
説明 |
AtLeastOneSuccessfulStrategy |
1つ(または複数)のレルム検証が成功している限り、検証は成功したと見なされます |
FirstSuccessfulStrategy |
最初のレルム検証は成功し、全体的な検証は成功したと見なされ、後続のレルムは無視されます。 |
AllSuccessfulStrategy |
すべてのレルムが成功し、認定は成功と見なされます |
ModularRealmAuthenticatorに組み込まれている認証戦略のデフォルトの実装は、AtLeastOneSuccessfulStrategyメソッドです。これは、このメソッドも広く使用されている認証戦略であるためです。もちろん、次のような構成ファイルを使用して、必要な戦略を定義することもできます。
[メイン] … authcStrategy = org.apache.shiro.authc.pam.FirstSuccessfulStrategy seurityManager.authenticator.authenticationStrategy = $ authcStrategy ..。 |
RealmAuthentication Order(レルム認証順序)
上記の認証戦略から、ModularRealmAuthenticatorのレルムの順序が認証に影響を与えることがわかります。ModularRealmAuthenticatorは、SecurityManagerで構成されたレルムを読み取ります。認証を実行すると、レルムコレクションをトラバースし、送信されたトークンをサポートするすべてのレルムでgetAuthenticationInfoメソッドを呼び出します。
暗黙の順序付け(ImplicitOrdering)
当使用Shiro 的INI 配置文件格式时,根据你在INI文件中定义好的顺序依次被处理。比如:
blahRealm = com.company.blah.Realm … fooRealm = com.company.foo.Realm … barRealm = com.company.another.Realm |
SecurityManager 根据这三个Realm 的配置顺序调用,依次是blahRealm,fooRealm 和barRealm顺序调用。与下面这样的效果是一样的。
securityManager.realms = $blahRealm, $fooRealm, $barRealm |
使用这种方法,你并不需要设置SecurityManager 的Realm 属性——每个定义好的realm 将会自动地被添加到realm 的属性。
显示排列(ExplicitOrdering)
明确地定义Realm的先后顺序,显式地配置securityManager.realms 的属性以表明你需要引用的Realm和它们的调用顺序。比如:
blahRealm = com.company.blah.Realm … fooRealm = com.company.foo.Realm … barRealm = com.company.another.Realm securityManager.realms = $fooRealm, $barRealm,$blahRealm |
这样调用的顺序依次是fooRealm,barRealm和blahRealm。
RealmAuthentication(Realm认证)
Realm 实质上就是一个特定安全的DAO。Realm 通常和数据源是一对一的对应关系,如关系数据库,LDAP 目录,文件系统,或其他类似资源。
若Realm 支持一个提交的AuthenticationToken,那么Authenticator 将会调用该Realm 的getAuthenticationInfo(token)方法。这代表了一个与Realm的后备数据源的认证尝试。该方法按以下方法进行:
1. 为主要的识别信息(帐户识别信息)检查token。
2. 基于principal 在数据源中寻找相吻合的帐户数据。
3. 确保token 支持的credentials 匹配那些存储在数据源的。
4. 若credentials 匹配,返回一个封装了Shiro 能够理解的帐户数据格式的AuthenticationInfo 实例。
5. 若credentials 不匹配,则抛出AuthenticationException 异常。
在上述过程中,Realm有一个职责就是匹配提交的credentials 和那些存储在Realm 后备数据存储中的credentials。Shiro 本身拥有CredentialsMatcher 实现,如SimpleCredenticalsMatcher 和HashedCredentialsMatcher,但你也可以根据自己的逻辑自定义一个实现。比如:
[main] … customMatcher = com.company.shiro.realm.CustomCredentialsMatcher myRealm = com.company.shiro.realm.MyRealm myRealm.credentialsMatcher = $customMatcher ... |
Shiro 中默认使用的是SimpleCredentialsMatcher,SimpleCredentialsMatcher 验证该密码是否与存储在数据库中的密码相同。SimpleCredentialsMatcher不仅仅为字符串执行直接相等比较。它能够处理大多数常用的字节码,像字符串,字符数组,字节数组,文件及输入流。
除此之外Shiro 还提供了HashedCredentialsMatcher,通过单向散列化方式实现一种更安全的方式存储终端用户的credentials。配置方式如下:
[main] … credentialsMatcher = org.apache.shiro.authc.credential.Sha256CredentialsMatcher # base64 encoding, not hex in this example: credentialsMatcher.storedCredentialsHexEncoded = false credentialsMatcher.hashIterations = 1024 # This next property is only needed in Shiro 1.0. Remove it in 1.1 and later: credentialsMatcher.hashSalted =true … myRealm = com.company…… myRealm.credentialsMatcher = $credentialsMathcer ... |