使用注释进行 Shiro 授权权限检查不起作用
平台:Shiro 1.1.0、Spring 3.0.5
我正在尝试使用 Shiro 注释来保护 MVC 控制器方法。但是注释有问题。常规通话正常。 Shiro debug 中也没有什么具体内容。
我的 shiro 配置:
<!-- 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>
我可以使以下内容正常工作:
@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");
}
}
但以下内容不起作用:
@RequiresPermissions("hc:patientView")
@RequestMapping(value="/form")
public String viewPatientForm(Model model, @RequestParam(value="patientId", required=false) Long patientId){
我错过了什么吗?请帮忙。
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
你说得完全正确。看到你的评论后,我开始思考。然后我发现这不是 Shiro 的实现问题,而是 jar 依赖项没有正确配置。 Shiro 的 pom.xml 也应该依赖于 cglib2。
所以以下更改对我有用:
<块引用>
aspectjrt-1.6.11.jar,
spectjweaver-1.6.12.jar,
cglib-2.2.2.jar,
asm-3.3.1.jar,
If you are using maven then :
最后将aop:aspectj-autoproxy放在webApplicationContext.xml中
注意:以上两个配置应该一起放在同一个spring-webApplicationContext.xml中。否则就行不通。此外,如果您在配置中使用了 context:annotation-config,请删除它。 context:component-scan 已经扫描了所有注释。
开始测试后,将 log4j 设置为调试或(更好的)跟踪模式。每当您启动服务器时,您都会在日志中找到以下条目:
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 :
If you are using maven then :
And finally placing the aop:aspectj-autoproxy in the webApplicationContext.xml
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 :
Guess Shiro 是在 Spring 2.0 就位时构建的。 Shiro 的注释(RequiresRoles 等)适用于 spring 容器托管 bean(服务层),但它不适用于 @Controller 注释。这是因为 @Controller 正在被 spring 框架扫描。我使用AOP来解决这个问题。以下是对我有用的解决方案。
为了使下面的解决方案发挥作用,您必须包含以下四个 jar:
如果您使用的是 Maven,那么下面的配置将会很有帮助。
下面是一个控制器类
为注释创建以下方面 (RequiresRoles)。您可以使用相同的原则为 RequiresPermission 创建切入点。
在您提到的 spring-webApplicationContext.xml 中
注意:以上两个配置要放在同一个 spring-webApplicationContext.xml 中。否则就行不通。此外,删除 context:annotation-config(如果您在配置中使用过它)。 context:component-scan 已经扫描了所有注释。
Guess Shiro was built when Spring 2.0 was in place. Shiro’s annotations (RequiresRoles etc…) works well for the spring container managed beans (service layer), but it does not work with @Controller annotation. This is due to the fact that @Controller is being component scanned by spring framework. I used AOP to resolve the issue. Below is the solution which worked for me.
For the below solution to work you have to include the below four jars:
If you are using maven then below configuration would be helpful.
Below is a controller class
Create the below Aspect for the annotation (RequiresRoles). You can use the same principle to create pointcuts for RequiresPermission.
In your spring-webApplicationContext.xml wherever you have mentioned
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.
如果您避免使用 Spring XML 并主要使用 Java 和注释配置,那么解决此问题的最简单方法是添加
到所有
@Controller
类中。您需要在类路径上使用 cglib。If you're avoiding Spring XML and using primarily Java and annotation configuration, the easiest way to fix this is to add
to all your
@Controller
classes. You need cglib on the classpath.我只使用了示例中的 spring-hibernate 示例。为了使用 @RequiresPermissions 等注释,我尝试了 shiro 手册中的配置、这篇文章中的配置,但我要么无法成功编译或运行有效的 url。所以我只评论了 ManageUserController 中的所有 @RequiresPermissions 并开始在服务实现中使用它。例如,在 getAllUsers 方法中的 DefaultUserService 中,我添加了注释 @RequiresPermissions("user:manage")。神奇的是,现在应用程序按预期工作了。每当调用 url manageUsers 时,如果用户具有 user:manage 角色,它将显示列表页面;如果用户没有该权限,则将用户抛出 /unauthorized。
我什至将应用程序配置为使用 mysql。根据新的 RBAC 使权限独立于角色(http:// /www.stormpath.com/blog/new-rbac-resource-based-access-control)我创建了一个名为 Permission 的新类,
现在 Role 类配置为
最后 SampleRealm 因为
它创建了五个表
|权限|
|角色 |
|角色权限 |
|用户 |
|用户角色 |
并且权限独立于任何其他权限。根据新的 RBAC,您有两种方式(显式和隐式)授权资源。
I have only used spring-hibernate example from sample. To use annotations like @RequiresPermissions and others I tried configuration from shiro manual, configuration from this post, but I was either unsuccessful to compile or run the valid urls. So I only commented all the @RequiresPermissions from ManageUserController and started to use it in service implementation. E.g In DefaultUserService in getAllUsers method I added the annotation @RequiresPermissions("user:manage"). Magically now the application works as expected. Whenever the url manageUsers is called it displays the list page if the user has role user:manage and throws the user to /unauthorized if the user don't have that permission.
I have even configured the application to use mysql instead. To make the permissions independent of roles according to new RBAC(http://www.stormpath.com/blog/new-rbac-resource-based-access-control) I have created a new class called Permission as
Now Role class is configured as
And finally SampleRealm as
It creates five tables as
| permissions |
| roles |
| roles_permissions |
| users |
| users_roles |
And permissions is independent of any other. According to new RBAC you have both ways (explicit and implicit) way of authorising resources.
您需要编写
AuthorizationAttributeSourceAdvisor
来根据 Shiro 文档如果您编写了
ShiroConfiguration
类,请确保包含以下内容:Github 上的示例
ShiroConfiguration
You need to write the
AuthorizationAttributeSourceAdvisor
to enable Shiro's annotations bean as per the Shiro documentationIf you have written
ShiroConfiguration
class, make sure you include this:Example
ShiroConfiguration
on Github我也有同样的问题。我的解决方法是将我的球衣版本从 2.2 更改为 2.22.2,并且所有 @RequiresPermissions 都适用于我的控制器。
I had the same problem. My fix was changing my jersey version from 2.2 to 2.22.2 and all @RequiresPermissions worked on my controllers.