I am using spring security 3.2 using the namespace configuration, and I want to make all the calls to be https. I know it would decrease the performance by about 1/10, but I still want to implement it. I know you/might achieve this from tomcat itself, but i want to configure it in security.xml
You can configure that https is required by adding requires-channel attribute on each intercept-url. For example:
<http>
<intercept-url pattern="/secure/**" access="ROLE_ADMIN" requires-channel="https"/>
<intercept-url pattern="/**" access="ROLE_USER" requires-channel="https"/>
</http>
You can configure this more concisely using Spring Security Java Configuration. Notice that we can separate the channel configuration from the role mappings. For example:
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/secure/**").hasRole("ADMIN")
.anyRequest.hasRole("USER")
.and()
.requiresChannel()
.anyRequest().requiresSecure();
}
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER");
}
}
As of Spring Security 3.2 you also might want to ensure you use Spring Security's headers support. This is enabled by default in Spring Security Java Configuration. In this specific case, the element can add a header called Strict-Transport-Security to the response that ensures that browsers do not even make HTTP requests in the future. For example:
<headers>
<hsts/>
</headers>
You will want to read more about this in the Headers section of the reference.
Related
I am attempting to configure cache-control response header to a custom value via my Spring Security configuration XML. Unfortunately, it seems like I'm only able to disable the cache-control header from the XML configuration as per the documentation:
<http>
<headers defaults-disable="true">
<cache-control />
</headers>
</http>
Being this seems to be the case, I attempted to create a custom WebSecurityConfigurerAdapter as so:
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
System.out.println("******* SETTING CUSTOM CACHE-CONTROL....");
StaticHeadersWriter writer = new StaticHeadersWriter("Cache-Control", "2592000");
RequestMatcher resourcesMatcher = new AntPathRequestMatcher("/**/*");
HeaderWriter resourcesHeaderWriter = new DelegatingRequestMatcherHeaderWriter(resourcesMatcher, writer);
http.headers().cacheControl().disable().addHeaderWriter(resourcesHeaderWriter);
http.headers().disable();
}
}
Unfortunately, even though the class is in fact initially called, it seems like the configuration is actually overwritten by the XML, as the cache-control response header still appears to be set to the defaults:
Any thoughts on how I can specify something similar with the XML file itself, preferably able to match a specific pattern (ex. *.js)?
Thanks!
I believe the answer that you want is already described in the question here:
disable caching for specific url in spring security
By doing something like this:
<security:http>
[intercept-url, etc omitted...]
<security:headers>
<!-- selectively applied to dynamic pages only via pattern matching, -->
<security:header ref="noCacheHeaders"/>
</security:headers>
</security:http>
<bean id="noCacheHeaders" class="org.springframework.security.web.header.writers.DelegatingRequestMatcherHeaderWriter">
<constructor-arg>
<bean class="org.springframework.security.web.util.matcher.AntPathRequestMatcher">
<constructor-arg value="/index.html"/>
</bean>
</constructor-arg>
<constructor-arg>
<bean class="org.springframework.security.web.header.writers.CacheControlHeadersWriter"/>
</constructor-arg>
</bean>
I have a fairly out-of-the-box Spring Security 3.2 J2EE xml config that I have almost finished converting to Java config.
The Before xml file:
<sec:global-method-security pre-post-annotations="enabled" />
<sec:authentication-manager />
<sec:http pattern="/css/**" security="none" />
<sec:http pattern="/js/**" security="none" />
....
<sec:http auto-config="true" create-session="never" use-expressions="true>
<sec:session-management session-fixation-protection="none" />
<sec:jee mappable-roles="admin,user" />
<sec:intercept-url pattern="/operations/admin/**" access="hasRole('ROLE_admin')" />
<sec:intercept-url pattern="/**" access="permitAll" />
</sec:http>
The self closing authentication-manager tag is my issue. It's picking up the PreAuthenticatedAuthenticationProvider created by the jee tag. I'm not quite sure how to replicate it in the Java Config:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled=true)
#ImportResource("classpath:security-context.xml")
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter{
#Override
public void configure(WebSecurity web) throws Exception{
web
.ignoring.antMatchers("/css/**")
.and()
.ignoring.antMatchers("/js/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception{
http
.sessionManagement()
.sessionFixation().none()
.sessionCreationPolicy(SessionCreationPolicy.NEVER)
.and()
.csrf().disable()
.jee()
.mappableAuthorities("admin","user")
.and()
.authorizeRequests()
.antMatchers("/operations/admin/**").hasAuthority("admin")
.anyRequest.permitAll();
}
}
This is working now only because I am importing my old security-context.xml which has nothing in it except the authentication-manager tag.
I have playing around with declaring an AuthenticationManagerBuilder bean, but it seems like everything requires a specific reference to an AuthenticationProvider or UserDetailsService to work. The ProviderManager default constructor is deprecated.
I know that the jee() entry adds the PreAuthenticatedAuthenticationProvider to the sharedObjects inside HttpSecurity, so I could go through the trouble of getting the PreAuthenticatedAuthenticationProvider out of the sharedObjects to create an AuthenticationManager if necessary, but it seems like there ought to be a simple Java config counterpart to the self-closing xml tag that I am just missing.
Can you try this on your SpringSecurityConfig class :-
#Autowired
public void registerGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(new AuthenticationManagerBeanDefinitionParser.NullAuthenticationProvider());
}
How can I replace default filter with custom filter in java configuration? In XML it would be, for example:
<bean id="myFilter" class="lalalal.MyFilter">
<property name="authenticationManager" ref="authenticationManager"/>
</bean>
<security:http auto-config="true">
<security:custom-filter ref="myFilter" position="FORM_LOGIN_FILTER"/>
</security:http>
About filterBefore, filterAfter and default filter inhereting I know.
Assuming you have an understanding in general of Java configuration for Spring-security, adding filters is relatively simple (general details of updating spring-security config to java here):
So in your WebSecurityConfigurerAdapter implementation, do something like this:
#Configuration
#EnableWebSecurity
class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override protected void configure(HttpSecurity http) throws Exception {
//Custom security filters
http.addFilterBefore( myFilter(), BasicAuthenticationFilter.class );
//Rest of the security configuration goes here
...
}
That is a very cut down example - but hopefully helps enough - you would put additional security configuration here (e.g. role based restrictions, csrf, session config etc) and myFilter() is another method defining the bean you mention in the question that sets up your Filter. There is also an addFilterAfter() method and you can choose where to place your filter in the chain.
Here is an example for API security that shows some custom filters being used.
I am using java config to apply spring security and i am able to apply security on particular urls but i want the default login page of spring security whenever anyone hits urls other than url which is not secured.
Here is my code of SecurityConfig:
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
//import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.web.bind.annotation.RequestMethod;
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter
{
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/myproject/userCont/user").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/myproject/login/form")
.loginProcessingUrl("/login")
.failureUrl("/login/form?error")
.permitAll();
}
so when i hit /myproject/userCont/user with GET method it works correctly but when I hit the same url with POST method or other urls spring security do not shows default login page.
Can any one help me?
doGet and doPost in Servlets
You should go through the above link to get a clear idea about GET and POST methods.
To remove spring security for /myproject/userCont/user url ur code should look like:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/myproject/login/form")
.loginProcessingUrl("/login")
.failureUrl("/login/form?error")
.permitAll();
}
Further more, You should not convert your urls into POST method as this will change the entire behaviour of your web page.
When we are in xml file
Inside the configuration element, you can restrict access to particular URLs with
one or more elements. Each element specifies a URL pattern
and a set of access attributes required to access the URLs. Remember that you must
always include a wildcard at the end of a URL pattern. Failing to do so will make the URL pattern
unable to match a URL that has request parameters.
<security:http auto-config="true" >
<security:intercept-url pattern="/index*" access="ROLE_USER" />
<security:intercept-url pattern="/Transit*" access="ROLE_USER" />
<security:form-login login-page="/login.htm" default-target-url="/index.htm"
authentication-failure-url="/loginerror.htm" />
<security:logout logout-success-url="/logout.htm" />
</security:http>
When ever we are going to describe a url without any security, Then we should remove the particular url from the above lines of code under security configured xml file.
for example if we dont need any security for index page then the above coding should look like this.
<security:http auto-config="true" >
<security:intercept-url pattern="/Transit*" access="ROLE_USER" />
<security:form-login login-page="/login.htm" default-target-url="/index.htm"
authentication-failure-url="/loginerror.htm" />
<security:logout logout-success-url="/logout.htm" />
</security:http>
Enabled CSRF in my Spring MVC application using Spring security 3.2.
My spring-security.xml
<http>
<intercept-url pattern="/**/verify" requires-channel="https"/>
<intercept-url pattern="/**/login*" requires-channel="http"/>
...
...
<csrf />
</http>
Trying to disable CSRF for requests that contain 'verify' in request URL.
MySecurityConfig.java
#Configuration
#EnableWebSecurity
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
private CsrfMatcher csrfRequestMatcher = new CsrfMatcher();
#Override
public void configure(HttpSecurity http) throws Exception {
http.csrf().requireCsrfProtectionMatcher(csrfRequestMatcher);
}
class CsrfMatcher implements RequestMatcher {
#Override
public boolean matches(HttpServletRequest request) {
if (request.getRequestURL().indexOf("verify") != -1)
return false;
else if (request.getRequestURL().indexOf("homePage") != -1)
return false;
return true;
}
}
}
Csrf filter validates CSRF token that is submitted from 'verify' and Invalid token exception (403) is thrown as I'm submitting request to https from http. How can I disable csrf token authentication in such a scenario ?
I know this is not a direct answer, but people (as me) usually don't specify spring's version when searching for this kinds of questions.
So, since spring security a method exists that lets ignore some routes:
The following will ensure CSRF protection ignores:
Any GET, HEAD, TRACE, OPTIONS (this is the default)
We also explicitly state to ignore any request that starts with "/sockjs/"
http
.csrf()
.ignoringAntMatchers("/sockjs/**")
.and()
...
I hope that my answer can help someone else. I found this question searching for How to disable CSFR for specfic URLs in Spring Boot.
I used the solution described here:
http://blog.netgloo.com/2014/09/28/spring-boot-enable-the-csrf-check-selectively-only-for-some-requests/
This is the Spring Security configuration that allow me to disable the CSFR control on some URLs:
#Configuration
#EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
// Build the request matcher for CSFR protection
RequestMatcher csrfRequestMatcher = new RequestMatcher() {
// Disable CSFR protection on the following urls:
private AntPathRequestMatcher[] requestMatchers = {
new AntPathRequestMatcher("/login"),
new AntPathRequestMatcher("/logout"),
new AntPathRequestMatcher("/verify/**")
};
#Override
public boolean matches(HttpServletRequest request) {
// If the request match one url the CSFR protection will be disabled
for (AntPathRequestMatcher rm : requestMatchers) {
if (rm.matches(request)) { return false; }
}
return true;
} // method matches
}; // new RequestMatcher
// Set security configurations
http
// Disable the csrf protection on some request matches
.csrf()
.requireCsrfProtectionMatcher(csrfRequestMatcher)
.and()
// Other configurations for the http object
// ...
return;
} // method configure
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth)
throws Exception {
// Authentication manager configuration
// ...
}
}
It works with Spring Boot 1.2.2 (and Spring Security 3.2.6).
I am using Spring Security v4.1. After a lot of reading and testing, I disable the CSRF security feature for specific URLs using XML configuration.
<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"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">
<http pattern="/files/**" security="none" create-session="stateless"/>
<http>
<intercept-url pattern="/admin/**" access="hasAuthority('GenericUser')" />
<intercept-url pattern="/**" access="permitAll" />
<form-login
login-page="/login"
login-processing-url="/login"
authentication-failure-url="/login"
default-target-url="/admin/"
password-parameter="password"
username-parameter="username"
/>
<logout delete-cookies="JSESSIONID" logout-success-url="/login" logout-url="/admin/logout" />
<http-basic />
<csrf request-matcher-ref="csrfMatcher"/>
</http>
<beans:bean id="csrfMatcher" class="org.springframework.security.web.util.matcher.OrRequestMatcher">
<beans:constructor-arg>
<util:list value-type="org.springframework.security.web.util.matcher.RequestMatcher">
<beans:bean class="org.springframework.security.web.util.matcher.AntPathRequestMatcher">
<beans:constructor-arg name="pattern" value="/rest/**"/>
<beans:constructor-arg name="httpMethod" value="POST"/>
</beans:bean>
<beans:bean class="org.springframework.security.web.util.matcher.AntPathRequestMatcher">
<beans:constructor-arg name="pattern" value="/rest/**"/>
<beans:constructor-arg name="httpMethod" value="PUT"/>
</beans:bean>
<beans:bean class="org.springframework.security.web.util.matcher.AntPathRequestMatcher">
<beans:constructor-arg name="pattern" value="/rest/**"/>
<beans:constructor-arg name="httpMethod" value="DELETE"/>
</beans:bean>
</util:list>
</beans:constructor-arg>
</beans:bean>
//...
</beans:bean>
With the above configuration, I enable the CSRF security only for POST|PUT|DELETE requests of all URLs which start with /rest/.
Explicitly disable for specific url patterns and enable for some url patterns.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
#EnableWebSecurity
public class SecurityConfig {
#Configuration
#Order
public static class GeneralWebSecurityConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http.csrf().ignoringAntMatchers("/rest/**").and()
.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/home/**","/search/**","/geo/**").authenticated().and().csrf()
.and().formLogin().loginPage("/login")
.usernameParameter("username").passwordParameter("password")
.and().exceptionHandling().accessDeniedPage("/error")
.and().sessionManagement().maximumSessions(1).maxSessionsPreventsLogin(true);
}
}
}
<http ...>
<csrf request-matcher-ref="csrfMatcher"/>
<headers>
<frame-options policy="SAMEORIGIN"/>
</headers>
...
</http>
<b:bean id="csrfMatcher"
class="AndRequestMatcher">
<b:constructor-arg value="#{T(org.springframework.security.web.csrf.CsrfFilter).DEFAULT_CSRF_MATCHER}"/>
<b:constructor-arg>
<b:bean class="org.springframework.security.web.util.matcher.NegatedRequestMatcher">
<b:bean class="org.springframework.security.web.util.matcher.AntPathRequestMatcher">
<b:constructor-arg value="/chat/**"/>
</b:bean>
</b:bean>
</b:constructor-arg>
</b:bean>
mean of
http
.csrf()
// ignore our stomp endpoints since they are protected using Stomp headers
.ignoringAntMatchers("/chat/**")
example from :
https://docs.spring.io/spring-security/site/docs/4.1.x/reference/htmlsingle/
Use security="none".
for e.g in spring-security-config.xml
<security:intercept-url pattern="/*/verify" security="none" />