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.
Related
I rewrite the security configuration class from this tutorial.
I try to enter the entries without login, the server redirect to the login page well, but submit the user credentials to login processing URL return page not found. How should I fix it?
My Spring Security configuration:
#Configuration
#EnableWebSecurity
public class SecurityConfiguration {
#Autowired
#Qualifier("customUserDetailsService")
UserDetailsService userDetailsService;
#Autowired
PersistentTokenRepository tokenRepository;
#Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
auth.authenticationProvider(authenticationProvider());
}
#Configuration
#Order(1)
ublic static class MobileSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/mobile/**")
.authorizeRequests()
.anyRequest().hasRole("MOBILE")
.and()
.formLogin()
.loginPage("/mobile_login")
.loginProcessingUrl("/mobile_login_processing_url")
.usernameParameter("ssoId")
.passwordParameter("password")
.defaultSuccessUrl("/mobile/menu")
.and()
.logout()
.logoutUrl("/mobile_logout")
.logoutSuccessUrl("/mobile_login?logout")
.deleteCookies("JSESSIONID")
.and()
.exceptionHandling()
.accessDeniedPage("/Access_Denied")
.defaultAuthenticationEntryPointFor(authenticationEntryPoint(), new AntPathRequestMatcher("/mobile/**"));
}
#Bean
Public AuthenticationEntryPoint authenticationEntryPoint(){
return new LoginUrlAuthenticationEntryPoint("/mobile_login");
}
}
#Configuration
#Order(2)
public static class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
PersistentTokenRepository tokenRepository;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/web/**").hasRole("ADMIN")
.and()
.formLogin()
.loginPage("/web_login")
.loginProcessingUrl("/web_login_processing_url")
.usernameParameter("ssoId")
.passwordParameter("password")
.defaultSuccessUrl("/web/list")
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/web_login?logout")
.deleteCookies("JSESSIONID")
.and()
.exceptionHandling().accessDeniedPage("/Access_Denied");
}
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
authenticationProvider.setUserDetailsService(userDetailsService);
authenticationProvider.setPasswordEncoder(passwordEncoder());
return authenticationProvider;
}
#Bean
public PersistentTokenBasedRememberMeServices getPersistentTokenBasedRememberMeServices() {
PersistentTokenBasedRememberMeServices tokenBasedservice = new PersistentTokenBasedRememberMeServices(
"remember-me", userDetailsService, tokenRepository);
return tokenBasedservice;
}
#Bean
public AuthenticationTrustResolver getAuthenticationTrustResolver() {
return new AuthenticationTrustResolverImpl();
}
}
Your login processing URL /mobile_login_processing_url is unavailable.
You configured a formLogin, which adds a UsernamePasswordAuthenticationFilter for a HttpSecurity, see FormLoginConfigurer:
The following Filters are populated
UsernamePasswordAuthenticationFilter
but your HttpSecurityis restricted to the pattern /mobile/**, see HttpSecurity#antMatcher:
Allows configuring the HttpSecurity to only be invoked when matching the provided ant pattern.
so with URL /mobile_login_processing_url the HttpSecurityis not invoked and therefore the UsernamePasswordAuthenticationFilter is never applied. Without this filter, the form login is not processible, see UsernamePasswordAuthenticationFilter:
Processes an authentication form submission.
You have to change your login processing URL to /mobile/mobile_login_processing_url. See your modified configuration:
#Configuration
#Order(1)
ublic static class MobileSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/mobile/**")
.authorizeRequests()
.anyRequest().hasRole("MOBILE")
.and()
.formLogin()
.loginPage("/mobile_login")
.loginProcessingUrl("/mobile/mobile_login_processing_url")
.usernameParameter("ssoId")
.passwordParameter("password")
.defaultSuccessUrl("/mobile/menu")
.and()
.logout()
.logoutUrl("/mobile_logout")
.logoutSuccessUrl("/mobile_login?logout")
.deleteCookies("JSESSIONID")
.and()
.exceptionHandling()
.accessDeniedPage("/Access_Denied")
.defaultAuthenticationEntryPointFor(authenticationEntryPoint(), new AntPathRequestMatcher("/mobile/**"));
}
#Bean
Public AuthenticationEntryPoint authenticationEntryPoint(){
return new LoginUrlAuthenticationEntryPoint("/mobile_login");
}
}
We would like to apply Oauth2 based security for the Rest Controllers while the rest of the application will have Spring Security. Will that be possible? Can you provide any examples please?
It seems like WebSecurityConfigurerAdapter and ResourceServerConfigurerAdapter conflicting when both configured.
Thank you in advance.
Yes it's possible. Here the example template configuration code is given. Please change the required configs to your need. The key is to define Sub static classes of configuration with different order. Here i have considered any requests which is orginating from \api as a REST API call.
I have not checked the code by compiling it.
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true, proxyTargetClass = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
#Order(1)
#Configuration
public static class ApiWebSecurityConfig extends OAuth2ServerConfigurerAdapter{
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//Write the AuthenticationManagerBuilder codes for the OAuth
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.antMatcher("/api/**")
.authorizeRequests()
.anyRequest().authenticated()
.and()
.apply(new OAuth2ServerConfigurer())
.tokenStore(new InMemoryTokenStore())
.resourceId(applicationName);
}
}
}
#Order(2)
#Configuration
public static class FormWebSecurityConfig extends WebSecurityConfigurerAdapter{
#Autowired
public void configure(AuthenticationManagerBuilder auth) throws Exception {
//Write the AuthenticationManagerBuilder codes for the Normal authentication
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable() //HTTP with Disable CSRF
.authorizeRequests() //Authorize Request Configuration
.anyRequest().authenticated()
.and() //Login Form configuration for all others
.formLogin()
.loginPage("/login").permitAll()
.and() //Logout Form configuration
.logout().permitAll();
}
}
}
I'm trying to do an example using spring-boot with spring security. My idea is to create a web app and also provide an API, I would like to both have security; so I need to create a multi http web security configuration however it is not working.
I followed this link http://docs.spring.io/spring-security/site/docs/3.2.x/reference/htmlsingle/#multiple-httpsecurity but no success. And, I'm getting this error
Error creating bean with name 'webSecurityConfiguration': Injection of autowired dependencies failed; nested exception is java.lang.IllegalStateException: Cannot apply org.springframework.security.config.annotation.authentication.configurers.provisioning.InMemoryUserDetailsManagerConfigurer to already built object
The configuration that I'm using is the following:
#Configuration
#Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
#EnableGlobalAuthentication
#EnableGlobalMethodSecurity(securedEnabled = true)
public class WebSecurityConfiguration {
#Autowired
protected void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("12345").roles("USER").and()
.withUser("admin").password("12345").roles("USER", "ADMIN");
}
#Configuration
#Order(1)
public static class ApiConfigurationAdapter extends
WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/api/**")
.authorizeRequests()
.anyRequest().hasRole("ADMIN")
.and()
.httpBasic();
}
}
#Configuration
#Order(2)
public static class WebConfigurationAdapter extends
WebSecurityConfigurerAdapter {
#Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/resources/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/home").permitAll()
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/login").permitAll()
.and()
.logout().permitAll();
}
}
}
Thanks in advance
after a lot of reading I found something that works for me:
#Configuration
#Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
#EnableGlobalMethodSecurity(securedEnabled = true)
public class WebSecurityConfiguration extends GlobalAuthenticationConfigurerAdapter {
#Resource(name = "customUserDetailsService")
protected CustomUserDetailsService customUserDetailsService;
#Resource
private DataSource dataSource;
#Autowired
protected void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(customUserDetailsService);
}
#Configuration
#Order(1)
public static class ApiConfigurationAdapter extends WebSecurityConfigurerAdapter {
#Resource(name = "restUnauthorizedEntryPoint")
private RestUnauthorizedEntryPoint restUnauthorizedEntryPoint;
#Resource(name = "restAccessDeniedHandler")
private RestAccessDeniedHandler restAccessDeniedHandler;
#Override
protected void configure(HttpSecurity http) throws Exception {
SecurityConfigurer<DefaultSecurityFilterChain, HttpSecurity> securityXAuthConfigurerAdapter = new XAuthTokenConfigurer(
userDetailsServiceBean());
// #formatter:off
http
.antMatcher("/api/**").csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.exceptionHandling()
.authenticationEntryPoint(restUnauthorizedEntryPoint)
.accessDeniedHandler(restAccessDeniedHandler)
.and()
.authorizeRequests()
.antMatchers(HttpMethod.POST, "/api/authenticate").permitAll()
.anyRequest().hasRole("ADMIN")
.and()
.apply(securityXAuthConfigurerAdapter);
// #formatter:on
}
}
#Configuration
#Order(2)
public static class WebConfigurationAdapter extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
// #formatter:off
http
.authorizeRequests()
.antMatchers("/", "/home").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login").permitAll()
.and()
.logout().permitAll()
;
// #formatter:on
}
}
}
I'm also faced the same issue. But I got it solved when I extend the WebSecurityConfiguration master class from WebSecurityConfigurerAdapter.
Kindly refer the following stackoverflow post in which you can find the full configuration.
Spring Security HTTP Basic for RESTFul and FormLogin for web - Annotations
I found I could solve this problem by annotating my class with
#EnableWebSecurity after reading this hint: https://github.com/spring-projects/spring-data-examples/issues/189#issuecomment-229552207
I have updated recently to spring-security-3.2.0.RC2 from RC1, and according to the blog post the QUIESCENT_POST_PROCESSOR have been removed. Before I used to create an AuthenticationManager bean like this below:
#Bean(name = {"defaultAuthenticationManager", "authenticationManager"})
public AuthenticationManager defaultAuthenticationManager() throws Exception {
return new AuthenticationManagerBuilder(null).userDetailsService(context.getBean(MyUserDetailsService.class)).passwordEncoder(new Md5PasswordEncoder()).and().build();
}
so I've changed it to:
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws BeansException, Exception {
auth.userDetailsService(context.getBean(MyUserDetailsService.class)).passwordEncoder(new Md5PasswordEncoder());
}
but unfortunately I can't get hold of the AuthenticationManager any more. I'm also creating RememberMeAuthenticationFilter like this:
#Bean(name = { "defaultRememberMeAuthenticationFilter", "rememberMeAuthenticationFilter" })
protected RememberMeAuthenticationFilter defaultRememberMeAuthenticationFilter() throws Exception {
return new RememberMeAuthenticationFilter(defaultAuthenticationManager(), context.getBean(DefaultRememberMeServices.class));
}
so as you can see I need to get hold of AuthenticationManager, but I don't know how???
You really shouldn't need to get a hold of the AuthenticationManager. From the javadoc of HttpSecurity the following should work just fine:
#Configuration
#EnableWebSecurity
public class RememberMeSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/**").hasRole("USER")
.and()
.formLogin()
.permitAll()
.and()
// Example Remember Me Configuration
.rememberMe();
}
}
Of course if you are using global AuthenticationManager, this will work too:
#Configuration
#EnableWebSecurity
public class RememberMeSecurityConfig 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("/**").hasRole("USER")
.and()
.formLogin()
.permitAll()
.and()
// Example Remember Me Configuration
.rememberMe();
}
}
The only difference is the first example isolates the AuthenticationManger to the HttpSecurity where as the second example will allow the AuthenticationManager to be used by global method security or another HttpSecurity (WebSecurityConfigurerAdapter).
The reason this works is the .rememberMe() will automatically find the AuthenticationManager, UserDetailsService and use that when creating the RememberMeAuthenticationFilter. It also creates the appropriate RememberMeServices so there is no need to do that. Of course there are additional options on .rememberMe() if you want to customize it, so refer to the RememberMeConfigurer javadoc for additional options.
If you REALLY need a reference to the AuthenticationManager instance you can do the following:
#Configuration
#EnableWebSecurity
public class RememberMeSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private AuthenticationManagerBuilder auth;
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth)
throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER");
}
#Bean
public AuthenticationManager authenticationManager() {
return auth.build();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/**").hasRole("USER")
.and()
.formLogin()
.permitAll()
.and()
// Example Remember Me Configuration
.rememberMe();
}
}
If you want to have multiple AuthenticationManager instances, you can do the following:
#Autowired
private ObjectPostProcessor<Object> opp;
public AuthenticationManager authenticationManager()
throws Exception {
return new AuthenticationManagerBuilder(opp)
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER").and()
.and()
.build();
}
public AuthenticationManager authenticationManager2()
throws Exception {
return new AuthenticationManagerBuilder(opp)
.inMemoryAuthentication()
.withUser("admin").password("password").roles("ADMIN").and()
.and()
.build();
}
NOTE This is almost the same as you had things before hand except instead of using the QUIESENT_POST_PROCESSOR you are using a real ObjectPostProcessor using the #Autowired annotation
PS: Thanks for giving RC2 a try!
The way to expose and get access to the AuthenticationManager bean is as follows:
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception
{
return super.authenticationManagerBean();
}
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");
}
}