Spring basic authentication not working - spring

Trying to set up basic authentication in a web-app using spring. I am patterning what I do off this example: http://howtodoinjava.com/2013/04/16/custom-userdetailsservice-example-for-spring-3-security/. I am using Spring 4.
The behavior is that my HttpRequestHandler runs, never challenging for password. LoginDao never runs.
spring config:
<security:http auto-config="true" use-expressions="true">
<security:intercept-url pattern="/*" access="hasRole('ROLE_USER')" />
<security:http-basic />
</security:http>
<security:authentication-manager>
<security:authentication-provider user-service-ref="loginDao" />
</security:authentication-manager>
<bean id="loginDao" class="weight.dao.LoginDao" />
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="/WEB-INF/wt.properties" />
</bean>

What's missing in this tutorial are the entries you have to add to your web.xml. These will load you security context and add the security filter chain to your whole app (which is the main strut of Spring Security):
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:/your-security-context-file.xml
classpath:/your-other-context-files.xml
...
</param-value>
</context-param>
<filter>
<display-name>Spring Security Filter</display-name>
<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>

Related

Spring Controller method executed twice

I have integrated Spring Security with Spring MVC and seeing strange behaviour. Every method in the Controller is executed twice for the same request. I googled for it quite a bit but didn't help much. The closest I could find is this http://forum.springsource.org/archive/index.php/t-83158.html I tried the suggestions without any success.
Here is my web.xml :
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<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>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/appServlet/security-app-context.xml
/WEB-INF/application-context.xml
</param-value>
</context-param>
Here is relevant part of applicationcontext.xml :
<context:component-scan base-package="com.*" />
<context:spring-configured/>
<mvc:annotation-driven />
<context:property-placeholder location="classpath:/conf/myConfig.properties" />
<mvc:resources mapping="/resources/**" location="/resources/" />
The servlet-context.xml only has mapping for the InternalResourceViewResolver
The security-context.xml is as follows :
<http pattern="/resources/**" security="none"/>
<http auto-config="false" create-session="stateless" entry-point-ref="loginUrlAuthenticationEntryPoint" >
<intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/j_spring_security_check" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/accessdenied" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/login" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/logout" access="ROLE_USER"/>
<custom-filter before="SECURITY_CONTEXT_FILTER" ref="cookieSecurityContextFilter" />
<custom-filter position="LOGOUT_FILTER" ref="logoutfilter" />
<custom-filter position="FORM_LOGIN_FILTER" ref="authenticationFilter" />
<custom-filter after="EXCEPTION_TRANSLATION_FILTER" ref="customExceptionFilter" />
</http>
<beans:bean id="logoutfilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
<beans:constructor-arg value="/"/>
<beans:constructor-arg ref="customLogouthandler"/>
</beans:bean>
And then further mapping for the filters.
Am I doing something wrong in the configuration that could lead to the controller being called twice. I have checked the logs and the beans are instantiated only once. Please help.
Thanks in advance.
Just in case someone stumbles on this post and solution posted here thinking it will fix the duplicate requests, please first check if it is your browser/rest client making the additional call.
I wasted many hours trying to configure app and servlet contexts "after seeing the first suggested solution", until I figured it was the rest client on certain browsers (Chrome) creating an additional request for "GET requests on image resources". Curl showed only one method execution.
However, I do agree that it is a good practice to separate controller specific beans and their required Spring beans into servlet-context and keep all common beans in app-context. This is especially important if you have multiple Spring dispatcher servlet- in your web.xml.
Elaborating the previous answer:
You can either define both component-scan and mvc in the same context file to keep it simple.
app-context.xml:
<context:component-scan base-package="..." />
<mvc:annotation-driven />
...
Or separate them as follows:
app-context.xml:
<context:component-scan base-package="....">
<context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
<context:exclude-filter expression="org.springframework.web.bind.annotation.ControllerAdvice" type="annotation"/>
<context:exclude-filter expression="org.springframework.web.bind.annotation.ExceptionHandler" type="annotation"/>
</context:component-scan>
...
servlet-context.xml:
<context:component-scan base-package="...">
<context:include-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
<context:include-filter expression="org.springframework.web.bind.annotation.ControllerAdvice" type="annotation"/>
<context:include-filter expression="org.springframework.web.bind.annotation.ExceptionHandler" type="annotation"/>
</context:component-scan>
<mvc:annotation-driven />
...
I would try moving <mvc:.. elements to servlet-context.xml, maybe having it on applicationContext.xml causes you to have duplicate dispatcher servlet (although beans are only created once)
Scan all components except #Controller on applicationContext.xml by using <context:exclude-filter... Likewise scan only #Controller on servlet-context.xml using <context:include-filter..

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.

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).

Static HTML files issue in spring 3

