簡體   English   中英

Spring Data Rest查找通過安全性檢查嵌套實體

[英]Spring data rest findBy securityCheck for nested entity

我將Spring-data-rest用於REST接口,並且在暴露的端點上實現了自定義安全檢查。 一切正常,但是現在我遇到了一些不平常的情況,我想知道spring數據剩余是否能夠解決這個問題。

我有以下模型:

@Entity
public class Cycle {

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  @Column(name = "unique_cycle_id")
  private long id;

  @Column(name = "user_id")
  private long userId;

  ...

  @OneToMany(cascade = CascadeType.ALL)
  @JoinTable(name = "cycles_records", joinColumns = @JoinColumn(name = "unique_cycle_id"),
      inverseJoinColumns = @JoinColumn(name = "unique_record_id"))
  private List<Record> records;
}

@Entity
public class Record {

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  @Column(name = "unique_record_id")
  private long id;

  ...
}

在獲取周期時,我檢查登錄用戶的ID是否與我的Cycle實體中的userId相同。

我已經實現了像這樣的膀胱囊腫安全檢查:

@Slf4j
@Component
public class SecurityCheck {

  public boolean check(Record record, Authentication authentication) {
    log.debug("===Security check for record===");
    if (record == null || record.getCycle() == null) {
      return false;
    }

    return Long.toString(record.getCycle().getUserId()).equals(authentication.getName());
  }

  public boolean check(Cycle cycle, Authentication authentication) {
    if (cycle == null) {
      return false;
    }

    return Long.toString(cycle.getUserId()).equals(authentication.getName());
  }
}

但是現在,我正在嘗試對記錄進行類似的安全檢查。 因此,在獲取給定周期的記錄時,我需要檢查周期的userId是否與身份驗證對象中的id匹配。

我的RecordRepository上有以下方法:

@Repository
public interface RecordRepository extends JpaRepository<Record, Long> {

      @PreAuthorize("hasRole('ROLE_ADMIN') OR @securityCheck.check(???, authentication)")
      Page<Record> findByCycle_Id(@Param("id") Long id, Pageable pageable);
}

是否可以在此securityCheck中使用此方法查詢的id訪問周期內的userId? 如果沒有,Spring實現此功能的正確方法是什么?

抱歉,我的問題不清楚。 讓我知道是否需要進一步說明。

編輯:我通過訪問后過濾器中返回的頁面找到了快速又骯臟的解決方案。 缺點是,當返回的數組為空時,我可以訪問不屬於登錄用戶的記錄(因此,我仍在尋找更優雅的解決方案)

@PostAuthorize("hasRole('ROLE_ADMIN') OR @securityCheck.check(returnObject, authentication)")
Page<Record> findByCycle_Id(@Param("id") Long id, Pageable pageable);

public boolean check(Page<Record> page, Authentication authentication) {
    log.debug("===Security check for page===");
    if (!page.hasContent()) {
      return true;
    }

    long userId = page.getContent().get(0).getCycle().getUserId();

    return Long.toString(userId).equals(authentication.getName());
  }

如果我正確理解你的話...

首先,確保啟用了SpEL EvaluationContext擴展

然后執行以下操作:

public interface RecordRepository extends JpaRepository<Record, Long> {

    @Query("select r from Record r join r.cycle c where c.id = ?1 and (c.userId = ?#{@RecordRepository.toLong(principal)} or 1 = ?#{hasRole('ROLE_ADMIN') ? 1 : 0})")
    Page<Record> findByCycleId(Long id, Pageable pageable);

    default Long toLong(String name) {
        return Long.valueOf(name);
    }
}

我想這個principal包含userId的字符串表示形式,因此在這里我將其轉換為long形式然后進行比較...

您也可以檢查我與此問題相關的示例 ...

更新

相反的@RecordRepository.toLong(principal)在規划環境地政司表達嘗試用T(java.lang.Long).valueOf(principal) ,並刪除toLong從您的回購方法。

如果您只需要在檢查userId與您登錄的用戶相同的同時獲取“周期”的特定記錄,我將使用類似以下內容的方法:

Page<Record> findByCycle_IdAndUserId(Long cycleId, Long userId, Pageable pageable);

JPA本身可以處理很多工作,而無需您手動創建查詢。 請參閱https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.query-methods中的查詢方法。

當然,這意味着安全檢查需要在控制器端通過Spring Security而不是模型端進行處理。 您的DAO不必擔心請求是否有效/授權,因為這些檢查是事先完成的。

干杯

您可以在應用程序中引入兩個處理程序,如下所示:-

  //This is your Request handler

public class CxfHttpRequestHandler extends AbstractPhaseInterceptor<Message> {


    public CxfHttpRequestHandler() {
        super("marshal");
    }

    @Override
    public void handleMessage(final Message message) throws Fault {
        //handle your all request here
       }
}

//this is your Response handler
public class CxfHttpResponseHandler extends AbstractPhaseInterceptor<Message> {

    public CxfHttpResponseHandler() {
        super("pre-stream");
    }

    @Override
    public void handleMessage(final Message message) throws Fault {
        //handle your outgoing message here
    }
}


Add the following  in your spring-bean.xml file:-

<bean id="cxfHttpRequestHandler" class="com.yourpackage.CxfHttpRequestHandler" >
        <description>
            This Bean implements Interceptor for all request
        </description>
</bean>

<bean id="cxfHttpResponseHandler" class="com.yourpackage.CxfHttpResponseHandler">
        <description>
            This Bean implements Interceptor for all response
        </description>
    </bean>

<cxf:bus>
        <cxf:inInterceptors>
            <ref bean="cxfHttpRequestHandler" />
        </cxf:inInterceptors>

        <cxf:outInterceptors>
            <ref bean="cxfHttpResponseHandler" />
        </cxf:outInterceptors>

</cxf:bus>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM