6

プラットフォーム:Shiro 1.1.0、Spring 3.0.5

Shiroアノテーションを使用してMVCコントローラーメソッドを保護しようとしています。ただし、注釈に問題があります。通常の通話は問題なく機能しています。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){    

私は何かが足りないのですか?助けてください。

4

6 に答える 6

9

あなたは絶対に正しかった。あなたのコメントを見て、私はそれについて考え始めました。すると、Shiro の実装上の問題ではなく、jar の依存関係が適切に構成されていないことがわかりました。Shiro の pom.xml も cglib2 に依存している必要があります。

したがって、以下の変更は私にとってはうまくいきました:

  1. これら 4 つの jar ファイルをすべて含めます。

    spectjrt-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>

最後に 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"/>

注 : 上記の 2 つの構成は、同じ spring-webApplicationContext.xml にまとめて配置する必要があります。それ以外の場合は機能しません。さらに、設定で使用している場合は context:annotation-config を削除します。context:component-scan はすでにすべての注釈をスキャンしています。

テストを開始したら、log4j をデバッグ モードまたは (より良い) トレース モードに設定します。サーバーを起動するたびに、ログのどこかに次のエントリが見つかります。

08:16:24,684 DEBUG AnnotationAwareAspectJAutoProxyCreator:537 - 0 の共通インターセプターと 1 つの特定のインターセプターを使用して、Bean 'userController' の暗黙のプロキシを作成しています

于 2011-11-29T03:11:38.120 に答える
3

Spring 2.0が導入されたときにShiroが構築されたと思います。Shiro のアノテーション (RequiresRoles など) は、Spring コンテナーのマネージド Bean (サービス層) に対してはうまく機能しますが、@Controller アノテーションでは機能しません。これは、@Controller が Spring フレームワークによってコンポーネント スキャンされているためです。AOP を使用して問題を解決しました。以下は私のために働いた解決策です。以下のソリューションを機能させるには、以下の 4 つの jar を含める必要があります。

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> 

以下はコントローラクラスです

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

アノテーション用に以下のアスペクトを作成します (RequiresRoles)。同じ原則を使用して、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()));
    }
}

あなたが言及した場所ならどこでもあなたの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"/>

: 上記の 2 つの構成は、同じspring-webApplicationContext.xml にまとめて配置する必要があります。それ以外の場合は機能しません。さらに、設定で使用している場合はcontext:annotation-configを削除します。 context:component-scanはすでにすべての注釈をスキャンしています。

于 2011-11-25T05:08:10.447 に答える
1

サンプルの春休止状態の例のみを使用しました。@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 という名前の新しいクラスを次のように作成しました。

@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

現在、Role クラスは次のように構成されています。

 @CollectionOfElements
    @JoinTable(name="roles_permissions")
    @Cache(usage=CacheConcurrencyStrategy.READ_WRITE)
    public Set<Permission> getPermissions() {
        return permissions;
    }

そして最後に SampleRealm として

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

| として 5 つのテーブルを作成します。パーミッション | | | 役割 | | | 役割_権限 | | | ユーザー | | | ユーザーの役割 |

また、パーミッションは他から独立しています。新しい RBAC によると、リソースを承認する方法は両方 (明示的および暗黙的) あります。

于 2012-06-21T17:26:13.233 に答える
0

Shiro のドキュメントAuthorizationAttributeSourceAdvisorに従って、Shiro の注釈 Bean を有効にするには、 を記述する必要があります。

クラスを書いた場合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;
}

ShiroConfigurationGithub の例

于 2017-01-21T13:32:15.293 に答える