I all,
i have a spring application working with role based security. Application is working fine it's just i need to introduce some static HTML pages which will also be hosted in the same war. So if www.myapp.com/abc/work.jsp is my secure page then www.myapp.com/home.htm should show static html page. I have incorporated HTML files but issue is i am getting 404 on www.myapp.com/home.htm and www.myapp.com/abc/work.jsp works fine.
web.xml -
<display-name>guru</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/app-security-config.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>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>/home.htm</welcome-file>
</welcome-file-list>
My app-security-config.xml
<http auto-config="false" disable-url-rewriting="false" access-decision-manager-ref="accessDecisionManager"
entry-point-ref="authenticationProcessingFilterEntryPoint">
<custom-filter position="FORM_LOGIN_FILTER" ref="authenticationProcessingFilter" />
<custom-filter position="LOGOUT_FILTER" ref="customLogoutFilter"/>
<access-denied-handler error-page="/login.jsp?login_error=true"/>
<intercept-url pattern="/login.htm" filters="none" />
<intercept-url pattern="/abc/def/**" access="ROLE_USER"/>
<intercept-url pattern="/**" access="ROLE_ANONYMOUS" />
<anonymous enabled='true'/>
<session-management session-authentication-strategy-ref="sas"/>
<custom-filter position="CONCURRENT_SESSION_FILTER" ref="concurrencyFilter" />
</http>
Hi you should provide a mapping for static contents inside your dispatcher servlet configuration, something like:
<mvc:resources mapping="/resources/**" location="/WEB-INF/" />
In this way, if your static home.htm content is located inside /WEB-INF/ folder you can reach it from the url /resources/home.htm.
This will avoid that spring intercept and redirect to a controller all paths starting with /resources reserving that path to static resources like images, css files, scripts and html static pages

Spring security issue with 404 error?

greetings all, i am using spring security 3.0.2, urlRewrite 3.1.0
, and i have a problem with spring security that i have a rule that all the pages in the app requires authentication except for some pages so my security.xml is:
<http use-expressions="true" >
<intercept-url pattern="/" access="permitAll" />
<intercept-url pattern="/error" filter="none" />
<intercept-url pattern="/**" access="isAuthenticated()" />
.
.
.</http>
in the web.xml i have defined the error page
<error-page>
<error-code>404</error-code>
<location>/p/error</location>
</error-page>
and the issue is that if i am not a logged in user, and typed some url that doesn't exist in the app like app/notFoundUrl the spring security matched this page to the pattern /** which requires authentication, so the user is not redirected to the error page as expected, but redirected to the login page and after it, redirected to the error page
and i want that if the user typed a bad url if he's logged in or not, he's redirected to the error page directly.
i think that the problem is related to the web.xml, here's it:
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<!-- Beans in these files will makeup the configuration of the root web application context -->
<!-- Bootstraps the root web application context before servlet initialization-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Deploys the 'projects' dispatcher servlet whose configuration resides in /WEB-INF/servlet-config.xml-->
<servlet>
<servlet-name>p</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/servlet-config.xml
</param-value>
</init-param>
</servlet>
<!-- Maps all /p URLs to the 'p' servlet -->
<servlet-mapping>
<servlet-name>p</servlet-name>
<url-pattern>/p/*</url-pattern>
</servlet-mapping>
<error-page>
<error-code>404</error-code>
<location>/p/error</location>
</error-page>
<!-- force encoding on the requests -->
<filter>
<filter-name>encoding-filter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding-filter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
<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>
<filter-name>UrlRewriteFilter</filter-name>
<filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>UrlRewriteFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Security -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/application-config.xml
/WEB-INF/app-security.xml
/WEB-INF/mvc-config.xml
</param-value>
</context-param>
<session-config>
<session-timeout>1</session-timeout>
</session-config>
</web-app>
any ideas how to solve this issue ?
You have said:
i want that if the user typed a bad url if he's logged in or not, he's redirected to the error page directly
Spring security will intercept every request before it knows whether its url is valid or not, so a way to get it would be intercept all valid urls with some patterns, and add at the end a general pattern which could be accessed by anyone.
<intercept-url pattern="/" access="permitAll" />
<intercept-url pattern="/validUrl1Pattern" access="permitAll" />
<intercept-url pattern="/validUrl2Pattern" access="permitAll" />
<intercept-url pattern="/validUrl2Pattern" access="permitAll" />
...
<intercept-url pattern="/**" access="ROLE_ANONYMOUS" />
The problem of this configuration is that is probably difficult to find patterns for all the valid urls if your application is complex.
Yep just add this:
<intercept-url pattern="/error/**" access="permitAll" />
That will make it so that anyone can get to all your error pages.
when you set the attribute access="true", you tell spring-security to check if the user has the security attribute (which is normally a role) named "true" . I don't think that is your goal?
to bypass security, you may set filters="none" and skip the access attribute:
<intercept-url pattern="/errorpage" filters="none" />
see documentation of <intercept-url>
Add /error to your list of <intercept-url/> elements so that it doesn't require authentication in order to access it.

Resources