I am working on converting a Spring 3 project to Spring 4 + Spring Boot. I don't know whether it is a right thing to do or not yet. I convert the Spring Security XML configuration to a Java based configuration as the following:
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/", "/home").permitAll()
.anyRequest().authenticated();
http.formLogin()
.defaultSuccessUrl("/afterLogin")
.loginPage("/profiles/lognin/form")
.failureUrl("/accessDenied")
.and()
.authorizeRequests()
.regexMatchers("....")
.hasRole("ROLE_USER")
.antMatchers("....")
.hasRole("ROLE_USER")
//....
;
}
#Override
protected void configure(AuthenticationManagerBuilder authManagerBuilder)
throws Exception {
authManagerBuilder.authenticationProvider(this.getDaoAuthenticationProvider());
}
// ....
}
I get the Spring Security default login popup panel when I hit the home URL. It seem to me that the above configuration doesn't take effect, but the default Spring Security configuration in Spring Boot doesn't. If so, how to override the default one?
I found the answer. I need to create a file called application.properties with the following line:
security.basic.enabled=false
and place this file under src/main/resource. That is it.
Configure your spring like that.
protected void configure(HttpSecurity http) throws Exception {
http
.csrf()
.and()
.addFilterAfter(csrfHeaderFilter(), CsrfFilter.class)
.exceptionHandling()
.and()
.rememberMe()
.and()
.formLogin()
.loginProcessingUrl("/user") // rest apiyi yaz.
//.usernameParameter("username")
//.passwordParameter("password")
.permitAll()
.and()
.logout()
//.logoutUrl("/api/logout")
//.deleteCookies("JSESSIONID", "CSRF-TOKEN")
.permitAll()
.and()
.headers()
.frameOptions()
.disable()
.authorizeRequests()
.antMatchers("/login").permitAll()
.antMatchers("/#/dashboard/home").permitAll()
;
}
Related
This question already has answers here:
Spring Security : Multiple HTTP Config not working
(2 answers)
Closed 1 year ago.
I am working with two Security configuration by extending WebSecurityConfigurerAdaptor like below
#Configuration
#Order(100)
public class CustomerSecurityAppConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user1")
.password("{noop}password")
.and()
.withUser("user2")
.password("{noop}password")
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.cors().disable();
http
.authorizeRequests()
.antMatchers("/customers/**")
.anyRequest()
.authenticated()
.and()
.formLogin()
.and()
.httpBasic();
}
}
#Configuration
class EmployeeSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("admin")
.password("{noop}password")
.roles("USER", "ADMIN")
.and()
.withUser("user")
.password("{noop}password")
.roles("USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.cors().disable();
http
.authorizeRequests()
.antMatchers(HttpMethod.GET, "/inventory/**")
.hasAnyRole("USER", "ADMIN")
.antMatchers(HttpMethod.POST, "/inventory/**")
.hasRole("ADMIN")
.anyRequest()
.authenticated()
.and()
.formLogin()
.and()
.httpBasic();
}
}
The idea here is to have two realms. One for customers and one for orders. When I make the HTTP requests, I am getting 200 OK response for both the /inventory and /customers endpoint with the users configured for CustomerSecurityConfiguration and getting 401 error for both users configured for EmployeeSecurityConfiguration configuration. I have two REST endpoints for inventory and customers with GET and POST.
Where am I going wrong?
I had to add the request matcher for the http like below
http
.requestMatchers().antMatchers("/actuator/**")
.and()
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.formLogin()
.and()
.httpBasic();
I've use Spring Security's WebSecurityConfig to manager permissions.
and permissions just loaded once when the spring application started.
so how could I manually reload WebSecurityConfig in runtime when permission is changed?
this is my WebSecurityConfig code:
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter
{
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/css/**").permitAll()
.antMatchers("/js/**").permitAll()
.antMatchers("/rest/login").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/boss/login")
.permitAll()
.and()
.logout()
.permitAll();
http.csrf().disable();
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authProvider);
}
}
Just get injected into WebSecurityConfig whatever you need. You can use #Autowire and #Value inside the WebSecurityConfig.
I am using Spring boot 1.3.2 with Spring Security.
I have following configure(HttpSecurity http) method to inforce authentication
protected void configure(HttpSecurity http) throws Exception {
RequestMatcher csrfRequestMatcher = new RequestMatcher() {
private AntPathRequestMatcher[] requestMatchers = {
new AntPathRequestMatcher("/iams/w/*")
};
#Override
public boolean matches(HttpServletRequest request) {
for (AntPathRequestMatcher rm : requestMatchers) {
if (rm.matches(request)) { return true; }
}
return false;
} // method matches
};
http
.csrf()
.requireCsrfProtectionMatcher(csrfRequestMatcher)
.and()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.requestCache()
.requestCache(new NullRequestCache())
.and()
.httpBasic();
}
and I have following configure(WebSecurity web) method to ignore some of the urls as below;
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers(
"/myapp/docs/**",
"/myapp/docs/*",
"/myapp/docs/index.html",
"/resources/**",
"/static/**");
}
But http request to http://127.0.0.1:9000/myapp/docs/index.html still reuires username/password ( authentication ) and returns "status":401,"error":"Unauthorized"...
Actually none of the ignore url on WebSecurity is working since it also requires authentication. If I provide the auth then it works. How can I simply ignore some urls (like "/myapp/docs/**" ) here. I have following definition in the SecurityConfig class
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
What am I missing ? Please Advise.
It would probably be easier to use as simple a set of patterns as possible to leave unsecured, and then simply say that everything else IS secured.
This may be closer to what you want:
public static final String[] NOT_SECURED = {"/iams/docs/**","/static/**"};
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers(NOT_SECURED);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers(NOT_SECURED).permitAll()
.anyRequest().authenticated()
.and()
.httpBasic()
.and()
.requestCache()
.requestCache(new NullRequestCache())
.and()
.csrf().disable();
}
There is an error order in your code.
http
.csrf()
.requireCsrfProtectionMatcher(csrfRequestMatcher)
.and()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.requestCache()
.requestCache(new NullRequestCache())
.and()
.httpBasic();
Therefore, any request is needed to be authenticated. You can directly use antMatchers.
http
.authorizeRequests()
.antMatchers("/iams/w/*")
.authenticated()
.and()
.httpBasic()
.and()
.requestCache()
.requestCache(new NullRequestCache())
.csrf().disable()
I hope it's helpful for you.
Thank you for your response but with your suggestion, my "/iams/w/*" is not protected at all. I can get to all these urls; "/iams/docs/**" , "/iams/w/" and "/iams/api/" without basic auth. Below is the set up as per your suggestion. Here I want to protect "/iams/w" and "/iams/api/" with username/password but let everyone get to "/iams/docs/*" without username/password. This is spring boot restful based implementation but want to expose some urls like docs so that it can be accessed by all and not the api calls.
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers(
"/iams/docs/**",
"/iams/docs/*",
"/iams/docs/index.html",
"/static/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/iams/api/**","/iams/api/v1/*")
.authenticated()
.and()
.httpBasic()
.and()
.requestCache()
.requestCache(new NullRequestCache())
.and()
.csrf().disable();
}
I want to expose an unsecure Restful endpoint in a Springboot secured application. GET requests to the endpoint /api/notify work, but POST requests result in a 403. How do I configure so that remote clients can POST to /api/notify from there server?
My extended WebSecurityConfigurerAdapter looks like this:
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/signup").permitAll()
.antMatchers("/reset").permitAll()
.antMatchers("/api/notify").permitAll()
.anyRequest().authenticated();
http
.formLogin()
.defaultSuccessUrl("/home")
.failureUrl("/login?error")
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
I think this is what you are looking for:
#Configuration
#EnableWebMvcSecurity
public class SecurityCtxConfig extends WebSecurityConfigurerAdapter {
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring()
.antMatchers(HttpMethod.POST,
"<YOUR URL>");
}
I suggest you try the folllowing configuration:
protected void configure(HttpSecurity http) throws Exception {
//This reads, invoke this configuration only when
//the pattern "/api/notify" is found.
//When this configuration is invoked, restrict access,
//disable CSRF, and if the path matches "/api/notify" permit all.
http.antMatcher("/api/notify")
.csrf().disable()
.authorizeRequests()
.antMatchers("/api/notify")
.permitAll();
//Your other configuration...
http
.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/signup").permitAll()
.antMatchers("/reset").permitAll()
.anyRequest().authenticated();
http
.formLogin()
.defaultSuccessUrl("/home")
.failureUrl("/login?error")
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
My current java security config looks as follows:
#Configuration
#EnableWebSecurity
public class RootConfig extends WebSecurityConfigurerAdapter {
#Override
protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception
{
auth.inMemoryAuthentication()
.withUser("tester").password("passwd").roles("USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeUrls()
.anyRequest().authenticated()
.and()
.httpBasic();
}
}
When I perform a GET request using a browser, I'll get an error 403.
I would expect to get a browser popup asking me for a username / password.
What might be the problem?
UPDATE: This is fixed in Spring Security 3.2.0.RC1+
This is a bug in the Security Java Configuration that will be resolved for the next release. I have created SEC-2198 to track it. For now, a work around is to use something like the following:
#Bean
public BasicAuthenticationEntryPoint entryPoint() {
BasicAuthenticationEntryPoint basicAuthEntryPoint = new BasicAuthenticationEntryPoint();
basicAuthEntryPoint.setRealmName("My Realm");
return basicAuthEntryPoint;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.exceptionHandling()
.authenticationEntryPoint(entryPoint())
.and()
.authorizeUrls()
.anyRequest().authenticated()
.and()
.httpBasic();
}
PS: Thanks for giving Spring Security Java Configuration a try! Keep the feedback up :)
With Spring Security 4.2.3 and probably before you can simply use this configuration:
#Configuration
#EnableWebSecurity
public class CommonWebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(final HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.httpBasic();
}
#Autowired
public void dlcmlUserDetails(final AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("tom").password("111").roles("USER");
}
}