Spring AOP and apache shiro configuration.Annotati

2019-07-16 14:06发布

问题:

I've been struggling with a configuration which requires a knowledge in AOP.

i must admit that AOP is that part i'm trying to get for a while without success. It seems that my shiro annotations are not scanned and thus are ignored.

i've tried using shiro 1.1.0+ maven3+spring 3.0.5.RELEASE, hibernate 3.6.1.Final with ZK 5.0.6. i got my hibernaterealm working , talking to database, i got the authentication working, i successfully(i believe) get the roles and permission loaded.

so to test the authorization side i have somewhere in my code this :

  Subject currentUser = SecurityUtils.getSubject();
   if (!currentUser.isPermitted("businessaccount:list")) {
    throw new AuthorizationException("User not authorized");
  }

and it works fine.
So i know my permissions were loaded.i'll be convenient for me using annotations to i've put it in implementation class, because i didn't plan on using interface at first place with my controller classes which are extending ZK GenericForwardController.

i've seen this bug and i've decided to do a try with one interface with the @RequiresPersmissions on methods.

apparently it's still not working as in it's giving access to unauthorized subject.there is no error in my log.Maybe i'm doing something wrong here are snippet of the codes:

@Component("layouteventhandler")
public class LayoutEventHandlerImpl extends GenericForwardComposer implements     LayoutEventHandler {

Logger logger = Logger.getLogger(LayoutEventHandlerImpl.class);
Menuitem logout;

//...


@Override
public void onClick$pAccounts() {
    try {
        execution.sendRedirect("/accounts/personal/list");
    } catch (Exception ex) {
        logger.info("Error redirecting to personal accounts", ex);
    }
}


@Override
public void onClick$bAccounts() {
  try {
        execution.sendRedirect("/accounts/business/list");
    } catch (Exception ex) {
        logger.info("Error redirecting to business accounts", ex);
    }
}
//.....
} 

its interface it :

public interface LayoutEventHandler {

@RequiresPermissions(value="personalaccount:list")
public void onClick$pAccounts();

@RequiresPermissions(value="businessaccount:list")
public void onClick$bAccounts();
//.....

 }

here is my shiro applicationcontext

<bean id="hibernateRealm" class="com.personal.project.admin.webapp.security.DatabaseRealm" />
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
    <property name="realm" ref="hibernateRealm" />
</bean>

<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />

<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
      depends-on="lifecycleBeanPostProcessor">
 <!--          <property name="proxyTargetClass" value="true" />-->
</bean>
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
    <property name="securityManager" ref="securityManager"/>
</bean>

<!-- Secure Spring remoting:  Ensure any Spring Remoting method invocations can be associated
     with a Subject for security checks. -->
<bean id="secureRemoteInvocationExecutor" class="org.apache.shiro.spring.remoting.SecureRemoteInvocationExecutor">
    <property name="securityManager" ref="securityManager"/>
</bean>
<!-- ... -->

is it in there something that i should do? thanks for reading and helping out

回答1:

I don't know Shiro, but I'm guessing that you've put annotations on your bean classes which implement interfaces and then you're proxying them for security, transactions, and/or something else. When that happens, the object that's returned is a JDK dynamic proxy, which isn't an instance of your bean's concrete class, only of the interface it implements. Therefore any annotation scanning that depends on annotations in the concrete class won't find them.



回答2:

To expand on Ryan Stewart's answer, you need to add

@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)

to the implementing class (not the interface) and move the Shiro annotations to it.



回答3:

I encountered a similar problem when I was running two spring contexts. There is a parent root context that defined Database, Service, Security and non-SpringMVC web beans and a child web context for a Spring MVC REST api which contained the Controllers I want to proxy. The Configuration for each context was class path scanning separate packages.

In this case make sure that the DefaultAdvisorAutoProxyCreator and the AuthorizationAttributeSourceAdvisor beans that are requied are defined in the child web context (i.e. where the Rest Controllers are class path scanned) as defining them in the parent context does not work (the documentation on the DefaultAdvisorAutoProxyCreate is quite clear about this in hindsight!).

Posting this in case someone else encounters the same issue.