Platform: Shiro 1.1.0, Spring 3.0.5
I'm trying to secure the MVC Controller methods using Shiro annotation. However something is wrong with annotations. Regular calls are just working OK. There is nothing specific in Shiro debug also.
My shiro configuration:
<!-- Security Manager -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="sessionMode" value="native" />
<property name="realm" ref="jdbcRealm" />
<property name="cacheManager" ref="cacheManager"/>
</bean>
<!-- Caching -->
<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
<property name="cacheManager" ref="ehCacheManager" />
</bean>
<bean id="ehCacheManager"
class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" />
<bean id="sessionDAO"
class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO" />
<bean id="sessionManager"
class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
<property name="sessionDAO" ref="sessionDAO" />
</bean>
<!-- JDBC Realm Settings -->
<bean id="jdbcRealm" class="org.apache.shiro.realm.jdbc.JdbcRealm">
<property name="name" value="jdbcRealm" />
<property name="dataSource" ref="dataSource" />
<property name="authenticationQuery"
value="SELECT password FROM system_user_accounts WHERE username=? and status=1" />
<property name="userRolesQuery"
value="SELECT role_name FROM system_roles r, system_user_accounts u, system_user_roles ur WHERE u.user_id=ur.user_id AND r.role_id=ur.role_id AND u.username=?" />
<property name="permissionsQuery"
value="SELECT permission_name FROM system_roles r, system_permissions p, system_role_permission rp WHERE r.role_id=rp.role_id AND p.permission_id=rp.permission_id AND r.role_name=?" />
<property name="permissionsLookupEnabled" value="true"></property>
</bean>
<!-- Spring Integration -->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
<!-- Enable Shiro Annotations for Spring-configured beans. Only run after
the lifecycleBeanProcessor has run: -->
<bean id="annotationProxy"
class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
depends-on="lifecycleBeanPostProcessor" />
<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>
<!-- Shiro filter -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<property name="loginUrl" value="/login" />
<property name="successUrl" value="/dashboard" />
<property name="unauthorizedUrl" value="/error" />
<property name="filterChainDefinitions">
<value>
<!-- !!! Order matters !!! -->
/authenticate = anon
/login = anon
/logout = anon
/error = anon
/** = authc
</value>
</property>
</bean>
I can get the following working correctly:
@RequestMapping(value="/form")
public String viewPatientForm(Model model, @RequestParam(value="patientId", required=false) Long patientId){
if (!SecurityUtils.getSubject().isPermitted("hc:viewPatient")){
logger.error("Operation not permitted");
throw new AuthorizationException("No Permission");
}
}
But the below doesn't work:
@RequiresPermissions("hc:patientView")
@RequestMapping(value="/form")
public String viewPatientForm(Model model, @RequestParam(value="patientId", required=false) Long patientId){
Am I missing something? Please help.
You were absolutely right. After seeing your comment, I started giving it a thought. Well then I found out that it was NOT an implementation problem with Shiro, but the jar dependecies were not properly configured. Shiro's pom.xml should have dependency for cglib2 too.
So the below changes worked for me :
aspectjrt-1.6.11.jar,
aspectjweaver-1.6.12.jar,
cglib-2.2.2.jar,
asm-3.3.1.jar, If you are using maven then :
<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>
And finally placing the aop:aspectj-autoproxy in the webApplicationContext.xml
<aop:aspectj-autoproxy proxy-target-class="true"/>
<!-- Annotation, so that it's easier to search controllers/components -->
<context:component-scan base-package="com.pepsey.soft.web.controller"/>
Note : The above two configuration should be placed together in the same spring-webApplicationContext.xml. Otherwise it won’t work. Moreover remove context:annotation-config if you have used it in your config. context:component-scan already scans all annotations.
Once you start testing , set your log4j to debug or (better) trace mode. Whenever you are starting your server you will find somewhere the following entry in your logs :
08:16:24,684 DEBUG AnnotationAwareAspectJAutoProxyCreator:537 - Creating implicit proxy for bean 'userController' with 0 common interceptor and 1 specific interceptors