11

Spring Security を 1 つの Spring プロジェクトに追加しています。システムのアーキテクチャは REST であり、ユーザーはさまざまなリソースにアクセスできます。

この情報の所有者である管理者とユーザーに、個人情報へのアクセスを許可したいと思います。私は簡単に始めました: 次のようなユーザープロファイルのフィルタリング:

私のサービスレイヤーでは、メソッドアノテーションを使用し、メソッドパラメーターを含めたいと思っていました..

@PreAuthorize("hasRole('ROLE_ADMIN') or principal.userId == #id")
public Usuario getUser(int id) throws DAOException {
    ...
}

しかし、これはまったく機能していません。この URL が要求された場合 ( Web レイヤー) 、すべてのユーザーはすべてのプロファイル (管理者とすべてのユーザーも) を表示できます。

@RequestMapping(value="/user/{uid}", method=RequestMethod.GET)
    public ModelAndView getUser(@PathVariable int uid) throws DAOException {
        userDAO = new UsuarioJPADAO();
        userService.setUsuarioDAO(userDAO);

    return new ModelAndView("user", "user", userService.getUser(uid));
}

これが私のsecurity.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
       xmlns:beans="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans 
       http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
       http://www.springframework.org/schema/security
       http://www.springframework.org/schema/security/spring-security-3.1.xsd">

<!-- Security Annotations -->
    <global-method-security 
        pre-post-annotations="enabled"/>

<http auto-config="true" use-expressions="true">
    <intercept-url pattern="/css/**" access="permitAll" />
    <intercept-url pattern="/images/**" access="permitAll" />
    <intercept-url pattern="/js/**" access="permitAll" />
    <intercept-url pattern="/favicon.ico" access="permitAll" />
    <intercept-url pattern="/login" access="permitAll" />

    <intercept-url pattern="/users" access="hasRole('ROLE_ADMIN')" />
    <intercept-url pattern="/users/page/*" access="hasRole('ROLE_ADMIN')" />
    <intercept-url pattern="/customers" access="hasRole('ROLE_ADMIN')" />
    <intercept-url pattern="/employees" access="hasRole('ROLE_ADMIN')" />

    <intercept-url pattern="/search/*" access="hasRole('ROLE_ADMIN')" />

    <intercept-url pattern="/*" access="hasAnyRole('ROLE_ADMIN, ROLE_EMPLOYEE, ROLE_PARTNER, ROLE_USER')" />
    <intercept-url pattern="/*/*" access="hasAnyRole('ROLE_USER, ROLE_ADMIN')" />
    <intercept-url pattern="/*/*/*" access="hasAnyRole('ROLE_USER, ROLE_ADMIN')" />
    <intercept-url pattern="/*/*/*/*" access="hasAnyRole('ROLE_USER, ROLE_ADMIN')" />
    <intercept-url pattern="/*/*/*/*/*" access="hasAnyRole('ROLE_USER, ROLE_ADMIN')" />
    <intercept-url pattern="/*/*/*/*/*/*" access="hasAnyRole('ROLE_USER, ROLE_ADMIN')" />
    <intercept-url pattern="/*/*/*/*/*/*/*" access="hasAnyRole('ROLE_USER, ROLE_ADMIN')" />
    <form-login login-page="/login" login-processing-url="/doLogin" 
                authentication-failure-url="/login?error"
                username-parameter="username" password-parameter="password"
                default-target-url="/default" />

    <logout invalidate-session="true" logout-success-url="/login?logout" logout-url="/logout"/>
</http>
<authentication-manager>
    <authentication-provider user-service-ref="UsuarioService">
    </authentication-provider>
</authentication-manager>    

私はSpring Security 3.1の本をチェックしましたが、どうやら私の構成は本が示唆するとおりです。他のスタック オーバーフローの投稿 (ここここ) を読みましたが、運がありませんでした。

更新:追加application-context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"       
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:security="http://www.springframework.org/schema/security"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:jee="http://www.springframework.org/schema/jee"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
       http://www.springframework.org/schema/aop 
       http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
       http://www.springframework.org/schema/tx 
       http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
       http://www.springframework.org/schema/mvc
       http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.1.xsd
       http://www.springframework.org/schema/security
       http://www.springframework.org/schema/security/spring-security-3.1.xsd">

    <context:annotation-config />

<context:component-scan base-package="com.pe.fs" />

<mvc:annotation-driven />

<mvc:resources mapping="/**" location="/" />   

<mvc:interceptors>
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
    <property name="paramName" value="lang" />
</bean>
</mvc:interceptors>

<!-- DataSource -->
<bean id="jpaDataSource" class="oracle.jdbc.pool.OracleDataSource"
    destroy-method="close" 
    p:driverType="oracle.jdbc.OracleDriver" 
    p:user="**********"
    p:password="**********"
    p:uRL="jdbc:oracle:thin:@localhost:1521:XE"
/>

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceXmlLocation" value="classpath*:META-INF/persistence.xml"></property>
    <property name="persistenceUnitName" value="freesunPU" />
    <property name="dataSource" ref="jpaDataSource" />
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
            <property name="showSql" value="false" />
        </bean>
    </property>
    <property name="loadTimeWeaver">
        <bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>
    </property>
</bean>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
    p:entityManagerFactory-ref="entityManagerFactory" />

<tx:annotation-driven mode="aspectj"/>

<context:load-time-weaver aspectj-weaving="autodetect" />

更新:spring-security-aspects POM に追加しましたが、変更はありません。回答で提案されているその他の変更はテストされていますが、そのような注釈@PreAuthorizeはまだ機能していません。これはコンテキスト間の問題でしょうか? 理由は、aspectJ の使用でしょうか。

私は何を間違っていますか?

4

3 に答える 3

9

最後に解決策を見つけました。SOで私はいくつかの有用な答えを見つけました。ここここを参照してください。

サービスのコンテキストであるに移動global-method-securityしました。application-context.xml

<security:global-method-security 
    mode="aspectj"
    secured-annotations="enabled"
    jsr250-annotations="disabled"
    pre-post-annotations="enabled"/>

mode="aspectj"Javadocが言うところ:

...デフォルトの Spring AOP の代わりに AspectJ を使用するように指定するために使用できます。設定する場合、保護されたクラスは spring-security-aspects モジュールの AnnotationSecurityAspect で織り込む必要があります。

もちろん、私は POM に追加しましたspring-security-aspects:

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-aspects</artifactId>
    <version>3.1.3.RELEASE</version>
</dependency>
于 2013-03-13T11:37:52.523 に答える
0

これを機能させる別の方法は、security.xml に次のコードを追加することです。

<intercept-url pattern="/user/**" access="hasRole('ROLE_ADMIN')" />

これにより、管理者のみがパターン /user/ で始まるリソースにアクセスできるようになります。

于 2015-05-18T11:50:05.280 に答える
0

新しいインターフェースを追加:

public interface UserService extends UserDetailsService {
    Usuario getUser(int id) throws DAOException
}

ユーザー サービスに実装し、再試行してください。Spring は、JDK プロキシを使用して要求された承認チェックを追加できます。

別のオプションとして、Javassist や AspectJ などのより重いライブラリを使用するように Spring を構成できます。この場合、インターフェースは必要ありません。

編集。global-method-securityがユーザー サービス Bean と同じ Spring コンテキストで宣言されていることを確認してください。

于 2013-03-12T12:36:12.573 に答える