我正在使用Shiro来保护我的Spring MVC webapp。我正在使用Hibernate进行持久化,因此我有一个HibernateRealm来获取并填充AuthenticationInfo对象。
@Override
@Transactional
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken token) throws AuthenticationException {
Account account = accountDao.findByUsername((String)token.getPrincipal());
SimplePrincipalCollection principals = new SimplePrincipalCollection(account, getName());
SimpleAccount info = new SimpleAccount(principals, account.getPassword());
return info;
}
Account
是我的自定义用户类。我使用DAO按用户名检索Account
。我想知道这个方法@Transactional
是否有任何意义。毕竟这是一个只读操作。
我也遇到以下问题:DAO会sessionFactory.getCurrentSession()
进行会话,但我得到了
HibernateException: No Session found for current thread
调用方法时我在我的应用程序上下文中有这些:
<tx:annotation-driven transaction-manager = "transactionManager" />
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
我无法理解为什么Spring没有为我开会。
修改要登录,我们使用Shiro的@Controller
Subject
方法中执行此操作
@RequestMapping(value = "/account/login", method = RequestMethod.POST)
public String login(@RequestParam("username") String username, @RequestParam("password") String password) {
Subject currentUser = SecurityUtils.getSubject();
if (!currentUser.isAuthenticated) {
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
currentUser.login(token);
return "profile";
}
return "home";
}
在内部,Shiro使用我上面的领域方法来获取存储的用户名/密码信息。它使用@Autowired
DAO检查我的数据库中是否有正确的帐户。然后,它将密码与CredentialsMatcher
实施匹配。
答案 0 :(得分:2)
所以你有两个问题。通常最好将这些问题分成两部分,因为这些问题并没有真正相互联系。
@Transactional
注释不起作用。为了确保你可以在调试模式下运行你的代码或测试并在堆栈中查找JdkDynamicAopProxy或类似的东西 - 如果它存在,那么你的Realm是通过事务拦截代理调用的,但我想没有代理功能。要使它工作,您需要从SpringContext而不是直接从HibernateRealm获取,但是这个领域正在实现的接口。这是因为内置的标准java库代理只能处理接口。@Transactional(readOnly=true)
)可以通过正确配置提高性能(例如,对于真正高负载的应用程序,readOnly查询可能使用数据库服务器的辅助副本)。作为Spring事务的一部分,将java.sql.Connection.setReadOnly()
方法设置为比其他方式更容易。答案 1 :(得分:2)
看来Spring没有为你的Realm bean创建一个事务代理。这是我可以理解为什么Hibernate会话不可用的唯一原因 - 因为支持基础设施不在那里(在线程上)可以使用。
关于您的问题,如果您想标记@Transactional
,可以考虑指定@Transactional(readOnly=true)
答案 2 :(得分:0)
Shiro创建了它自己的Realm实例,因此Spring没有权力将它包装在代理中。这就是为什么它无法添加交易行为。