通过覆盖
对shiro的AuthorizingRealm
(或仅AuthenticationRealm
)进行子分类时
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
}
我的工作是检查AuthenticationToken中提供的凭据是否实际匹配?
或者我应该返回AuthenticationInfo
principals
已解决AuthenticationToken
来自namespace MyVendor\MyExt\Scheduler;
class MultiStepProcessTask extends \TYPO3\CMS\Scheduler\Task\AbstractTask {
public function execute() {
$objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Extbase\\Object\\ObjectManager');
$businessLogic = $objectManager->get(\MyVendor\MyExt\Scheduler\MultiStepProcessTaskBusinessLogic::class);
return $businessLogic->run();
}
}
和给定凭据的正确密码,shiro会在流程中的某个地方对它们进行比较Subject.login(AuthenticationToken)调用?
答案 0 :(得分:2)
AuthenticatingRealm.doGetAuthenticationInfo()
州的Javadocs(强调我的):
从给定身份验证令牌的特定于实现的数据源(RDBMS,LDAP等)中检索身份验证数据。
对于大多数数据源而言,这意味着只需“拉动”数据源。关联主题/用户的身份验证数据,仅此而已让Shiro完成其余工作。但在某些系统中,除了检索数据外,此方法实际上还可以执行EIS特定的登录逻辑 - 这取决于领域实施。
方法AuthenticatingRealm.getAuthenticationInfo()
首先调用doGetAuthenticationInfo()
,然后使用配置的assertCredentialsMatch()
调用credentialsMatcher
:
public final AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
AuthenticationInfo info = getCachedAuthenticationInfo(token);
if (info == null) {
//otherwise not cached, perform the lookup:
info = doGetAuthenticationInfo(token);
log.debug("Looked up AuthenticationInfo [{}] from doGetAuthenticationInfo", info);
if (token != null && info != null) {
cacheAuthenticationInfoIfPossible(token, info);
}
} else {
log.debug("Using cached authentication info [{}] to perform credentials matching.", info);
}
if (info != null) {
assertCredentialsMatch(token, info);
} else {
log.debug("No AuthenticationInfo found for submitted AuthenticationToken [{}]. Returning null.", token);
}
return info;
}
因此,根据您的Realm实现的典型程度,您可能希望避免在AuthenticationToken
方法中查看doGetAuthenticationInfo()
的凭据,因为已经getAuthenticationInfo()
模板方法包含确保提交的凭据匹配的步骤。
如果您有责任专门解决您的问题,并且要检查AuthenticationToken中提供的凭据是否与#34;实际匹配,那么答案是是,但不是doGetAuthenticationInfo()
方法即可。通常,您将在CredentialsMatcher
接口的实现中执行凭据比较,如here所述。
答案 1 :(得分:0)
在doGetAuthenticationInfo(...)中,您需要验证用户是否为您提供了身份验证证明。
以下是您可能会做的伪编码示例:
protected AuthenticationInfo doGetAutheticationInfo(AuthenticationToken token) {
if(token instanceof UsernamePasswordToken) {
String username = token.getUsername();
// Look up the user by the provide username
UserRecord userRecord = lookupUserRecord(username);
// No record found - don't know who this is
if (userRecord == null) {
throw new UnknownAccountException();
}
// Check for other things, like a locked account, expired password, etc.
// Verify the user
SimpleAuthenticationInfo sai = new SimpleAuthenticationInfo(userRecord.getPrincipal(), userRecord.getHashedCredentials(), userRecord.getCredentialsSalt(), getName());
boolean successfulAuthentication = getCredentialsMatcher().doCredentialsMatch(token, sai);
if(successfulAuthentication) {
// Check for anything else that might prevent login (expired password, locked account, etc
if (other problems) {
throw new CredentialsException(); // Or something more specific
}
// Success!
return sai;
} else {
// Bad password
throw new IncorrectCredentialsException();
}
}
// Don't know what to do with this token
throw new CredentialsException();
}
您必须编写lookupUserRecord(用户名)或类似的东西来查找用户信息,包括他的散列和盐渍凭证。
答案 2 :(得分:0)
doGetAuthenticationInfo是完成身份验证的主要方法。因此,如果您覆盖它,通常会覆盖身份验证过程。如果你想使用为那个reealm定义的进程并做一些额外的事情,最好先调用超类方法然后获取它的信息,然后使用它,这样你就不必改变任何东西了。同样在jdbcrealm的情况下,shiro.ini中的sqls会自动映射。并且在你覆盖之前不会改变它们 setAuthenticationQuery,setUserRolesQuery等
您可以轻松调用以下方法来模拟实际过程,然后对其进行自定义。
AuthenticationInfo info = super.doGetAuthenticationInfo(token);
注意,super是对父级的引用,但是super()是它的构造函数。
像:
public class CustomJdbcRealm extends JdbcRealm
{
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException
{
AuthenticationInfo info = super.doGetAuthenticationInfo(token);
// Your own code here
}
}