适用于复杂主键的安全persistenceId编码器

问题描述

persistenceId(字符串,字符串)生成complex key的最佳方法是什么,并且此密钥的每个部分都不受控制(可能包含任何符号)?

  1. 如果需要解码
  2. 如果不需要解码(原始密钥存储在actor中)

解决方法

一种可能是将密钥的第一个字符串的长度编码为persistenceId的第一个字符。 Scala中的示例:

import scala.util.Try

type ComplexKey = (String,String)

def persistenceIdFor(key: ComplexKey): String = {
  val (first,second) = key
  val firstLen = first.length
  s"${firstLen};${first},${second}"
}

val PersistenceIdRegex = """^(\d+);(.*)$""".r

// You might not necessarily ever need to get a key for a given persistenceId,but to show the above is invertible
def keyForPersistenceId(persistenceId: String): Option[ComplexKey] =
  persistenceId match {
    case PersistenceIdRegex(firstLenStr,content) =>
      val firstLenTry = Try(firstLenStr.toInt)

      firstLenTry
        .filter(_ <= content.length)
        .toOption
        .map(firstLen => content.splitAt(firstLen))

    case _ => None
  }

另一种方法是使用转义,但是尽管起初看起来很简单,但还是有很多微妙之处。

正在使用的特定Akka Persistence后端可能会对persistenceId施加限制(例如ID的长度)。