Spring 使用批注的Shiro授权权限检查不起作用
平台:Shiro 1.1.0,Spring 3.0.5 我正在尝试使用Shiro注释保护MVC控制器方法。然而,注释有问题。常规电话正常工作。Shiro调试中也没有任何特定内容 我的shiro配置:Spring 使用批注的Shiro授权权限检查不起作用,spring,shiro,Spring,Shiro,平台:Shiro 1.1.0,Spring 3.0.5 我正在尝试使用Shiro注释保护MVC控制器方法。然而,注释有问题。常规电话正常工作。Shiro调试中也没有任何特定内容 我的shiro配置: <!-- Security Manager --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property
<!-- 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>
但以下方法不起作用:
@RequiresPermissions("hc:patientView")
@RequestMapping(value="/form")
public String viewPatientForm(Model model, @RequestParam(value="patientId", required=false) Long patientId){
我错过什么了吗?请帮忙。我猜Shiro是在Spring2.0推出时建造的。Shiro的注释(RequiresRoles等)适用于spring容器管理的bean(服务层),但不适用于@Controller注释。这是因为@Controller正在被spring框架扫描组件。我使用AOP解决了这个问题。下面是对我有效的解决方案。 要使用以下解决方案,您必须包括以下四个罐子:
aspectjrt-1.6.11.jar
aspectjweaver-1.6.12.jar
cglib-2.2.2.jar
asm-3.3.1.jar
如果您使用的是maven,那么下面的配置将非常有用
<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>
为注释创建以下方面(RequiresRoles)。您可以使用相同的原则为requirePermission创建切入点
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()));
}
}
在您提到的spring-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.example.controller"/>
注意:上述两种配置应放在同一个spring-webApplicationContext.xml中。否则就不行了。此外,如果您在配置中使用了注释配置,请删除它。上下文:组件扫描已经扫描了所有注释。你完全正确。看到你的评论后,我开始思考。然后我发现Shiro没有实现问题,但是jar依赖项没有正确配置。Shiro的pom.xml也应该依赖于cglib2 因此,以下更改对我起了作用:
aspectjweaver-1.6.12.jar,
cglib-2.2.2.jar,
asm-3.3.1.jar
org.aspectj
aspectjrt
1.6.11
org.aspectj
aspectjweaver
1.6.12
cglib
cglib
2.2.2
最后将aop:aspectj autoproxy放在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"/>
注意:以上两种配置应放在同一个spring-webApplicationContext.xml中。否则就不行了。此外,如果您在配置中使用了context:annotation-config,请删除它。上下文:组件扫描已扫描所有批注
一旦开始测试,将log4j设置为调试或(更好的)跟踪模式。无论何时启动服务器,您都会在日志中找到以下条目:
08:16:24684调试注释awareaspectjautoproxycreator:537-
正在为0公用的bean“userController”创建隐式代理
拦截器和1个特定拦截器
我只使用了示例中的SpringHibernate示例。为了使用@RequiresPermissions等注释,我尝试了shiro手册中的配置,这篇文章中的配置,但编译或运行有效URL失败。所以我只注释了ManageUserController中的所有@requirepermissions,并开始在服务实现中使用它。例如,在getAllUsers方法中的DefaultUserService中,我添加了注释@RequiresPermissions(“用户:管理”)。神奇的是,现在该应用程序可以按预期工作。每当调用url manageUsers时,如果用户具有角色user:manage,则会显示列表页,如果用户没有该权限,则会将该用户抛出/未经授权 我甚至将应用程序配置为使用mysql。为了根据new RBAC()使权限独立于角色,我创建了一个名为Permission as的新类
@Entity
@Table(name = "permissions")
@Cache(usage= CacheConcurrencyStrategy.READ_WRITE)
public class Permission {
@Id
@GeneratedValue
private Long id;
private String element;
private String description;
// setter and getter
现在角色类配置为
@CollectionOfElements
@JoinTable(name="roles_permissions")
@Cache(usage=CacheConcurrencyStrategy.READ_WRITE)
public Set<Permission> getPermissions() {
return permissions;
}
@collectionfements
@JoinTable(name=“角色\权限”)
@缓存(用法=CacheConcurrencyStrategy.READ\u WRITE)
公共设置getPermissions(){
返回权限;
}
最后,我是
for (Role role : user.getRoles()) {
info.addRole(role.getName());
System.out.println("Roles " + role.getName());
// Get permissions first
Set<Permission> permissions = role.getPermissions();
Set<String> permissionsStrings = new HashSet<String>();
for (Permission permission : permissions) {
permissionsStrings.add(permission.getelement());
System.out
.println("Permissions " + permission.getelement());
}
info.addStringPermissions(permissionsStrings);
}
for(角色:user.getRoles()){
info.addRole(role.getName());
System.out.println(“角色”+role.getName());
//首先获取权限
Set permissions=role.getPermissions();
Set permissionsStrings=new HashSet();
用于(权限:权限){
permissionsString.add(permission.getelement());
系统输出
.println(“权限”+权限.getelement());
}
info.addStringPermissions(permissionsString);
}
它创建了五个表作为
|权限|
|角色|
|角色\u权限|
|使用者|
|用户角色|
并且权限独立于任何其他权限。根据新的RBAC,您有两种授权资源的方式(显式和隐式)。如果您避免使用Spring XML,主要使用Java和注释配置,最简单的解决方法是添加
@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
所有
@Controller
类。您需要类路径上的cglib。您需要编写授权属性SourceVisor
以根据
如果您编写了ShiroConfiguration
类,请确保包含以下内容:
@Bean(name = "lifecycleBeanPostProcessor")
public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
@Bean
@ConditionalOnMissingBean
public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(DefaultSecurityManager securityManager) {
// This is to enable Shiro's security annotations
AuthorizationAttributeSourceAdvisor sourceAdvisor = new AuthorizationAttributeSourceAdvisor();
sourceAdvisor.setSecurityManager(securityManager);
return sourceAdvisor;
}
@ConditionalOnMissingBean
@Bean(name = "defaultAdvisorAutoProxyCreator")
@DependsOn("lifecycleBeanPostProcessor")
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator proxyCreator = new DefaultAdvisorAutoProxyCreator();
proxyCreator.setProxyTargetClass(true);
return proxyCreator;
}
我也有同样的问题。我的修正将我的运动衫版本从2.2改为2.22.2,所有@RequiresPermissions都在我的控制器上工作。你好,我也遇到了一个与你在这里发布的问题非常相似的问题:到目前为止还没有具体的问题。我真的很想知道为什么人们对它保持沉默。你有没有找到解决方案?还没有解决方案,因为我不知道问题出在哪里。调试中也没有任何内容。我认为Shiro团队不再发布堆栈溢出。然而,中国也有好的活动。我们可以带些东西去吗?德巴什,我明白你的意思。然而,Se
for (Role role : user.getRoles()) {
info.addRole(role.getName());
System.out.println("Roles " + role.getName());
// Get permissions first
Set<Permission> permissions = role.getPermissions();
Set<String> permissionsStrings = new HashSet<String>();
for (Permission permission : permissions) {
permissionsStrings.add(permission.getelement());
System.out
.println("Permissions " + permission.getelement());
}
info.addStringPermissions(permissionsStrings);
}
@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
@Bean(name = "lifecycleBeanPostProcessor")
public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
@Bean
@ConditionalOnMissingBean
public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(DefaultSecurityManager securityManager) {
// This is to enable Shiro's security annotations
AuthorizationAttributeSourceAdvisor sourceAdvisor = new AuthorizationAttributeSourceAdvisor();
sourceAdvisor.setSecurityManager(securityManager);
return sourceAdvisor;
}
@ConditionalOnMissingBean
@Bean(name = "defaultAdvisorAutoProxyCreator")
@DependsOn("lifecycleBeanPostProcessor")
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator proxyCreator = new DefaultAdvisorAutoProxyCreator();
proxyCreator.setProxyTargetClass(true);
return proxyCreator;
}