Following up on this question, which was quite useful when i ran into the same problem. The main goal is to provide some extra information on Les Hazlewood's suggested implementation. Another good alternative source of information is also this topic https://groups.google.com/forum/#!topic/spray-user/wpiG4SREpl0
Shiro is currently thread based, meaning it binds the subject information to the current thread. This is an issue for Akka as it uses thread pools of dispatchers and workers.
As the threads get reused, the subject leaks from one request into the another, leading to unauthenticated request being process as authenticated as well as the opposite.
As Les awesomely suggested, a possible solution for the issue is to abandon the thread binding and store the subject on the Akka messages. For this to work it means the static methods provided on Shiro's SecurityUtils cannot be used. The operations should be done on the Subject directly. Also, this subject should be built using the Subject.Builder.
For that you can wrap your messages with the subject,
case class ActorMessage(subject:Subject, value: Any)
object MessageSender {
def ? (actorRef: ActorRef, message: Any)(implicit subject: Subject): Future[Any] = {
val resultFuture = if (!message.isInstanceOf[ActorMessage]) {
val actorMessage = ActorMessage(subject, message)
actorRef ask actorMessage
} else actorRef ask message
for (result <- resultFuture) yield {
if (result.isInstanceOf[ActorMessage]) {
val actorMessageResp = result.asInstanceOf[ActorMessage]
actorMessageResp.value
} else result
}
}
}
and unwrap them on the actor when it receives the message. Or initialize the subject if it was the request entry actor.
abstract class ShiroActor extends Actor {
implicit var shiroSubject: Subject = (new Subject.Builder).buildSubject
override def aroundReceive(receive: Actor.Receive, msg: Any): Unit = {
if (msg.isInstanceOf[ActorMessage]) {
val actorMessage = msg.asInstanceOf[ActorMessage]
shiroSubject = actorMessage.subject
receive.applyOrElse(actorMessage.value, unhandled)
} else {
shiroSubject = (new Subject.Builder).buildSubject
receive.applyOrElse(msg, unhandled)
}
}
}
Now to use it the implemented actors will have to extend the ShiroActor and to exchange a message between actors you will have to use the MessageSender, instead of the ActorRef ask or tell methods.
To login the subject, checkpermissions, roles and so on you can now use the subject available on the actor. Like this,
shiroSubject.login(new AuthenticationToken(principal, credentials))
This assumes the login is done on the request entry actor and subject is just shared to be checked for permissions on the subsequent actors. But I'm sure it can be easilly adapted to update the shiroSubject on the actors bidirectionally.
Hope this can be an helpful resource as it seems to be nearly impossible to find an example of the integration between this two frameworks.