Guess Shiro was built when Spring 2.0 was in place. Shiros annotations (RequiresRoles, etc.) work well for Spring container-managed beans (service level), but it does not work with @Controller annotation. This is because @Controller is a component scanned by the Spring framework. I used AOP to solve the problem. Below is a solution that worked for me. For the solution below to work, you need to include the following four banks:
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 the below configuration will be useful.
<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>
Below is the controller class
import org.apache.shiro.authz.annotation.RequiresRoles; @Controller public class PatientController { @RequiresRoles("admin,warden") @RequestMapping(value="/form") public String viewPatientForm(Model model, @RequestParam(value="patientId", required=false) Long patientId){ return "somePatientFormJsp"; } }
Create the following aspect of the annotation (RequiresRoles). You can use the same principle to create a pointcut for RequiresPermission .
import java.util.Arrays; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authz.annotation.RequiresRoles; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; @Aspect @Component public class WebAuthorizationAspect { @Before("@target(org.springframework.stereotype.Controller) && @annotation(requiresRoles)") public void assertAuthorized(JoinPoint jp, RequiresRoles requiresRoles) { SecurityUtils.getSubject().checkRoles(Arrays.asList(requiresRoles.value())); } }
In spring -webApplicationContext.xml, wherever you mention
<aop:aspectj-autoproxy proxy-target-class="true"/> <context:component-scan base-package="com.example.controller"/>
Note The two above configurations should be placed together in the same spring -webApplicationContext.xml. Otherwise it will not work. Moreover, delete the context: annotation-config if you used it in your configuration. context: the scan component already scans all annotations.