私のシナリオは次のとおりです。Spring セキュリティを追加したばかりの Spring Web アプリケーション (webmvc を使用) があります。十分な権限を持つユーザーがユーザーを追加できる CRUD ユーザー マネージャー ページがあります。サーバーでは、これは com.myapp.UserController クラスによって処理されます。また、com.myapp.UserDetailsServiceImpl と呼ばれる org.springframework.security.core.userdetails.UserDetailsService の独自の実装も取得しました。UserController と私の UserDetailsService impl はどちらも、java.util.List でユーザーを追跡する com.myapp.UserService を使用します。
私が見つけたのは、Web インターフェイスを介して新しいユーザーを作成し、ログアウトしてから、その新しいユーザーで再度ログインしようとしたときに、ユーザーが見つからないということでした。よく調べてみると、com.myapp.UserService の 2 つの異なるインスタンスがあるためです。UserController によって使用されるものには新しいユーザーがありますが、UserDetailsServiceImpl によって使用されるものにはありません。
この webapp を起動すると、2 つの異なる Spring コンテナーが実行されるという事実まで原因を突き止めました。1 つは webmvc (myapp-servlet.xml) 用で、もう 1 つはセキュリティ (myapp-security.xml) 用です。それぞれに UserService の独自のインスタンスがあります。これは、Spring webmvc をセキュリティで構成するための非常に一般的なシナリオであることを理解しています。
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<servlet>
<servlet-name>myapp</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>myapp</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/myapp-servlet.xml, /WEB-INF/myapp-security.xml</param-value>
</context-param>
<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>
</web-app>
私の myapp-servlet.xml では、@Service で注釈が付けられているため、UserService を取得するコンポーネント スキャンが進行中です。
<context:component-scan base-package="com.myapp" />
ただし、UserService は myapp-security.xml によっても取得されます。これは、認証マネージャー構成の一部として参照されているためです。
<authentication-manager>
<authentication-provider user-service-ref="userDetailsService" />
</authentication-manager>
完全を期すために、com.myapp.UserDetailsServiceImpl の関連部分を次に示します。
@Service("userDetailsService")
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
@Qualifier("testUserService")
private UserService userService;
...
}
そして私のUserController:
@Controller
@RequestMapping("/admin/users")
public class UserController {
@Autowired
@Qualifier("testUserService")
private UserService userService;
...
}
私の質問はこれです: webmvc とセキュリティの両方を 1 つのスプリング コンテナーに結合して、UserService のインスタンスが重複して作成されないようにする方法はありますか?