0

I am trying to use Apache Shiro for an RMI server with multiple clients connecting.

The architecture I want to have is a few singleton service registered in the register of RMI. Each of them have a login method that return a new exported service by client. So I can in each client's service keep a final reference to a client Object.

With Shiro I will use annotation @RequireRoles etc on services of clients.

My question is how to intercept the Aspect of all annotations @RequireRoles and just set the Subject with the reference in the service?

I could write my own annotations @AllowRoles(String[]) and my own Aspect to get the jointPoint (the service) with the "this" and get the reference to the client and check if the client has these roles. But I would rather use a good framework and not code everything from beginning...

The same apply to @Transactional but I do not use SpringAOP.

How to organize RMI Client-Server architecture

Correct way to use Apache Shiro on distributed system using RMI?

EDIT: I might have found a solution but not sure it is the good one: Without precedence it would not work properly or not work at all if subject is null.

public aspect TestIntercept {

private static final Logger log = LoggerFactory.getLogger(TestIntercept.class);

declare precedence : TestIntercept, org.apache.shiro.aspectj.ShiroAnnotationAuthorizingAspect;

pointcut allow(): execution(@org.apache.shiro.authz.annotation.RequiresPermissions * *(..)) || execution(@org.apache.shiro.authz.annotation.RequiresRoles * *(..));

before(): allow(){
        log.info("Before, in log2");

        Signature sig = thisJoinPointStaticPart.getSignature();
        String line = String.valueOf(thisJoinPointStaticPart.getSourceLocation().getLine());

        String sourceName = thisJoinPointStaticPart.getSourceLocation()
                .getWithinType().getCanonicalName();
        System.out.println("Call2 from " + sourceName + " line " + line + "\n   to "
                + sig.getDeclaringTypeName() + "." + sig.getName() + "\n");


        log.info("Got subject from service: " + ((Service) thisJoinPoint.getThis()).getSubject().isAuthenticated());
        log.info("Got subject from service: " + ((Service) thisJoinPoint.getThis()).getSubject().getPrincipal());

//        Subject subject = ((Service) thisJoinPoint.getThis()).getSubject();
        /*
        Subject subject = new Subject.Builder()
                .authenticated(true)
                .principals(new SimplePrincipalCollection("fake", "realmm"))
                .buildSubject();
        //*/
        //*
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
        subject.login(new UsernamePasswordToken("fake2", "11"));
        //*/
        ThreadState threadState = new SubjectThreadState(subject);
        threadState.bind();

    }
}

I did not unbind the subject from the thread context because any call to a service method will make sure the user of the service is bound to the executing thread.

I could use instead of bind, use: subject.execute(()->{return proceed()}); within an advice "around" to automatically have the threadConext cleared but is it really necessary ?

Thanks for any help

tkruse
  • 10,222
  • 7
  • 53
  • 80
Yoann CAPLAIN
  • 121
  • 3
  • 11

1 Answers1

0

+1 for the around

Please follow up with the post on nabble as well: http://shiro-user.582556.n2.nabble.com/How-to-make-RMI-work-with-Apache-Shiro-td7581467.html

Brian Demers
  • 2,051
  • 1
  • 9
  • 12