Following this question, it was very helpful when I came across the same problem. The main goal is to provide additional information about the proposed Les Hazlewood implementation. Another good alternative source of information is also this topic https://groups.google.com/forum/#!topic/spray-user/wpiG4SREpl0
Shiro currently uses streaming, which means linking subject information to the current stream. This is a problem for Akka, as it uses dispatcher and worker thread pools.
As threads are reused, the object flows from one request to another, which leads to the fact that an unauthorized request is processed both authenticated and vice versa.
As suggested by Les, a possible solution to the problem is to abandon the thread binding and save the object in Akka messages. For this, this means that the static methods provided by Shiro SecurityUtils cannot be used. Operations must be performed directly on the Subject. In addition, this object must be built using the Subject.Builder object.
To do this, you can wrap your messages with a 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 deploy them to the actor when he receives the message. Or initialize the topic, if it was a participant in the application.
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, in order to use it, the performers will need to extend the ShiroActor action and exchange messages between the participants, you will have to use MessageSender, instead of requesting or telling the methods of ActorRef.
To enter the topic, checks, roles, etc., you can now use the item available to the actor. Like this,
shiroSubject.login(new AuthenticationToken(principal, credentials))
This assumes that the login is made on the subject of the request input, and the subject is simply used to check permissions for subsequent participants. But I'm sure this can be easily adapted to update siroSubject for participants in two ways.
Hope this can be a useful resource, as it seems almost impossible to find an example of integration between the two structures.