Announcement Announcement Module
Collapse
No announcement yet.
NTLM and SecurityContextHolderAwareRequestFilter isn't working Page Title Module
Move Remove Collapse
This topic is closed
X
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • NTLM and SecurityContextHolderAwareRequestFilter isn't working

    Hi all,

    I have a Problem using NTLM Login and the SecurityContextHolderAwareRequestFilter. When I have the RequestFilter in my Filter Chain the NTLM Login is not working. Why is the RequestFilter loosing the NTLM Message for the NtlmProcessingFilter?

    When I use my configuration without the RequestFilter everything is working. But then I have no request.isUserinRoll and so the org.springframework.web.servlet.handler.UserRoleAu thorizationInterceptor is not working.

    Who knows this problem? Is there a solution to use the request.isuserinroll feature? Because my Webapp is using this feature at different places.

    Thank You very much!
    Sebastian

  • #2
    NTLM and SecurityContextHolderAwareRequestFilter isn't working

    I just ran into this a couple days ago.

    The culprit is the SavedRequestAwareWrapper that the SecurityContextHolderAwareRequestFilter wraps around the the request before the NtlmProcessingFilter accesses it.

    Here's what happens:

    Initial Request
    • The browser makes the first request for a restricted resource. Note that this first request has no Authentication header.
    • The SecurityContextHolderAwareRequestFilter wraps the request with a SavedRequestAwareWrapper .
    • The SavedRequestAwareWrapper constructor saves the request as a session attribute for later use.
    • The server returns a 401 message indicating that a NTLM authentication attempt should be made.
    Second Request (Type 2)
    • The browser then makes a second request with an appropriate Authentication header.
    • The SecurityContextHolderAwareRequestFilter again wraps the request with a SavedRequestAwareWrapper .
    • The NtlmProcessingFilter attempts to get the the Authorization header from the request...

    This is where the trouble starts. At this point, the NtlmProcessingFilter isn't accessing the raw request, but instead accesses the SavedRequestAwareWrapper. When getHeader() is called on the SavedRequestAwareWrapper, it checks to see if there is a saved request in the session, and if so it returns the header value of that request instead of the current. Remember the initial request without the Authorization header is currently saved, and since there is no Authorization header, the getHeader() method returns null - which is exactly not what you want.

    There are a number of ways to get around this. One is to not use the SecurityContextHolderAwareRequestFilter at all, but that doesn't sound like an option for you. Another is to modify the getHeader() method on the SavedRequestAwareWrapper to make an exception for Authorization header requests. Like this...

    Code:
    if (name.equalsIgnoreCase("Authorization"))
    {
    	return super.getHeader(name);
    }
    else if (savedRequest == null)
    {
    	return super.getHeader(name);
    } 
    else 
    {
    ...
    But if you REALLY want to be non-intrusive, and protect yourself somewhat from upgrades, you can instead make your own modified copy of SavedRequestAwareWrapper, and mess around with the Spring context to make sure that requests are wrapped with your class instead of the standard one.

    To do this, you need to explicitly define your own SecurityContextHolderAwareRequestFilter in your spring context, and inject your custom SavedRequestAwareWrapper.
    Code:
    <bean id="servletApiSupportFilter" class="org.springframework.security.wrapper.SecurityContextHolderAwareRequestFilter">
    	<sec:custom-filter position="SERVLET_API_SUPPORT_FILTER"/>
    	<property name="wrapperClass" value="sebastians.cool.SavedRequestAwareWrapper" />
    </bean>
    If you just did this, you would get an error for attempting to insert 2 filters with the same position number (the default one and the one you are defining here). You can get around this by preventing the default from starting up, so that the one that you are using is used. To do this, you need to set the servlet-api-provision attribute to the http tag to false:

    Code:
    <sec:http servlet-api-provision="false" access-decision-manager-ref="accessDecisionManager" entry-point-ref="ntlmEntryPoint">
    	<sec:intercept-url pattern="/access_denied.jsp" filters="none" />
    	<sec:intercept-url pattern="/**" access="ROLE_USER" />	
    </sec:http>
    I don't know if this is what the original Spring Security folks intended as a work around, but hopefully that gets you pointed in the right direction!

    Steve

    Comment


    • #3
      Hi Steve,

      Thank you very much for your details post.

      I have tested it and with sebastians.cool.SavedRequestAwareWrapper ;-) the NTLM Logon is working.
      But I still have problems in using the isUserInRoll feature. For now the login is working but I still get no isUserinRoll back.
      So it would be a pleasure i you have another hint for me ;-)

      Greatings
      Sebastian

      Comment


      • #4
        Unfortunately, now that you got the NTLM logon to work... you're way ahead of me. I'm still trying to get it to work in my environment (only getting 2 http requests out of 3 for the NTLM Http handshake).

        Once I get there, and if you haven't figured it out already, I'll see what I can find. My advise is to get a debugger set up and step through the code to see what its actually doing. Thats how I found out about the SavedRequestAwareWrapper.

        Comment

        Working...
        X