1

Trying to make some experiments with Spring MVC and Spring Security:

@Controller
@RequestMapping("/auth")
public class AuthController {   
    @Autowired
    // @Qualifier("userDetailsService") - tried adding this
    private MyUserDetailsService userDetailsService;
    ...
}

// @Scope("singleton") - tried adding this
@Service("userDetailsService")
public class MyUserDetailsService implements UserDetailsService {
    ...
}

Complete context.xml that I have:

<?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:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:security="http://www.springframework.org/schema/security"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
        http://www.springframework.org/schema/security
        http://www.springframework.org/schema/security/spring-security-3.0.xsd">

    <!-- ORIGINAL springmvc-servlet.xml -->
    <mvc:annotation-driven />
    <mvc:resources mapping="/static/**" location="/static/" />

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
        <property name="prefix" value="/WEB-INF/jsp/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>

    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
    <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />

    <context:annotation-config />
    <context:component-scan base-package="com.xxxxxxxxx" />
    <!-- end ORIGINAL springmvc-servlet.xml -->

    <!-- FROM springmvc-security.xml -->
    <security:global-method-security secured-annotations="enabled">
    </security:global-method-security>

    <security:http auto-config="true" access-denied-page="/auth/denied">
        <security:intercept-url pattern="/admin/*" access="ROLE_ADMIN"/>        
        <security:intercept-url pattern="/user/*" access="ROLE_USER"/>
        <security:intercept-url pattern="/auth/login" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
        <security:intercept-url pattern="/auth/register" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
        <security:intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
        <security:form-login login-page="/auth/login" authentication-failure-url="/auth/login?login_error=true" default-target-url="/user"/>
        <security:logout logout-url="/auth/logout" logout-success-url="/" invalidate-session="true"/>
        <security:openid-login authentication-failure-url="/login?login_error=t" user-service-ref="openIdUserDetailsService" />
    </security:http>

    <security:authentication-manager>
        <security:authentication-provider user-service-ref="userDetailsService" />
    </security:authentication-manager>
    <!-- end FROM springmvc-security.xml -->    
</beans>

For some reason, there are 2 instances of MyUserDetailsService created. The first one is used by Spring Security and the second one is injected to AuthController. What's the right approach in case I want to have a single instance of MyUserDetailsService?

Andrey Agibalov
  • 7,624
  • 8
  • 66
  • 111
  • Interesting, I always wondered how to make spring security run in a single application context with other beans - I suppose they run in separate ones. – Boris Treukhov May 29 '12 at 06:20
  • Btw in my current configuration UserDetailsService is declared only in SecurityContext not in the ApplicationContext (autoscan is disabled). – Boris Treukhov May 29 '12 at 06:33

2 Answers2

1

You haven't shown enough configuration to be certain, but I'd bet money that you're confused about how Spring ApplicationContexts should be managed in a Spring MVC app. My answer to another question about the same problem is almost certainly what you need to read:

Declaring Spring Bean in Parent Context vs Child Context

You've most likely declared your service bean (either explicitly or with a component-scan) in both the root and child contexts of your app. Being a service bean, it should live only in the root context. You may also benefit from reading this answer:

Spring XML file configuration hierarchy help/explanation

Community
  • 1
  • 1
Ryan Stewart
  • 126,015
  • 21
  • 180
  • 199
  • I've updated the question with my complete context configuration. Could you please check it? – Andrey Agibalov May 29 '12 at 06:43
  • That's the context file that belongs to your DispatcherServlet. You should have one of those in your web.xml named "springmvc". Also show how your root context is initialized. That's probably also done in your web.xml, by a ContextLoaderListener, and with a contextConfigLocation parameter. – Ryan Stewart May 29 '12 at 14:25
  • That took me about an hour, but now I get it. Thank you for your answer :-) – Andrey Agibalov May 29 '12 at 17:28
0

this config works for me :

<security:authentication-manager>
<security:authentication-provider user-service-ref="userService">

and

<bean id="userService" class="com.mydomain.service.UserDetailsServiceImpl" />

A tutorial here.

NimChimpsky
  • 46,453
  • 60
  • 198
  • 311
  • That's not going to keep two of them from being created. It's just going to change the name of one or both of the created beans. – Ryan Stewart May 29 '12 at 06:23
  • @NimChimpsky: renamed to `theUserDetailsService`, it's still the same. – Andrey Agibalov May 29 '12 at 06:28
  • @loki2302 oh you changed it in app cotnext too ? Are you implementing userdetailsservice elsewhere then ? – NimChimpsky May 29 '12 at 06:31
  • @NimChimpsky: all 3 - `@Qualifier`, `@Service` and context. All 3 are now theUserDetailsService and I still have 2 instances. Any other ideas? – Andrey Agibalov May 29 '12 at 06:38
  • @loki2302 see update, actually don;t you just have to define the bean userDetailsSerivce in app context, you have just got the security manager ref defined, nto the bean itself – NimChimpsky May 29 '12 at 06:41