You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@shiro.apache.org by Philippe Deslauriers <pd...@me.com> on 2013/05/21 17:06:24 UTC

Shiro annotations - Spring 3.x / Jersey 1.17

Hi guys,

I just spent a full day trying to get Shiro authorization annotations to work, but I'm having some trouble and I would appreciate some help :)

I'm writing a REST web application using spring and jersey. I'm able to verify permissions using the standard programmatic approach, but the annotation-based authorization is not working for me, nothing happens. I found a lot of thread but none of the solutions I found worked for me.

My issue is very similar to the one in this question: http://stackoverflow.com/questions/7743749/shiro-authorization-permission-check-using-annotation-not-working. I added the dependencies and the config in shiro context. Here is my configuration file for shiro:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
    
    <context:component-scan base-package="com.company.mc" />  
    <aop:aspectj-autoproxy proxy-target-class="true" />

<!-- Enable Shiro Annotations for Spring-configured beans.  Only run after -->
<!-- the lifecycleBeanProcessor has run: --> 
<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>

<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean (http://web.ShiroFilterFactoryBean)">
    <property name="securityManager" ref="securityManager"/>
    <property name="loginUrl" value="/login.jsp"/>
    <property name="successUrl" value="/home.htm"/>

    <property name="filterChainDefinitions">
        <value>
            # some example chain definitions:
/css/** = anon
/font/** = anon
/img/** = anon
/js/** = anon
/libs/** = anon
/locales/** = anon
/login = authFilter
/login.jsp = authFilter 
/login.htm = authFilter
/logout = logoutFilter
/ = authFilter
/** = authFilter

        </value>
    </property>
</bean>
 
<bean id="authFilter" class="com.company.mc.security.filter.CustomFormAuthenticationFilter">
</bean>

<bean id="logoutFilter" class="org.apache.shiro.web.filter.authc.LogoutFilter (http://web.filter.authc.LogoutFilter)">
<property name="redirectUrl" value="/"/>
</bean>

<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager (http://web.mgt.DefaultWebSecurityManager)">
    <property name="authenticator" ref="customizedModularRealmAuthenticator" />  
    
    <property name="realms">
     <list>
     <!-- <ref bean="easyRealm"/>-->
     <ref bean="myRealm"/>
     <ref bean="adRealm"/>
     </list>
    </property>
    <!-- By default the servlet container sessions will be used.  Uncomment this line
         to use shiro's native sessions (see the JavaDoc for more):-->
    <property name="sessionMode" value="native"/> 
</bean>

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

<!-- This realm authenticates against the specified active directory by attempting a bind
     with the username & password token posted from the login form -->
<bean id="adRealm" class="com.company.mc.security.realm.NonAuthorizingActiveDirectoryRealm">
</bean>

<!-- This dummy realm authenticates by simply checking that the provided password in the login
     form matches the provided username. This is practical (in a dev setting) when you want to login
     with an account for which you don't have the password or when LDAP is not accessible. MUST
     BE REMOVED FOR PRODUCTION. -->
<bean id="easyRealm" class="com.company.mc.security.realm.EasyAccessRealm">
</bean> 
<bean id="myRealm" class="com.company.mc.security.realm.myRealm">
</bean> 

<bean id="customizedModularRealmAuthenticator" class="com.company.mc.security.authenticator.CustomizedModularRealmAuthenticator">
<property name="authenticationStrategy" ref="firstSuccessfulStrategy"/>
</bean>

<bean id="firstSuccessfulStrategy" class="org.apache.shiro.authc.pam.FirstSuccessfulStrategy"/>

</beans>

Here are my dependencies

<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>

<!-- Support for Spring-Shiro authorization annotations -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.6.11</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.12</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</dependency>

<!-- Jersey -->
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-server</artifactId>
<version>${jersey.version}</version>
</dependency>

<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-servlet</artifactId>
<version>${jersey.version}</version>
</dependency>


<!-- Shiro -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.2.1</version>
</dependency>

<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.2.1</version>
</dependency>

<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.2.1</version>
</dependency>

<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-aspectj</artifactId>
<version>1.2.1</version>
</dependency>


And the piece of code that is not being processed:

@RequiresPermissions({"tenants:create", "accessOtherTenants"})
@POST
@Consumes("Application/json")
public Response addTenant(Tenant newTenant) {

// My Code
}

(trust me on that: my subject does not have any of those two permissions)

I would appreciate some hints on where to direct my search or anything really that can help me going forward in "my quest". I'll make sure to post the solution once I figure it out.

Thanks for your help and have a nice day
Philippe D.

Re: Shiro annotations - Spring 3.x / Jersey 1.17

Posted by Philippe Deslauriers <pd...@me.com>.
Hi, 

Ok, I found the solution to my problem. It's not directly related to Shiro, the issue was coming from a bad integration between jersey and spring. My jersey servlet was defined with 

<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>

when it should have been 

<servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class>

Here is a link to a guide that shows how to integrate jersey with spring: http://www.mkyong.com/webservices/jax-rs/jersey-spring-integration-example/

For Shiro annotations, the information in this thread helped me to get everything working: http://stackoverflow.com/questions/7743749/shiro-authorization-permission-check-using-annotation-not-working 

Philippe D.


On Wednesday 22 May 2013 at 09:18, Philippe Deslauriers wrote:

> Him 
> 
> I tried to delete the line as well as to mimic as much as possible the sample context xml, but still no result. For now I will "upgrade" the sample to make it closer to my setup until it breaks, it should help me to find my mistake. I'll get back to you next week with the result. 
> 
> Thanks for your help,
> Philippe D.
> 
> 
> On Tuesday 21 May 2013 at 18:00, Harald Wellmann wrote:
> 
> > Have you tried running the Spring-Hibernate sample from the Shiro source 
> > repository? The Hibernate part is probably not relevant to your use 
> > case, but the Spring configuration might help you.
> > 
> > This sample does NOT use AspectJ, and that may be the reason why your 
> > setup doesn't work.
> > 
> > In other words, Spring and Shiro do support AspectJ but don't require 
> > it, so unless your own application relies on AspectJ, I'd say you're 
> > better off without it.
> > 
> > Can you try deleting
> > 
> > <aop:aspectj-autoproxy proxy-target-class="true" />
> > 
> > from your Spring context?
> > 
> > The DefaultAdvisorAutoProxyCreator bean should be sufficient to create 
> > proxies and advice for your Shiro annotations.
> > 
> > Best regards,
> > Harald
> > 
> > 
> > 
> 
> 


Re: Shiro annotations - Spring 3.x / Jersey 1.17

Posted by Philippe Deslauriers <pd...@me.com>.
Him 

I tried to delete the line as well as to mimic as much as possible the sample context xml, but still no result. For now I will "upgrade" the sample to make it closer to my setup until it breaks, it should help me to find my mistake. I'll get back to you next week with the result. 

Thanks for your help,
Philippe D.


On Tuesday 21 May 2013 at 18:00, Harald Wellmann wrote:

> Have you tried running the Spring-Hibernate sample from the Shiro source 
> repository? The Hibernate part is probably not relevant to your use 
> case, but the Spring configuration might help you.
> 
> This sample does NOT use AspectJ, and that may be the reason why your 
> setup doesn't work.
> 
> In other words, Spring and Shiro do support AspectJ but don't require 
> it, so unless your own application relies on AspectJ, I'd say you're 
> better off without it.
> 
> Can you try deleting
> 
> <aop:aspectj-autoproxy proxy-target-class="true" />
> 
> from your Spring context?
> 
> The DefaultAdvisorAutoProxyCreator bean should be sufficient to create 
> proxies and advice for your Shiro annotations.
> 
> Best regards,
> Harald
> 
> 



Re: Shiro annotations - Spring 3.x / Jersey 1.17

Posted by Harald Wellmann <hw...@gmail.com>.
Have you tried running the Spring-Hibernate sample from the Shiro source 
repository? The Hibernate part is probably not relevant to your use 
case, but the Spring configuration might help you.

This sample does NOT use AspectJ, and that may be the reason why your 
setup doesn't work.

In other words, Spring and Shiro do support AspectJ but don't require 
it, so unless your own application relies on AspectJ, I'd say you're 
better off without it.

Can you try deleting

   <aop:aspectj-autoproxy proxy-target-class="true" />

from your Spring context?

The DefaultAdvisorAutoProxyCreator bean should be sufficient to create 
proxies and advice for your Shiro annotations.

Best regards,
Harald



Re: Shiro annotations - Spring 3.x / Jersey 1.17

Posted by Les Hazlewood <lh...@apache.org>.
I don't have time to look into this today (maybe tomorrow if I'm lucky -
I'm at a conference this week), but I think the
DefaultAdvisorAutoProxyCreator approach for Spring AOP is no longer
recommended by the Spring team (or at least it conflicts with more recent
AOP mechanisms).  I *think* we need to find another way to support custom
annotations in later Spring environments, but I'm not 100% sure.

--
Les Hazlewood | @lhazlewood
CTO, Stormpath | http://stormpath.com | @goStormpath | 888.391.5282


On Tue, May 21, 2013 at 8:06 AM, Philippe Deslauriers
<pd...@me.com>wrote:

> Hi guys,
>
> I just spent a full day trying to get Shiro authorization annotations to
> work, but I'm having some trouble and I would appreciate some help :)
>
> I'm writing a REST web application using spring and jersey. I'm able to
> verify permissions using the standard programmatic approach, but the
> annotation-based authorization is not working for me, nothing happens. I
> found a lot of thread but none of the solutions I found worked for me.
>
> My issue is very similar to the one in this question:
> http://stackoverflow.com/questions/7743749/shiro-authorization-permission-check-using-annotation-not-working.
> I added the dependencies and the config in shiro context. Here is my
> configuration file for shiro:
>
> <?xml version="1.0" encoding="UTF-8"?>
> <beans xmlns="http://www.springframework.org/schema/beans"
>     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>     xmlns:context="http://www.springframework.org/schema/context"
>     xmlns:aop="http://www.springframework.org/schema/aop"
>     xsi:schemaLocation="
>     http://www.springframework.org/schema/beans
>     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
>     http://www.springframework.org/schema/context
>     http://www.springframework.org/schema/context/spring-context-3.0.xsd
>     http://www.springframework.org/schema/aop
>     http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
>
>     <context:component-scan base-package="com.company.mc" />
>     <aop:aspectj-autoproxy proxy-target-class="true" />
>  <!-- Enable Shiro Annotations for Spring-configured beans.  Only run
> after -->
> <!-- the lifecycleBeanProcessor has run: -->
> <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>
>
> <bean id="shiroFilter" class="org.apache.shiro.spring.
> web.ShiroFilterFactoryBean">
>     <property name="securityManager" ref="securityManager"/>
>     <property name="loginUrl" value="/login.jsp"/>
>     <property name="successUrl" value="/home.htm"/>
>
>     <property name="filterChainDefinitions">
>         <value>
>             # some example chain definitions:
> /css/** = anon
> /font/** = anon
> /img/** = anon
> /js/** = anon
> /libs/** = anon
> /locales/** = anon
> /login = authFilter
> /login.jsp = authFilter
> /login.htm = authFilter
> /logout = logoutFilter
> / = authFilter
> /** = authFilter
>
>         </value>
>     </property>
> </bean>
>
> <bean id="authFilter"
> class="com.company.mc.security.filter.CustomFormAuthenticationFilter">
> </bean>
>
> <bean id="logoutFilter" class="org.apache.shiro.
> web.filter.authc.LogoutFilter">
> <property name="redirectUrl" value="/"/>
> </bean>
>  <bean id="securityManager" class="org.apache.shiro.
> web.mgt.DefaultWebSecurityManager">
>     <property name="authenticator"
> ref="customizedModularRealmAuthenticator" />
>
>     <property name="realms">
>      <list>
>      <!-- <ref bean="easyRealm"/>-->
>      <ref bean="myRealm"/>
>      <ref bean="adRealm"/>
>      </list>
>     </property>
>     <!-- By default the servlet container sessions will be used.
>  Uncomment this line
>          to use shiro's native sessions (see the JavaDoc for more):-->
>     <property name="sessionMode" value="native"/>
> </bean>
>  <bean id="lifecycleBeanPostProcessor"
> class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
>
> <!-- This realm authenticates against the specified active directory by
> attempting a bind
>      with the username & password token posted from the login form -->
> <bean id="adRealm"
> class="com.company.mc.security.realm.NonAuthorizingActiveDirectoryRealm">
> </bean>
>  <!-- This dummy realm authenticates by simply checking that the provided
> password in the login
>      form matches the provided username. This is practical (in a dev
> setting) when you want to login
>      with an account for which you don't have the password or when LDAP is
> not accessible. MUST
>      BE REMOVED FOR PRODUCTION. -->
> <bean id="easyRealm" class="com.company.mc.security.realm.EasyAccessRealm">
> </bean>
> <bean id="myRealm" class="com.company.mc.security.realm.myRealm">
> </bean>
>  <bean id="customizedModularRealmAuthenticator"
> class="com.company.mc.security.authenticator.CustomizedModularRealmAuthenticator">
> <property name="authenticationStrategy" ref="firstSuccessfulStrategy"/>
> </bean>
>  <bean id="firstSuccessfulStrategy"
> class="org.apache.shiro.authc.pam.FirstSuccessfulStrategy"/>
>
> </beans>
>
> Here are my dependencies
>
> <!-- Spring -->
> <dependency>
> <groupId>org.springframework</groupId>
> <artifactId>spring-context</artifactId>
> <version>${spring.version}</version>
> </dependency>
>
> <dependency>
> <groupId>org.springframework</groupId>
> <artifactId>spring-context-support</artifactId>
> <version>${spring.version}</version>
> </dependency>
>
> <dependency>
> <groupId>org.springframework</groupId>
> <artifactId>spring-web</artifactId>
> <version>${spring.version}</version>
> </dependency>
>
> <dependency>
> <groupId>org.springframework</groupId>
> <artifactId>spring-webmvc</artifactId>
> <version>${spring.version}</version>
> </dependency>
>
> <dependency>
> <groupId>org.springframework</groupId>
> <artifactId>spring-aop</artifactId>
> <version>${spring.version}</version>
> </dependency>
>
> <dependency>
> <groupId>org.springframework</groupId>
> <artifactId>spring-aspects</artifactId>
> <version>${spring.version}</version>
> </dependency>
>
> <!-- Support for Spring-Shiro authorization annotations -->
> <dependency>
> <groupId>org.aspectj</groupId>
> <artifactId>aspectjrt</artifactId>
> <version>1.6.11</version>
> </dependency>
> <dependency>
> <groupId>org.aspectj</groupId>
> <artifactId>aspectjweaver</artifactId>
> <version>1.6.12</version>
> </dependency>
> <dependency>
> <groupId>cglib</groupId>
> <artifactId>cglib</artifactId>
> <version>2.2.2</version>
> </dependency>
>
> <!-- Jersey -->
> <dependency>
> <groupId>com.sun.jersey</groupId>
> <artifactId>jersey-server</artifactId>
> <version>${jersey.version}</version>
> </dependency>
>
> <dependency>
> <groupId>com.sun.jersey</groupId>
> <artifactId>jersey-servlet</artifactId>
> <version>${jersey.version}</version>
> </dependency>
>
>
> <!-- Shiro -->
> <dependency>
> <groupId>org.apache.shiro</groupId>
> <artifactId>shiro-core</artifactId>
> <version>1.2.1</version>
> </dependency>
>
> <dependency>
> <groupId>org.apache.shiro</groupId>
> <artifactId>shiro-web</artifactId>
> <version>1.2.1</version>
> </dependency>
>
> <dependency>
> <groupId>org.apache.shiro</groupId>
> <artifactId>shiro-spring</artifactId>
> <version>1.2.1</version>
> </dependency>
>
> <dependency>
> <groupId>org.apache.shiro</groupId>
> <artifactId>shiro-aspectj</artifactId>
> <version>1.2.1</version>
> </dependency>
>
> And the piece of code that is not being processed:
>
> @RequiresPermissions({"tenants:create", "accessOtherTenants"})
> @POST
> @Consumes("Application/json")
> public Response addTenant(Tenant newTenant) {
> // My Code
> }
>
> (trust me on that: my subject does not have any of those two permissions)
>
> I would appreciate some hints on where to direct my search or anything
> really that can help me going forward in "my quest". I'll make sure to post
> the solution once I figure it out.
>
> Thanks for your help and have a nice day
> Philippe D.
>