Spring Security Context is null when accessing Tomcat application without trailing slash - spring

I have a Spring based web application deployed on Tomcat 7. What I do to run it is copy the application.war archive into the webapps directory and start the server, so my application root is available under https://localhost:8443/application/.
Then I wanted to add Spring security (3.2.4) to it. My intention is to secure the entire application, not only parts of it. The Spring security configuration I have:
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.2.xsd">
<http auto-config="true">
<intercept-url pattern="/**" access="ROLE_USER" />
</http>
<authentication-manager>
<authentication-provider>
<user-service>
<user name="admin" password="admin" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</authentication-manager>
</beans:beans>
And in web.xml:
<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>
It's a basic configuration which can be found in the official docs and many tutorials. Everything works fine, when I'm not authenticated Spring redirects me to it's default login page. I can then log in and can access the application until the session expires or I navigate to the logout url.
The problem begins to show up when I access the application root without the trailing slash: https://localhost:8443/application.
Spring fails to find the security context:
2016-07-19 17:48:36,650 DEBUG: security.web.FilterChainProxy - / at position 1 of 12 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2016-07-19 17:48:36,650 DEBUG: web.context.HttpSessionSecurityContextRepository - HttpSession returned null object for SPRING_SECURITY_CONTEXT
2016-07-19 17:48:36,650 DEBUG: web.context.HttpSessionSecurityContextRepository - No SecurityContext was available from the HttpSession: org.apache.catalina.session.StandardSessionFacade#53b1e801. A new one will be created.
I then get redirected to the login page, but after I log in I get redirected to the original URL without the slash, Spring fails again and I see the login form again.
Does anybody know why is this happening? My configuration is minimal, uses out of the box defaults. The use case is also very simple and it feels weird that this is not working as expected. I feel I'm missing something fundamental, either with Spring or Tomcat.
Any help will be appreciated, thanks.

The problem was with the JSESSIONID cookie path -- Tomcat set it automatically to /application/, so any requests accessing the application root without a trailing slash were treated as new users which required authentication. Setting the cookie path to /application solved the problem for me.

just try this
<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>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/</url-pattern>
</filter-mapping>

