I have a basic REST service exposing various APIs based on Spring MVC and the @RestController mechanism. Now I am trying to add an interceptor for Spring security in order to require login (through a particular REST request) before any other request can be accessed. The idea is that the interceptor checks the active session of the request, and points it to the login service if an active login is not found. If an active login is found the interceptor lets the request through to the proper URL. I've been playing around with the XML files but all I keep getting is redirection loops. :( It's worthwhile noting that I do not have a view associated with this server at all. Access is done via http requests from a GUI that I don't have access to.
Here's my configuration thus far: Web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<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">
<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml, /WEB-INF/spring/application-security.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>/aisrv/*</url-pattern>
</filter-mapping>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Processes application requests -->
<servlet>
<servlet-name>aisrvServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/aisrvServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>aisrvServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
Servlet-Context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
<!-- Enables the Spring MVC @Controller programming model -->
<annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<context:component-scan base-package="com.bmc.ai.server" />
<!--- Specific beans for my server -->
</beans:beans>
application-security.xml:
<?xml version="1.0" encoding="UTF-8"?>
<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-3.2.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.2.xsd">
<http pattern="/resources/**" security="none" />
<http auto-config="true" use-expressions="true">
<!-- <intercept-url pattern="/login" access="ROLE_ADMIN" /> -->
<!-- <intercept-url pattern="/logout" access="permitAll" />
<intercept-url pattern="/accessdenied" access="permitAll" /> -->
<intercept-url pattern="/**" access="ROLE_USER" requires-channel="https"/>
<!-- <http-basic /> -->
<form-login default-target-url="/test" />
<!-- <logout logout-success-url="/logout" /> -->
</http>
<authentication-manager alias="authenticationManager">
<authentication-provider>
<user-service>
<user name="user" password="123" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</authentication-manager>
</beans:beans>
I'm sure this is something pretty basic and easy to fix, but I can't seem to find my hand and legs in it. Any help would be greatly appreciated.
============EDIT======================= Following the example from Varun I've modified my application-security.xml like this:
<?xml version="1.0" encoding="UTF-8"?>
<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-3.2.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.2.xsd">
<http pattern="/resources/**" security="none" />
<http auto-config="true" use-expressions="true">
<!-- other filters -->
<custom-filter ref="myCustomFilter" before="SESSION_MANAGEMENT_FILTER" />
<intercept-url pattern="/**" access="ROLE_USER" requires-channel="https"/>
</http>
<beans:bean id="myCustomFilter" class="com.company.server.impl.security.RestFilter">
</beans:bean>
<!-- <http auto-config="true" use-expressions="true">
<intercept-url pattern="/login" access="ROLE_ADMIN" />
<intercept-url pattern="/logout" access="permitAll" />
<intercept-url pattern="/accessdenied" access="permitAll" />
<intercept-url pattern="/**" access="ROLE_USER" requires-channel="https"/>
<http-basic />
<form-login default-target-url="/test" />
<logout logout-success-url="/logout" />
</http>-->
<authentication-manager alias="authenticationManager">
<authentication-provider>
<user-service>
<user name="user" password="123" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</authentication-manager>
</beans:beans>
and added the following RestFiletClass:
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.web.filter.GenericFilterBean;
import com.company.server.controller.ExcpetionHandling.GenericErrorExeception;
import com.company.server.interfaces.comm.ICorbaClient;
public class RestFilter extends GenericFilterBean {
@Override
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = ((HttpServletResponse) res);
HttpServletRequest request = ((HttpServletRequest) req);
ICorbaClient corba = (ICorbaClient)request.getSession().getAttribute("corba");
if(corba.getSuccessfulLogin()){
System.out.println("Authorized through filter");
chain.doFilter(req, res);
}else{
throw new GenericErrorExeception("User unauthorized", null, HttpServletResponse.SC_UNAUTHORIZED);
}
}
}
However, spring appears to skip the filter altogether. Do I need to add it somewhere or do something more with it?
You need to add a custom filter in your spring security xml. In the example below a pre-built filter has been modified, but you can checkout the classes as reference to build your own filter.
<http use-expressions="true">
<!-- other filters -->
<custom-filter ref="myCustomFilter" before="SESSION_MANAGEMENT_FILTER" />
</http>
<beans:bean id="myCustomFilter" class="com.mycompany.RestFilter">
</beans:bean>
public class RestFilter extends GenericFilterBean {
// @Override of Filter.doFilter() method
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
// Implement
}
}
Spring security will automatically call this filter before the predefined SESSION_MANAGEMENT_FILTER
and run your code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With