次のxmlを介してServletContextでインスタンス化するSpring Bean(dao)オブジェクトがあります。
<bean id="userDao" class="com.company.dao.impl.UserDaoImpl">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
この Bean は webapp-servlet.xml ファイル内で宣言され、ServletContext 内のアプリによって使用されます。
SpringSecurity も使用しています。これが別のコンテキスト (SecurityContext) で実行されることは、私の理解です。
私のアプリケーションには、カスタム認証プロバイダーをインスタンス化する webapp-security.xml があります。アプリで使用されているdaoを使用して、セキュリティコンテキストでユーザールックアップも行いたいのですが、実行すると:
<bean id="userAuthenticationProvider" class="com.company.security.UserAuthenticationProvider">
<property name="userDao" ref="userDao" />
</bean>
そのような Bean "userDao" がないというエラーが表示されます。Bean は、他のコンテキストで宣言された Bean では正常に自動配線されますが、セキュリティ コンテキスト内では自動配線されません。Spring Docsによると、web.xmlには両方の別々のコンテキストが必要だと思います
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<listener>
<listener-class>
org.springframework.security.web.session.HttpSessionEventPublisher
</listener-class>
</listener>
私の質問は、SecurityContext 内の ServletContext にある DAO にアクセスするにはどうすればよいですか? 私のdaoのスコープ修飾子はありますか、それとも実行時に認証プロバイダー内で何らかの方法でServletContextを取得できますか? 参考までに、これは認証プロバイダー内で使用する方法です。
public class UserAuthenticationProvider extends
AbstractUserDetailsAuthenticationProvider {
@Override
protected UserDetails retrieveUser(String userName,
UsernamePasswordAuthenticationToken authenticationToken)
throws AuthenticationException {
// use dao here
これを私に説明してくれてありがとう
アップデート:
調査を続けると、daos を使用している DispatcherServlet は子コンテキストであり、セキュリティ コンテキストはどこか上位にあるようです。したがって、DispatcherServlet の Bean は親コンテキストからは見えません。答えは、どうにかして Bean 宣言を親アプリケーションのコンテキストに移動することだと思いますが、これを行う方法がわかりません。これが私のweb.xmlです
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/spring-*.xml
</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.security.web.session.HttpSessionEventPublisher
</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy
</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>myapp</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
<init-param>
<param-name>listings</param-name>
<param-value>true</param-value>
</init-param>
</servlet>
...
すべての dao 作成を spring-dao.xml に移動し、spring-security.xml で次のことを行っています。
<import resource="spring-dao.xml" />
ただし、daos は DispatcherServlet コンテキストには表示されたままですが、SecurityContext には表示されません。
答えた:
わかりました。ここにいくつかの役立つリンクがあります:
http://static.springsource.org/spring-security/site/faq.html#faq-method-security-in-web-context
したがって、問題は、dao が ApplicationContext (上位のスプリング コンテナー) に存在することを確認する必要があることでした。これが確実に行われるようにするために、web.xml を次のように変更しました。
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/spring-dao.xml WEB-INF/spring-security.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<listener>
<listener-class>
org.springframework.security.web.session.HttpSessionEventPublisher
</listener-class>
</listener>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy
</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>webapp</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
<init-param>
<param-name>listings</param-name>
<param-value>true</param-value>
</init-param>
</servlet>
これにより、起動する最初のコンテキストローダーがdao構成を読み取り(そしてdao Beanを作成し)、次にセキュリティ構成を読み取ることが確実になると思いました。dao Bean はこの方法で作成されているため、security.xml 内の以前の "import resource="spring-dao.xml"" ステートメントは不要になるため削除しました。
その context-param 構成の直後に、ContextLoaderListener を作成しました。これは DispatcherServlet よりも高レベルの Spring コンテナーであるため、これを最初に配置すると、最初に構成ファイルを読み取り、Bean を作成することになると考えました。次に、子コンテキストはそれらにアクセスできます。DispatcherServlet は contextConfigLocation を読み取ることすらできないため、これは機能しない可能性がありますが、読み取ったとしても、この時点で Bean は既に宣言されているので、残念なことに、親コンテキストがそれらを所有していると考えました。
さて、別のトリックとして... DAO を取得するために、@Autowiredを実行できませんでした。XML経由で手動で挿入する必要がありました:
<bean id="userAuthenticationProvider" class="com.company.app.security.UserAuthenticationProvider">
<property name="userDao" ref="userDao" />
</bean>
もちろん、私は自分の dao でゲッター メソッドとセッター メソッドを作成しました。ここで @Autowired が機能しない理由がわかりません。設計によるものだと思います。おそらく、これは SecurityContext に固有のものであり (他のコンテキストからはプルされません)、@Autowired は通常、現在のコンテキストからのみプルするか、または XML を介して Bean を作成したため、xml を介してプロパティも設定する必要があります。注釈経由ではありませんか?(注釈は有効になっており、最上位のアプリケーション名前空間で機能しています)。
とにかく..まだわからないことがたくさんありますが、重要な点は、ようやく機能するようになったことです。