<http auto-config="true">
<!-- my be this can`t match -->
<intercept-url pattern="/**" access="ROLE_USER" />
<!-- add this for try -->
<intercept-url pattern="/" access="ROLE_USER" />
</http>

Related

Allow Specific URL patterns to bypass Spring Security Login

I have a web application protected by spring security. However, there is one particular URL pattern that I do not want to apply any security to. I've tried a few different approaches, but none of them seem to be working. Whenever I attempt to go to that specific URL, I am forwarded to the spring_security_login page.
A piece of the web.xml:
<!-- NOT SECURE -->
<servlet>
<servlet-name>dontSecureServlet</servlet-name>
<servlet-class>org.com.gov.lol.DontSecure</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dontSecureServlet</servlet-name>
<url-pattern>/dontSecure</url-pattern>
</servlet-mapping>
<!-- SECURE -->
<servlet>
<servlet-name>secureServlet</servlet-name>
<servlet-class>org.com.gov.lol.Secure</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>secureServlet</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
<!-- SECURITY FILTER -->
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
A piece of the security-context.xml:
<!-- This did not work -->
<http pattern="/dontSecure" security="none" />
<http entry-point-ref="entryPoint" use-expressions="true">
<custom-filter ref="customFilter" position="PRE_AUTH_FILTER" />
<!-- I've also tried adding the following here (with no luck) -->
<intercept-url pattern="/dontSecure" filters="none" />
<intercept-url pattern="/secureMe" requires-channel="https" />
<intercept-url pattern="/secureUs" requires-channel="https" />
</http>
<!-- I have even tried adding a separate <http> block just for /dontSecure -->
<http>
<intercept-url pattern="/dontSecure" security="none" />
</http>
Again, with any combination of the above configuration, the url /dontSecure is still forwarded to the spring login page.
Any ideas as to what could be causing this?
Cheers.
UPDATE
From the server logs, it seems that the /dontSecure url is loading the dontSecureServlet. However, an error seems to be generated and I am being forwareded the 404 error page (which is configured as /404.htm, which must be what brings me back to the login page).
I've included some extra snippits from the web.xml that I didn't think were relevant at first.
Try to change your intercept-url in your configuration with this one:
<intercept-url pattern="/dontSecure/**" access="permitAll" />
not in a separate <http> tag
The problem might be caused by the fact that your custom filter is getting applied to all the paths. You have to find a way to register your custom filter only for certain paths (I could show you how to do this in Spring Boot, but you probably aren't using it).

Authentication failed in Spring due to no mapping found for HTTP request with URI?

I have a web project using Spring Security. The user begin from login.jsp, pass through the authentication, and direct to hello.jsp. Take note that all JSP pages are locate in WEB-INF. During the process, I notice the URL begin with localhost:8081/Project1/pages/login.jsp, right after submit the page, the URL have change to http://localhost:8081/Project1/pages/j_spring_security_check;jsessionid=792884C463EAC3C6CBC155EA75F4C6E4.
And then the page showing me HTTP status 404 after the authentication instead of showing hello.jsp. In the console output, I see this message:
WARNING: No mapping found for HTTP request with URI [/SpringSecurity3/pages/j_spring_security_check] in DispatcherServlet with name 'SpringSecurity3'
I am not sure what is miss configure in Spring configuration? The configuration code is as follow:
<http auto-config="true">
<intercept-url pattern="/welcome*" access="ROLE_ADMIN"/>
<intercept-url pattern="/pages/hello.jsp" access="ROLE_ADMIN"/>
<form-login login-page="/login" default-target-url="/welcome" authentication-failure-url="/loginfailed" />
<logout logout-success-url="/pages/login.jsp"/>
</http>
and my web.xml is as follow:
<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>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/WEB-INF/pages/*</url-pattern>
</filter-mapping>
Remove
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/WEB-INF/pages/*</url-pattern>
</filter-mapping>
Also you can refer to this tutorials:
http://www.mkyong.com/spring-security/spring-security-hello-world-example http://www.mkyong.com/spring-security/spring-security-form-login-example/
Double-check if the security configuration is included in the main application context (as opposed to the servlet application context). The xml configuration file declaring the security filter chain (<http ...>) should be listed in the contextConfigLocation context parameter in web.xml (or be imported by one of the xml config files listed there).
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
...
[spring-security config file should be included here]
...
</param-value>
</context-param>

Websphere 8 / Spring security (LDAP) / not redirecting to login.xhtml

I try to get LDAP and Spring on a Websphere 8 running. It somehow does, but it does not forward any requests to my login.xhtml.
Means, that it looks like you are logged in, but you cannot click anything on that page and you are not forwarded to the login page.
If I call it directly (/faces/login.xhtml), log in and then click around, everything works as expected, so it is just that my application does not forward me to the required loginpage.
Hope you guys have a good idea.
My web.xml looks like that:
<!-- removed non-relevant parts-->
<welcome-file-list>
<welcome-file>faces/index.xhtml</welcome-file>
</welcome-file-list>
<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>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
My applicationSecurity.xml looks like that:
<security:http pattern="/faces/ressources/**" security="none"/>
<security:http auto-config="true" pattern="/**">
<!-- Login pages -->
<security:form-login login-page="/faces/login.xhtml" default-target-url="/faces/index.xhtml"
login-processing-url="/faces/j_spring_security_check"
authentication-failure-url="/faces/login.xhtml" />
<security:logout logout-success-url="/faces/login.xhtml" />
<!-- Security zones -->
<!-- secured -->
<security:intercept-url pattern="/faces/index.xhtml" access="ROLE_APP_QPA_ADMIN,ROLE_APP_QPA_USER" />
<security:intercept-url pattern="/faces/datadictionary/**" access="ROLE_APP_QPA_ADMIN,ROLE_APP_QPA_USER" />
<security:intercept-url pattern="/faces/templates/**" access="ROLE_APP_QPA_ADMIN,ROLE_APP_QPA_USER" />
</security:http>
I have no clue what else I could do.
I use Spring as shared Library, if that matters.

JSF and Spring securtiy Integration [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Spring Security Authentication is not working as expected in my configuration
I tried integrating JSF and spring security i spent almost a day but there is no result
Developed an application using JSF,Spring MVC and Primfaces. I am almost done with my requirements, at the end i planned to integrate the spring security but i could n't and i did enough search on net. I feel it may be bug in related framework.
If anyone of you came across the same please post the solution. I post my approach over here
Step 1:
Created Login.jsp(to have customized login page)
Step 2:
Added below code in my web.xml
<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>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
Step 3:
Created Springsecurity.xml
<sec:global-method-security
secured-annotations="enabled" />
<sec:http auto-config="true" use-expressions="true"
once-per-request="false">
<sec:intercept-url pattern="pages/secured/**"
access="ROLE_USER" />
<sec:form-login login-page="/login.jsp"
default-target-url="/pages/secured/products.xhtml"
authentication-failure-url="/login.html?login_error=1" />
<sec:logout logout-url="/logout" logout-success-url="/login.jsp" />
</sec:http>
<sec:authentication-manager alias="authenticationManager">
<sec:authentication-provider>
<sec:user-service>
<sec:user name="vijay" authorities="ROLE_USER" password="vijay"/>
</sec:user-service>
</sec:authentication-provider>
</sec:authentication-manager>
Executed the application and got the login.jsp as first page since i defind in web.xml. On login authentication its forwarding to the Products.xhtml but i could even access the rest of pages which all are comes under the secured folder with out logging in.
Please suggest a better approach or other alternatives.
For your access attribute have your tried. Your first slash was missing in the pattern.
<sec:intercept-url pattern="/pages/secured/**"
access="hasRole('ROLE_USER')" />

Spring Security: SecurityContextHolder.getContext().getAuthentication() returns null on Wicket Page

I am using Spring MVC(for REST), Spring Security 3 and Apache Wicket (UI) on Google App Engine. Everything is working fine except I am having trouble in getting the Authentication on the Wicket Page through the SecurityContextHolder after login.
I have google'd this issue, but none seems to be working for me. I suspect this is something wrong with my web xml. Can anyone please help. Thanks.
I am using the tutorials for Spring Security on Google App Engine from http://blog.springsource.org/2010/08/02/spring-security-in-google-app-engine/
Here is my web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<display-name>MTP Portal</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/mtp-web-servlet.xml, /WEB-INF/mtp-web-security-context.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>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>mtp-web</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>mtp-web</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
<filter>
<filter-name>WicketApp</filter-name>
<filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
<init-param>
<param-name>applicationFactoryClassName</param-name>
<param-value>org.apache.wicket.spring.SpringWebApplicationFactory</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>WicketApp</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Here is my spring security config:
<?xml version="1.0" encoding="UTF-8"?>
<b:beans xmlns="http://www.springframework.org/schema/security"
xmlns:b="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<global-method-security pre-post-annotations="enabled"/>
<http pattern="/images/**" security="none"/>
<http pattern="/css/**" security="none"/>
<http pattern="/js/**" security="none"/>
<http pattern="/api/**" security="none"/>
<http pattern="/favicon.ico" security="none"/>
<http pattern="/disabled" security="none"/>
<http use-expressions="true" entry-point-ref="gaeEntryPoint" auto-config="true">
<intercept-url pattern="/" access="permitAll"/>
<intercept-url pattern="/api/**" access="permitAll"/>
<intercept-url pattern="/admin/logout" access="permitAll"/>
<intercept-url pattern="/register" access="hasRole('NEW_USER')"/>
<intercept-url pattern="/admin/**" access="hasRole('ADMIN')"/>
<custom-filter position="PRE_AUTH_FILTER" ref="gaeFilter"/>
</http>
<b:bean id="gaeEntryPoint"
class="com.peerbuccoss.apps.mtp.web.authentication.impl.GoogleAccountsAuthenticationEntryPoint"/>
<b:bean id="gaeFilter" class="com.peerbuccoss.apps.mtp.web.authentication.filter.GaeAuthenticationFilter">
<b:property name="authenticationManager" ref="authenticationManager"/>
<b:property name="failureHandler">
<b:bean class="org.springframework.security.web.authentication.ExceptionMappingAuthenticationFailureHandler">
<b:property name="exceptionMappings">
<b:map>
<b:entry key="org.springframework.security.authentication.DisabledException"
value="/disabled"/>
</b:map>
</b:property>
</b:bean>
</b:property>
</b:bean>
<authentication-manager alias="authenticationManager">
<authentication-provider ref="gaeAuthenticationProvider"/>
</authentication-manager>
<b:bean id="gaeAuthenticationProvider"
class="com.peerbuccoss.apps.mtp.web.authentication.provider.GoogleAccountsAuthenticationProvider"/>
I'm not sure what URL is failing to obtain the SecurityContext (perhaps you can provide an example URL), but the SecurityContext will not be populated for any URL that is mapped to security="none". This is because security="none" instructs Spring Security to ignore this URL entirely. If you need to access the SecurityContext on a URL that is allowed for every user, then you need to use permitAll.
PS: If this does not help you might provide an example URL that you are having trouble with getting the Authentication. You might also provide details on what you mean by "having trouble in getting the Authentication on the Wicket Page" (i.e. is it null, throwing an Exception, etc).

Resources