spring / hibernate - 按当前用户ID过滤

时间:2010-10-08 14:37:23

标签: hibernate spring-mvc spring-security

我的Oracle数据库中有一个表CompanyList:

CMP_ID INTEGER -- ID of company
CMP_NAME VARCHAR2 -- name of company
USR_ID INTEGER -- Foreign key to the USERS table

我的Spring 3 MVC应用程序全部使用注释配置,我的POJO也是,我的DAO对象(CompanyDao)使用hibernate来检索例如公司列表。

公司道:

@Transactional
    public Set<Company> findAllCompanys() throws DataAccessException {

        return findAllCompanies(-1, -1);
    }

    @SuppressWarnings("unchecked")
    @Transactional
    public Set<Company> findAllCompanies(int startResult, int maxRows) throws DataAccessException {
        Query query = createNamedQuery("findAllCompanies", startResult, maxRows);
        return new LinkedHashSet<Company>(query.getResultList());
    }

我的公司域名:

@Entity
@NamedQueries( {
        @NamedQuery(name = "findAllCompanies", query = "select myCompany from Company myCompany")})
...
public class Company implements Serializable {
...

然后我设置了弹簧安全性,因此我的所有页面都需要识别。

使用当前登录用户会话的USER ID过滤CompanyDao返回的行的最佳方法是什么?

2 个答案:

答案 0 :(得分:2)

简答:SecurityContextHolder。

答案稍长: 如果作为user_id外键关系的父端的User实体也实现UserDetails接口,则可以在Spring的安全上下文中直接使用User实体。

您可以从DAO层或其上方的层调用SecurityContextHolder.getContext()方法......这并不重要,因为返回的实例将作用于请求的本地线程。

然后,您可以从上下文实例获取UserDetails,将其强制转换为您的User实体,并将其作为命名参数传递给DAO调用。

作为一个快速跟进,我意识到你的原始问题意味着你运行目前存在的命名查询,然后筛选出不匹配的公司。您仍然可以通过将与公司关联的用户与安全上下文中的用户进行比较来使用该方法,但一般情况下我不建议采用这种方法;向数据库询问您需要的确切内容。

答案 1 :(得分:1)

实际上,Spring Security 3可以使用@PostFilter注释过滤返回的集合,请参阅15.3.1 @Pre and @Post Annotations

但我想在你的情况下,当CompanyUser有多对一的关系时,Jeff的建议更合适 - 你应该为查询添加一个条件,即替换{{1 } findAllCompanies(),并在演示文稿或服务层将findAllCompaniesForUser()提取的userId作为参数传递。