【发布时间】:2019-09-05 04:01:53
【问题描述】:
我的配置中有一个拦截器,我想禁止访问其他用户的资源。在 WebMvcConfig(实现 WebMvcConfigurer)内部,我有:
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new FolderInterceptor(userService, folderService))
.addPathPatterns(Mapping.FOLDER_MAPPING + "/{id}",
Mapping.UPDATE_FOLDER_MAPPING + "/{id}",
Mapping.DELETE_FOLDER_MAPPING + "/{id}",
Mapping.DOWNLOAD_FOLDER_MAPPING + "/{id}");
}
在我的 FolderInterceptor 中,我有一个 preHandle 方法获取访问的文件夹并检查其所有者:
Map pathVariables = (Map) request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
Long id = Long.valueOf((String) pathVariables.get("id"));
User user = userService.getLoggedAccount();
if (folderService.existsById(id)) {
Folder folder = folderService.findById(id);
if (folder.getOwner().getId().equals(user.getId())) {
return true;
}
else {
response.sendError(403, "Unauthorized");
return false;
}
}
else {
response.sendError(404, "Folder does not exist");
return false;
}
如果我打印文件夹对象,那一行也会出现同样的错误。
org.hibernate.LazyInitializationException: could not initialize proxy.
感谢您的帮助。
【问题讨论】:
-
没有 tx,因此没有 session/entitymanager,因此没有这个例外。您在拦截器中的代码属于单个事务服务方法。而不是调用拦截器中的所有不同方法。
-
我应该补充一点,我的一个朋友向我展示了他完美运行的项目,我采用了与他完全相同的拦截器方法,只重命名了他与我的对象(文件夹)。
-
它适用于另一个项目的事实并不意味着它会自动运行。您有他拥有的不同设置(可能没有打开的会话/实体管理器)。他没有延迟加载,你可能有。无论如何,理想情况下,它应该在一个单一的事务方法中,这将解决问题。或者修改您的对象模型以不使用延迟加载(但这可能会影响应用程序的其他部分)。
-
我的模型中没有延迟加载,我确定了这一点。而且除了依赖的版本不同,我们两个项目在结构上非常相似。如果不是版本的原因,我看不出来是什么。
-
get 永远不会访问数据库,并且总是使用 LAZY 代理直接返回。因此,即使实际实体不存在,它也会为您提供
Folder,并在您尝试对其调用 getter/setter 时立即导致问题,然后将转到数据库。查找将查询数据库并在未找到时返回实际的Folder或null。因此,您正在使用延迟加载...
标签: java spring session lazy-evaluation interceptor