Spring 使用批注的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

平台: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 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

因此,以下更改对我起了作用:

  • 包括所有这四个jar文件

    aspectjrt-1.6.11.jar,
    aspectjweaver-1.6.12.jar,
    cglib-2.2.2.jar,
    asm-3.3.1.jar
  • 如果您使用的是maven,那么:

    
    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;
    }