I'm currently writing a Spring MVC application, secured by Spring Security. For the login a basic form authentication is used and since I didn't added further configuration the credentials are POSTed to http://www.localhost:8080/myWebApp/j_spring_security_check.
So far so good, but now I've introduced a second servlet (CometD), which shall not be affected by Spring nor Spring Security. For this, I tried to change the servlet-mappings to map Spring and Spring Security against /app, respectively /app/*, and the other Servlet against cometd/*. My web.xml looks as follows:
<!-- Spring security -->
<listener>
<listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</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>/app/*</url-pattern>
</filter-mapping>
<!-- Spring MVC -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/app</url-pattern>
</servlet-mapping>
<!-- CometD -->
<servlet>
<servlet-name>cometd</servlet-name>
<servlet-class>org.cometd.server.CometdServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>cometd</servlet-name>
<url-pattern>/cometd/*</url-pattern>
</servlet-mapping>
The problem with this is that after this changes I'm be able to login any more. The server is not able to find any request mapping and the client tells me
NetworkError: 404 Not Found - http://localhost:8080/myWebApp/app/j_spring_security_check.
What's wrong with this mappings? How can I configure Spring and Spring Security to only handle requests for specific mappings and not for / and /* as described in the documentation?
Thanks a lot in advance!
Best,
René
Leave your springSecurityFilterChain mapped to /. Change your security config:
<http use-expressions="true">
<intercept-url pattern="/cometd/**" access="permitAll" />
<intercept-url pattern="/**" access="hasRole('ROLE_USER')" />
</http>
Related
I get a 404 error when I try to access a Spring Security protected URL after I have successfully logged in, but do not get the error when I do not protect the URL with Spring Security.
I am using Spring-MVC, Spring Security and Hibernate. I have tried to get what the problem might be, but have totally failed. I need your help guys.
My spring-security.xml file is as:
<http auto-config="true">
<intercept-url pattern="/sec/*" access="ROLE_USER" />
<form-login login-page="/login"
authentication-success-handler-ref="successHandler" authentication-failure-handler-ref="failureHandler"
authentication-failure-url="/login/error" />
<remember-me/>
<logout logout-success-url="/login" />
<access-denied-handler error-page="/403"/>
</http>
The dispatcher-servlet.xml is as:
<mvc:annotation-driven/>
<bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles2.TilesConfigurer" p:definitions="/WEB-INF/tiles.xml" />
<bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.tiles2.TilesView"/>
</bean>
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="/WEB-INF/application"/>
<property name="cacheSeconds" value="1"/>
and web.xml is as:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/dispatcher-servlet.xml,
/WEB-INF/spring-security.xml,
/WEB-INF/applicationContext.xml,
/WEB-INF/spring-db.xml
</param-value>
</context-param>
<filter>
<filter-name>hibernateSessionInViewFilter</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
<init-param>
<param-name>sessionFactoryBeanName</param-name>
<param-value>sessionFactory</param-value>
</init-param>
<init-param>
<param-name>flushMode</param-name>
<param-value>ALWAYS</param-value>
</init-param>
<init-param>
<param-name>singleSession</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>hibernateSessionInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<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>
<listener>
<listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</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>
<welcome-file-list>
<welcome-file>redirect.jsp</welcome-file>
</welcome-file-list>
Note that the Spring Security Authentication works just fine. Its the urls it protects that kind of are no longer being mapped by the dispatcher. Someone please help me solve this. Thank you in advance.
I have got the problem. I had set the wrong role in the database for the user I was trying to log in as. So essentially its a 403 error of which I hadn't mapped the 403 handling page hence throwing the 404 error. Thanx to all those who tried to help.
There ara two DispatcherServlets in my app. One is for jsp service and dispatches admin's addresses.
<servlet>
<servlet-name>adminServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/adminServlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>adminServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
Second DispatcherServlet dispatches addresses where xml or json are sending.
<servlet>
<servlet-name>userServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/userServlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>userServlet</servlet-name>
<url-pattern>/user/*</url-pattern>
</servlet-mapping>
There is also DelegatingFilterProxy to ensure security
<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>
Security context configuration file:
<http auto-config="true" use-expressions="true">
<intercept-url pattern="/login.do"
access="permitAll" requires-channel="http" />
<intercept-url pattern="/*"
access="hasRole('ROLE_USER')" requires-channel="http" />
<intercept-url pattern="/admin/*"
access="hasRole('ROLE_ADMIN')" requires-channel="http" />
<form-login login-page="/login.do"
login-processing-url="/loginProcess" username-parameter="user"
password-parameter="password" default-target-url="/admin" />
<logout logout-url="/logout.do"
invalidate-session="true" />
<remember-me key="secCh4"
token-validity-seconds="3600" data-source-ref="dataSource" />
<session-management
session-fixation-protection="newSession">
</session-management>
<intercept-url pattern="/user/*" access="hasRole('ROLE_USER')" />
</http>
The part of service which is dispatched by adminServlet need authentication and is secured, but the part which is dipatched by userServlet is completely unsecured and any authentication is not necessary. I don't know why, I set url-pattern in DelegatingFilterProxy to /* and i also set
<intercept-url pattern="/user/*" access="hasRole('ROLE_USER')" />
Any ideas?
DelegatingFilterProxy has nothing to do with DispatcherServlet. In fact, Spring MVC is not needed and you can use any other frame, like Struts.
With your rule <intercept-url pattern="/user/*" access="hasRole('ROLE_USER')" /> you are specifying to intercept urls like /user/list/ or /user/4, but not /user/4/save. If you want to intercept all urls starting with /user/ try with <intercept-url pattern="/user/**" access="hasRole('ROLE_USER')" />. You can read a little more here.
Anyway, remember that intercept-url order is important, too.
I am using Spring MVC within Tomcat and what I thought was a standard configuration. The web.xml looks like this:
<servlet>
<servlet-name>acme</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/appServlet/acme-spring.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>acme</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
Withing the Spring acme-spring.xml, I have the view-controller tag set to the root path:
<mvc:view-controller path="/" view-name="login.jsp"/
and the site resolver tag:
<bean id="siteResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver" >
<property name="prefix">
<value>/WEB-INF/views/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
However, when I hit localhost:8080/acme, I would have expected the login.jsp but instead, I receive an Invalid URL error. I took a look at both HTTP Status 404 on Spring 3.1 MVC app and HTTP Status 404 on Spring 3.1 MVC app but there was no joy.
Thoughts on what I have misconfigured?
your tag should be like this
<mvc:view-controller path="/" view-name="login"/>
because veiwResolver will take care about the prefix and suffix.
if you are accessing it by using just context path ,
then you should either mention your welcome-file list in your web-xml
or you should direcly access any welcome or jsp which you want to show on start-up.
1.First add below lines or hit localhost:8080/acme/Login.jsp instead of hitting localhost:8080/acme
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
2. Add servlet name mapping like :
<servlet>
<servlet-name>app_name</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
Add servlet URL mapping :
app_name
*.do //you can write url pattern as per your requir.
check and let me know if any other exception you are facing..!!
How do I ensure that a call is being made to the OAuth2ProtectedResourceFilter when a request is sent with the oauth_token in the Authorization header?
It always passes through a filter if it is mapped properly
As mentioned, everything that you want to be secured, needs to go through a spring security filter:
Here a sample how a filter is mapped in front of the servlet (the spring MVC DispatcherServlet used for the authorization endpoints)
You could additionally map the same filter to any other servlet, for example to a jersey servlet you have configured.
In /WEB-INF/web.xml you need a filter-mapping like:
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<servlet-name>spring-dispatcher</servlet-name>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
<servlet>
<servlet-name>spring-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-mvc-dispatcher-servlet.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>spring-dispatcher</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
To ensure every call to '/*', or whatever pattern, is filtered you use http from the spring security namespace and a filter called OAuth2AuthenticationProcessingFilter, that will watch out for the Bearer Authorization header, you will need something like this in your /WEB-INF/spring-mvc-dispatcher-servlet.xml or where ever your spring security is configured:
<http pattern="/**"
create-session="never"
authentication-manager-ref="userAuthenticationManager"
access-decision-manager-ref="accessDecisionManager"
use-expressions="true">
<anonymous enabled="false" />
<custom-filter ref="oAuth2AuthenticationFilter" position="PRE_AUTH_FILTER" />
<access-denied-handler ref="oAuthAccessDeniedHandler" />
<intercept-url pattern="/**" access="isAuthenticated()" />
</http>
<beans:bean id="oAuth2AuthenticationFilter" class="org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter">
<beans:property name="authenticationManager" ref="userAuthenticationManager"/>
<beans:property name="authenticationEntryPoint" ref="oAuthAuthenticationEntryPoint"/>
</beans:bean>
I have specified my JAX-RS Application in the web.xml as follows:
<servlet>
<servlet-name>CXFServlet</servlet-name>
<servlet-class>
org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet
</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>
com.myapp.MYRestApplication
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
Is it possible for me to pass another JAX-RS application class to this CXF servlet?
Regards,
Anand
While CXF can manage multiple JAX-RS applications within a single servlet — I use this configuration in my own code — it is sufficiently complex that you're far better off switching to using a Spring-based configuration. The CXFNonSpringJaxrsServlet can only support limited configuration. In my code, I have this (a little complex because I'm also using Spring security, but you can drop that filter):
<!-- Location of the main Spring/CXF configuration file -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/beans.xml</param-value>
</context-param>
<!-- Apply Spring Security as a wrapper to everything -->
<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>
<!-- Hook for Spring lifecycle management; you want this -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- A single servlet to handle all CXF processing -->
<servlet>
<servlet-name>CXFServlet</servlet-name>
<display-name>CXF Servlet</display-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>