Apache Shiro Annotation AOP和RMI

时间:2017-01-25 10:41:59

标签: java rmi spring-aop interceptor shiro

我正在尝试将Apache Shiro用于连接多个客户端的RMI服务器。

我想要的架构是在RMI注册表中注册的一些单例服务。它们中的每一个都有一个登录方法,用于返回客户端的新导出服务。 所以我可以在每个客户端的服务中保留对客户端Object的最终引用。

使用Shiro,我将在客户服务上使用注释@RequireRoles等。

我的问题是如何拦截所有注释@RequireRoles的Aspect,只是在服务中使用引用设置Subject?

我可以编写自己的注释@AllowRoles(String [])和我自己的Aspect来获取带有“this”的jointPoint(服务)并获取对客户端的引用并检查客户端是否具有这些角色。 但我宁愿使用一个好的框架,而不是从一开始就对所有内容进行编码......

同样适用于@Transactional但我不使用SpringAOP。

How to organize RMI Client-Server architecture

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

编辑: 我可能找到了解决方案,但不确定它是好的解决方案: 没有优先权,如果subject为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();

    }
}

我没有从线程上下文中取消绑定主题,因为对服务方法的任何调用都将确保服务的用户绑定到正在执行的线程。

我可以使用而不是bind,使用:subject.execute(() - > {return proceed()});在“周围”的建议中自动清除threadConext但是它真的有必要吗?

感谢您的帮助

1 个答案:

答案 0 :(得分:0)