首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Spring和JPA存储库--如何通过ID过滤GET

Spring和JPA存储库--如何通过ID过滤GET
EN

Stack Overflow用户
提问于 2017-05-13 16:26:09
回答 3查看 16.4K关注 0票数 1

我正在重写一个应用程序,这次使用Spring的RESTful接口。我认为服务器端授权是最好的。这就是:

  • 假设用户1工作这个REST存储库。他/她访问mysite.com/英雄/1,并从英雄表中获取(id = 1)英雄。
  • 用户2没有看到(id = 1)英雄的权限,但无论如何都可以创建一个cURL语句来尝试。我声称服务器应该阻止用户2访问(id = 1)英雄。

我相信服务器可以提取给我用户名或密码的JWT有效负载(我把它放进去了)。从该有效负载中,服务器获取用户的帐户,并知道他/她有权看到哪些英雄。

我已经通过服务和DAO类实现了这个目标。但是,我看到的Spring和JPA教程提倡使用CrudRepository实现来减少编码。我想知道如何使用这种技术进行过滤。

下面是一个来自网络的例子:

代码语言:javascript
复制
@RepositoryRestResource(collectionResourceRel = "heroes", path = "heroes")
public interface HeroRepository extends CrudRepository<Hero, Long> {
}

当访问mysite.com/英雄/1时,它会自动从英雄返回数据(id = 1)。我想指示它让我选择允许哪个ID值。也就是说,在运行时,通过代码向其提供查询参数。

作为测试,我提供了以下代码:

代码语言:javascript
复制
@RepositoryRestResource(collectionResourceRel = "heroes", path = "heroes")
public interface HeroRepository extends CrudRepository<Hero, Long> {

    @Query ("from Hero h where id in (1, 3, 5)")
    public Hero get();

}

但是,它不会阻止mysite.com/英雄/2返回(id = 2)英雄。

我怎样才能达到我想要的目标?

谢了杰罗姆。

更新5/13,下午5:50

我的要求被误解了,所以我进一步解释我的意图。

  • 用户1和2是普通用户,访问他们的帐户。
  • 每个用户必须仅限于自己的帐户。
  • 用户不能通过伪造其他人的数据请求来欺骗他人。

因此,服务器需要从JWT令牌中提取用户ID,并将其应用于任何导致/heroes查询工作的代码中。

我最初的示例来自于本教程。其中唯一的Java类是Hero和HeroRepository。DAO、服务或控制器没有明确的类。所包含的Spring库允许所有的/heroes抓取都发生,而无需进一步编码。

再次感谢你所有的关心和帮助。杰罗姆。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-05-15 07:29:34

您可以创建一个自定义@Query,它使用登录用户的信息(此处为:id)。使用此解决方案,用户只能访问具有与他相同的id的实体。

代码语言:javascript
复制
@Override
@Query("SELECT h FROM Hero h WHERE h.id=?1 AND h.id=?#{principal.id}")
public Hero findOne(Long id);

您需要启用SpEl for @Query (链接)并使用自定义UserDetails创建一个自定义UserDetailsService (链接),其中包含用户的id,这样就可以执行principal.id了。

同样,您应该保护findAll()方法。

票数 1
EN

Stack Overflow用户

发布于 2017-05-13 21:55:04

根据我的理解,我创建了HeroRepository来解决所有的查询。

我想指示它让我选择允许哪个ID值。

你可以实现同样的使用。

代码语言:javascript
复制
List<Hero> findByIdIn(List<Long> ids);

或者,如果你喜欢Query

代码语言:javascript
复制
@Query("SELECT H FROM Hero H WHERE H.id IN :ids")
List<Hero> alternativeFindByIdIn(@Param("ids") List<Long> ids);

它不会阻止mysite.com/英雄/2返回(id = 2)英雄。

我看不到您的Controller/Service方法,因此我假设正在调用findOne()。你可以防止它使用..。

代码语言:javascript
复制
// Disallow everybody to use findOne()
default Hero findOne(Long id) {
    throw new RuntimeException("Forbidden !!");
} 

或者,如果您希望更多地控制您的方法调用,也可以使用来自spring-securityspring-security

代码语言:javascript
复制
// Authorization based method call
@PreAuthorize("hasRole('ADMIN')")
Optional<Hero> findById(Long id);

摘要

代码语言:javascript
复制
public interface HeroRepository extends CrudRepository<Hero, Long> {

    // Disallow everybody to use findOne()
    default Hero findOne(Long id) {
        throw new RuntimeException("Forbidden !!");
    }

    // If u want to pass ids as a list
    List<Hero> findByIdIn(List<Long> ids);

    // Alternative to above one
    @Query("SELECT H FROM Hero H WHERE H.id IN :ids")
    List<Hero> alternativeFindByIdIn(@Param("ids") List<Long> ids);

    // Authorization based method call
    @PreAuthorize("hasRole('ADMIN')")
    Optional<Hero> findById(Long id);

}

PS:请注意,我正在从方法返回Optional<Hero>。如果查询不产生任何结果,将返回Optional.empty()。这将迫使我们在执行任何操作之前检查值是否存在,从而避免了NullPointerException

票数 0
EN

Stack Overflow用户

发布于 2017-05-13 16:28:32

对控制器使用此代码:-

代码语言:javascript
复制
@RestController
@RequestMapping("/cities")
public class CityController {

private static final Logger logger = LoggerFactory.getLogger(CityController.class);

@Autowired
private CityService cityService;


@RequestMapping(value = "/{id}", method = RequestMethod.GET)
public RestResponse find(@PathVariable("id") Long id) {
.
.
}

使用以下代码进行回购:-

代码语言:javascript
复制
 public interface CityRepo extends JpaRepository<FCity, Long> {

@Query("select e from FCity e where  e.cityId = :id")
FCity findOne(@Param("id") Long id);

}

使用以下服务代码:-

代码语言:javascript
复制
@Service
@Transactional
public class CityService {

@Autowired(required = true)
private CityRepo cityRepo;

public FCity findOne(Long id) {
    return cityRepo.findOne(id);
}

}
票数 -4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43955406

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档