I developing some rest application and have problems with configuration of spring security.
Help me with my xml configuration for spring security 4 in my rest aplication.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:sec="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
<import resource="classpath*:securityServicesContext.xml"/>
<import resource="classpath*:businessServicesContext.xml"/>
<sec:http pattern="/rest/**" create-session="stateless" auto-config="false" entry-point-ref="unauthorizedEntryPoint">
<sec:expression-handler ref="webSecurityExpressionHandler"/>
<sec:custom-filter ref="customTokenAuthenticationFilter" position="FORM_LOGIN_FILTER"/>
<sec:intercept-url pattern="/rest/login" access="permitAll"/>
<sec:intercept-url pattern="/**" access="hasRole('USER')"/>
<sec:csrf disabled="true"/>
</sec:http>
<sec:authentication-manager id="authenticationManager">
<sec:authentication-provider ref="daoAuthenticationProvider"/>
</sec:authentication-manager>
<bean id="unauthorizedEntryPoint" class="com.itechart.security.web.security.UnauthorizedEntryPoint"/>
<bean id="customTokenAuthenticationFilter"
class="com.itechart.security.web.security.CustomTokenAuthenticationFilter">
<constructor-arg name="defaultFilterProcessesUrl" value="/rest/**"/>
<constructor-arg name="authenticationManager" ref="authenticationManager"/>
<constructor-arg name="authenticationSuccessHandler">
<bean class="com.itechart.security.web.security.TokenSimpleUrlAuthenticationSuccessHandler"/>
</constructor-arg>
</bean>
When I send username&password to /rest/login I catch in the CustomTokenAuthenticationFilter and authentication failed. How I can configure my xml to /rest/login request was without filtering and other /rest/** with filtering?
Here is my web.xml:
<?xml version="1.0" encoding="UTF-8"?>
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<display-name>Security Web Application</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/dispatcherServlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-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>/rest/*</url-pattern>
</filter-mapping>
<resource-ref>
<res-ref-name>jdbc/SecuritySampleDB</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
<welcome-file-list>
<welcome-file>/app/index.html</welcome-file>
</welcome-file-list>
UPDATE 1:
public class CustomTokenAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
private static final Logger logger = LoggerFactory.getLogger(CustomTokenAuthenticationFilter.class);
private String excludedUrl;
public CustomTokenAuthenticationFilter(String excludedUrl, String defaultFilterProcessesUrl, AuthenticationManager authenticationManager, AuthenticationSuccessHandler authenticationSuccessHandler) {
super(defaultFilterProcessesUrl);
this.excludedUrl = excludedUrl;
super.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher(defaultFilterProcessesUrl));
setAuthenticationManager(authenticationManager);
setAuthenticationSuccessHandler(authenticationSuccessHandler);
}
public final String HEADER_SECURITY_TOKEN = "X-CustomToken";
/**
* Attempt to authenticate request - basically just pass over to another method to authenticate request headers
*/
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
String token = request.getHeader(HEADER_SECURITY_TOKEN);
logger.info("token found:" + token);
AbstractAuthenticationToken userAuthenticationToken = authUserByToken(token);
if (userAuthenticationToken == null)
throw new AuthenticationServiceException(MessageFormat.format("Error | {0}", "Bad Token"));
return userAuthenticationToken;
}
/**
* authenticate the user based on token
*
* @return
*/
private AbstractAuthenticationToken authUserByToken(String token) {
if (token == null) {
return null;
}
AbstractAuthenticationToken authToken = null;//todo
try {
return authToken;
} catch (Exception e) {
logger.error("Authenticate user by token error: ", e);
}
return authToken;
}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
if (((HttpServletRequest) req).getRequestURI().endsWith(excludedUrl)) {
chain.doFilter(req, res);
} else {
super.doFilter(req, res, chain);
}
}
}
Here is log, when I send request:
21:14:00.805 [http-nio-8080-exec-1] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/rest/test'; against '/rest/**'
21:14:00.808 [http-nio-8080-exec-1] DEBUG o.s.security.web.FilterChainProxy - /rest/test at position 1 of 8 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
21:14:00.818 [http-nio-8080-exec-1] DEBUG o.s.security.web.FilterChainProxy - /rest/test at position 2 of 8 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
21:14:00.826 [http-nio-8080-exec-1] DEBUG o.s.security.web.FilterChainProxy - /rest/test at position 3 of 8 in additional filter chain; firing Filter: 'HeaderWriterFilter'
21:14:00.826 [http-nio-8080-exec-1] DEBUG o.s.s.w.h.writers.HstsHeaderWriter - Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@1fd019da
21:14:00.827 [http-nio-8080-exec-1] DEBUG o.s.security.web.FilterChainProxy - /rest/test at position 4 of 8 in additional filter chain; firing Filter: 'CustomTokenAuthenticationFilter'
21:14:00.827 [http-nio-8080-exec-1] DEBUG o.s.security.web.FilterChainProxy - /rest/test at position 5 of 8 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
21:14:00.836 [http-nio-8080-exec-1] DEBUG o.s.security.web.FilterChainProxy - /rest/test at position 6 of 8 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
21:14:00.838 [http-nio-8080-exec-1] DEBUG o.s.s.w.a.AnonymousAuthenticationFilter - Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken@9055c2bc: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS'
21:14:00.839 [http-nio-8080-exec-1] DEBUG o.s.security.web.FilterChainProxy - /rest/test at position 7 of 8 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
21:14:00.839 [http-nio-8080-exec-1] DEBUG o.s.security.web.FilterChainProxy - /rest/test at position 8 of 8 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
21:14:00.840 [http-nio-8080-exec-1] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/rest/test'; against '/rest/login'
21:14:00.842 [http-nio-8080-exec-1] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/rest/test'; against '/rest/test'
21:14:00.842 [http-nio-8080-exec-1] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Secure object: FilterInvocation: URL: /rest/test; Attributes: [permitAll]
21:14:00.843 [http-nio-8080-exec-1] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@9055c2bc: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS
21:14:00.862 [http-nio-8080-exec-1] DEBUG o.s.s.access.vote.AffirmativeBased - Voter: org.springframework.security.web.access.expression.WebExpressionVoter@66e0e4e6, returned: 1
21:14:00.862 [http-nio-8080-exec-1] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Authorization successful
21:14:00.862 [http-nio-8080-exec-1] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - RunAsManager did not change Authentication object
21:14:00.863 [http-nio-8080-exec-1] DEBUG o.s.security.web.FilterChainProxy - /rest/test reached end of additional filter chain; proceeding with original chain
21:14:00.925 [http-nio-8080-exec-1] WARN o.s.web.servlet.PageNotFound - No mapping found for HTTP request with URI [/rest/test] in DispatcherServlet with name 'dispatcherServlet'
21:14:00.933 [http-nio-8080-exec-1] DEBUG o.s.s.w.a.ExceptionTranslationFilter - Chain processed normally
21:14:00.933 [http-nio-8080-exec-1] DEBUG o.s.s.w.c.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed