Zend-Authentication:将身份设为加载RBAC角色的自定义对象
你已经离目标很近啦!要让AuthenticationService::getIdentity()返回你的AuthenticatedIdentity对象,只需要利用AuthenticationService自带的存储组件,覆盖会话中Zend_Auth条目里的内容就行,具体操作如下:
直接写入自定义Identity到Auth存储
在你创建完$identity对象之后,只需要调用AuthenticationService的getStorage()->write()方法,把自定义对象写入会话存储:
// 你已有的创建Identity的代码 $identity = new AuthenticatedIdentity( $authenticationResult->getIdentity(), 'admin', $permissions, $roles ); $identity->setUserId($authenticationResultRow->user_id); // 新增这行:把自定义Identity写入Auth会话存储,覆盖默认的用户名 $this->authenticationService->getStorage()->write($identity); return $this->redirect()->toRoute('dashboard');
这样之后,无论你在项目哪个地方调用$this->authenticationService->getIdentity(),都会返回这个包含用户ID、角色和权限的自定义对象了。
为什么这个方法有效?
默认情况下,ZF2的AuthenticationService使用SessionStorage作为存储介质,它默认的会话键就是Zend_Auth。当你调用authenticate()方法时,AuthAdapter会把验证成功后的标识(默认是你传入的用户名)写入这个存储。而我们调用write()方法,就是直接覆盖这个存储里的内容,把原来的字符串替换成你的自定义Identity对象。
进阶方案:让AuthAdapter直接返回自定义Identity
如果你想让代码更优雅,不想在Controller里手动创建Identity,可以自定义你的AuthAdapter,在authenticate()方法中直接构造并返回包含自定义Identity的AuthenticationResult。比如:
在你的AuthAdapter类中调整验证逻辑:
public function authenticate() { // 这里写你的用户验证逻辑,比如查询数据库用户数据... // 验证成功后构造自定义Identity $permissions = $this->rbacService->getPermissionsForUser($userRow->user_id); $roles = $this->rbacService->getRolesForUser($userRow->user_id); $identity = new AuthenticatedIdentity( $userRow->username, 'admin', $permissions, $roles ); $identity->setUserId($userRow->user_id); // 返回包含自定义Identity的AuthenticationResult return new AuthenticationResult( AuthenticationResult::SUCCESS, $identity, ['登录成功'] ); }
这样当你调用$authenticationService->authenticate($adapter)时,验证成功后会自动把这个自定义Identity写入存储,不需要在Controller里额外调用write()方法。
注意事项
- 确保你的
AuthenticatedIdentity类是可序列化的(PHP普通类默认支持,但如果包含不可序列化的属性,需要实现Serializable接口),因为会话存储需要序列化对象才能保存。 - 如果你之前修改过AuthenticationService的存储配置,要确认
getStorage()返回的是你当前使用的存储实例(默认是SessionStorage)。
内容的提问来源于stack exchange,提问作者John Crest

