4

I know it may not be a best design for a question like this but just for specific requirement.

Current application needs ServletContext, HttpServletRequest, HttpServletResponse in to service layer for a customized authentication provider.

Obviously without any specific configuration or inheritance following code:

@Component("myAuthenticaionProvider")
public class MyAuthenticaionProvider implements AuthenticationUserDetailsService {
    @Autowired private ServletContext context;
    @Autowired private HttpServletRequest request;
    @Autowired private HttpServletResponse response;
        .......
}

must throw exception:

nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException:
No matching bean of type [javax.servlet.http.HttpServletResponse] found for dependency:

Possible solutions I can think of:

  1. Intercept HttpServletRequest with a filter, but that requires an URL pattern, otherwise will intercept all URLs which I think might be a performance concern?

  2. Create a request scope bean in spring-security.xml or application-context.xml and then inject into current authentication provider class, to make it capable to get the HttpServletRequest. But I think there is something wrong here, as how to initiate the request scope bean?

Then what could be the best practice?

Dreamer
  • 7,333
  • 24
  • 99
  • 179
  • 1
    what exactly are you trying to achieve? – dhamibirendra Jan 09 '14 at 16:35
  • 2
    This is bad idea, but in an appropriate environment it will work. `((ServletWebRequest) RequestContextHolder.getRequestAttributes()).getResponse();`. By _appropriate environment_, I mean one where the `RequestAttributes` returned by `getRequestAttributes()` is of type `ServletWebRequest`. – Sotirios Delimanolis Jan 09 '14 at 16:40
  • The chances to get a good solution would be much higher if you described what you want to achieve. To me it looks like you need a filter (especially because of the response object), but you don't want that. So I'm really wondering who calls this service and when (and why). – a better oliver Jan 09 '14 at 18:43

2 Answers2

3

Beyond being a "bad idea" a request object only lives as long as the request. You can't inject it into a singleton due to lifecycle differences. You can pass it in via a method parameter.

The closest solution matching your request is to create a ThreadLocal variable inside a catch all filter and set it there and inject that filter or a delegate to the thread local into your service. I highly suggest you avoid that.

Andrew White
  • 52,720
  • 19
  • 113
  • 137
  • Interestingly I found `HttpServletRequest` is able to autowired to a service layer. But not sure how it is initiated. Thanks for the advice. – Dreamer Jan 09 '14 at 16:48
  • It is possible to inject a request scoped bean into a singleton, see for example https://stackoverflow.com/a/51398651/5226711 – Lars Gendner Oct 12 '22 at 10:56
0

Have you tried to implement HttpRequestHandler interface in your authentication provider along with AuthenticationUserDetailsService?

Vaelyr
  • 2,841
  • 2
  • 21
  • 34