I am trying to add ACL capabilities to my server. I have configured spring security using java file and would like to add ACL in the same manner. How should I do it? All the tutorials I found used XML file.
SecurityInit:
#Order(1)
public class SecurityInitializer extends AbstractSecurityWebApplicationInitializer {
}
SecurityConfig
#EnableWebMvcSecurity
#EnableGlobalMethodSecurity(prePostEnabled=true)
#Component
#ComponentScan(basePackages = {"test.package"})
public class SecurityConfig extends
WebSecurityConfigurerAdapter {
...
#Autowired
protected void registerAuthentication(UserDetailsService userDetailsService, AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
// http://stackoverflow.com/a/21100458/162345
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.headers().disable()
.addFilterBefore(...)
.addFilterBefore(...)
// TODO: create a better way to differentiate login to signup
.exceptionHandling()
.authenticationEntryPoint(noRedirectForAnonymous)
.and()
.formLogin()
.successHandler(restAuthenticationSuccessHandler)
.failureHandler(restAuthenticationFailureHandler)
.and()
.logout()
.logoutSuccessHandler(noRedirectLogoutSuccessHandler)
.and()
.authorizeRequests()
.antMatchers("/api/keywords/**").permitAll()
.antMatchers("/api/**").authenticated();
}
}
You can configure spring acl with Java configuration class as follow
#Configuration
#EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class ACLConfig extends GlobalMethodSecurityConfiguration {
#Autowired
DataSource dataSource;
EhCacheBasedAclCache aclCache() {
EhCacheFactoryBean factoryBean = new EhCacheFactoryBean();
EhCacheManagerFactoryBean cacheManager = new EhCacheManagerFactoryBean();
factoryBean.setName("aclCache");
factoryBean.setCacheManager(cacheManager.getObject());
return new EhCacheBasedAclCache(factoryBean.getObject());
}
LookupStrategy lookupStrategy() {
return new BasicLookupStrategy(dataSource, aclCache(), aclAuthorizationStrategy(), new ConsoleAuditLogger());
}
AclAuthorizationStrategy aclAuthorizationStrategy() {
return new AclAuthorizationStrategyImpl(new SimpleGrantedAuthority("ROLE_ACL_ADMIN"),
new SimpleGrantedAuthority("ROLE_ACL_ADMIN"),
new SimpleGrantedAuthority("ROLE_ACL_ADMIN"));
}
#Bean
JdbcMutableAclService aclService() {
JdbcMutableAclService service = new JdbcMutableAclService(dataSource, lookupStrategy(), aclCache());
service.setClassIdentityQuery("select currval(pg_get_serial_sequence('acl_class', 'id'))");
service.setSidIdentityQuery("select currval(pg_get_serial_sequence('acl_sid', 'id'))");
return service;
}
#Bean
AclMasterService masterService() {
return new AclMasterService();
}
#Override
protected MethodSecurityExpressionHandler createExpressionHandler(){
DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
expressionHandler.setPermissionEvaluator(new AclPermissionEvaluator(aclService()));
return expressionHandler;
}
}
The important aspect of the configuration are extend from
GlobalMethodSecurityConfiguration
override the method
createExpressionHandler
and enable the Pre and Post anotations with the follow anotation at the begining of the class
#EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled =
true)
Now you can use anotations like
#PreAuthorize('hasPermission(#object,read)')
see the Contact sample of Spring Security or the spring security reference guide for more uses of #Pre and #Post anotations.
This configuration class was tested on Spring 4 , Spring Security 4.0.1 and Spring Security ACL 3.1.2. If you want configure the authentication you can use a different Java class or override the configure method from this. If you already have a configured ehcache this configuration could not work correctly due to the ehcache is a singleton class and this configuration try to create a new one.
There is no way to configure spring acl without xml file. This is mentioned in spring docs itself.Refer to spring documentation.
Related
Since WebSecurityConfigurerAdapter has been deprecated, I have updated my SecurityConfig class with defining SecurityFilterChain as a bean in my config class but none of the config is working and spring still generates Security Password!
Here's my new WebSecurityConfig:
#Configuration
#EnableWebSecurity
public class SecurityConfig {
#Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf().disable();
http.authorizeHttpRequests()
.requestMatchers("/auth/**").permitAll()
.requestMatchers("/role1/**").hasAnyRole("admin")
.requestMatchers("/role2/**").hasAnyRole("admin")
.requestMatchers("/role3/**").hasAnyRole("admin")
.anyRequest()
.permitAll();
return http.build();
}
}
Spring still generates password:
Using generated security password: ******-****-****-****-**********
This generated password is for development use only. Your security configuration must be updated before running your application in production.
I have tried excluding SecurityAutoConfiguration class from the main application but it did not work.
You can either remove the UserDetailsServiceAutoConfiguration by doing:
#SpringBootApplication(excludes = UserDetailsServiceAutoConfiguration.class) or you can provide a UserDetailsService of your own:
#Bean
public UserDetailsService userDetailsService() {
return new InMemoryUserDetailsManager();
}
I have implemented authentication in my Spring Boot Application with Spring Security.
The main class controlling authentication should be websecurityconfig:
#Configuration
#EnableWebSecurity
#PropertySource(value = { "classpath:/config/application.properties" })
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private RestAuthenticationSuccessHandler authenticationSuccessHandler;
#Autowired
private RestAuthenticationEntryPoint restAuthenticationEntryPoint;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic()
.and()
.csrf().disable()
.sessionManagement().sessionCreationPolicy(
SessionCreationPolicy.STATELESS)
.and()
.exceptionHandling()
.authenticationEntryPoint(restAuthenticationEntryPoint)
.and()
.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/login").permitAll()
.antMatchers("/logout").permitAll()
.antMatchers("/ristore/**").authenticated()
.anyRequest().authenticated()
.and()
.formLogin()
.successHandler(authenticationSuccessHandler)
.failureHandler(new SimpleUrlAuthenticationFailureHandler());
}
Since I am doing OAuth, I have AuthServerConfig and ResourceServerConfig as well. My main application class looks like this:
#SpringBootApplication
#EnableSpringDataWebSupport
#EntityScan({"org.mdacc.ristore.fm.models"})
public class RistoreWebApplication extends SpringBootServletInitializer
{
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("*");
}
};
}
public static void main( String[] args )
{
SpringApplication.run(RistoreWebApplication.class, args);
}
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(RistoreWebApplication.class);
}
}
Since we are doing code consolidation, we need to turn off authentication temporarily. However, I tried the following methods and nothing seems to work. I am still getting 401 when I hit these rest api urls.
Comment out all the annotations in classes related to security including #Configuration, #EnableWebSecurity. In Spring boot Security Disable security, it was suggested at the bottom adding #EnableWebSecurity will DISABLE auth which I don't think make any sense. Tried it anyway, did not work.
Modify websecurityconfig by removing all the security stuff and only do
http
.authorizeRequests()
.anyRequest().permitAll();
Disable Basic Authentication while using Spring Security Java configuration. Does not help either.
Remove security auto config
#EnableAutoConfiguration(exclude = {
org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration.class,
org.springframework.boot.actuate.autoconfigure.ManagementSecurityAutoConfiguration.class})
like what they did in disabling spring security in spring boot app. However I think this feature only works with spring-boot-actuator which I don't have. So didn't try this.
What is the correct way disable spring security?
As #Maciej Walkowiak mentioned, you should do this for your main class:
#SpringBootApplication(exclude = org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration.class)
public class MainClass {
try this
1->Comment annotation #EnableWebSecurity in your security config
//#EnableWebSecurity
2->Add these lines in your security config
spring.security.enabled=false
management.security.enabled=false
security.basic.enabled=false
What worked for me is this. Creating WebFilter and PermitAll Request Exchange and disabling CSRF.
#Bean
public SecurityWebFilterChain chain(ServerHttpSecurity http, AuthenticationWebFilter webFilter) {
return http.authorizeExchange().anyExchange().permitAll().and()
.csrf().disable()
.build();
}
Just put this code in #SpringBootApplication class, Like this and will work like charm
#SpringBootApplication
public class ConverterApplication {
public static void main(String[] args) {
SpringApplication.run(ConverterApplication.class, args);
}
#Bean
public SecurityWebFilterChain chain(ServerHttpSecurity http, AuthenticationWebFilter webFilter) {
return http.authorizeExchange().anyExchange().permitAll().and()
.csrf().disable()
.build();
}
#Preauthrize and #Secured annotations are not working in Spring Oauth (All examples I've referred to are for Spring basic security and not for Oauth protocol):
What I've done is:
I enabled global security in spring_security.xml
I used Preauthrize tag in service but it is not working.
Just add
#EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
To one of your configurations. I have added to my Resource Server Config
#Configuration
#EnableResourceServer
#Order(2)
#EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
#Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.resourceId("Sample");
}
#Override
public void configure(HttpSecurity http) throws Exception {
//restrict access using #Secured or #PreAuthorize annotation
http.authorizeRequests().anyRequest().permitAll();
}
}
Worked flawlessly
I'm new to Spring Security so I probably miss out on something. I have a Spring Application that starts a Jetty with a WebApplication I want to secure using Spring Security. The webapp is running and reachable, but not restricted. I've tried a lot of stuff but nothing worked so I broke it down to a minimal setup, but still no chance.
the webapp is configured by the following java configuration:
#EnableWebMvc
#Configuration
#Import(SecurityConfiguration.class)
#ComponentScan(useDefaultFilters = false, basePackages = { "myapp.web" }, includeFilters = { #ComponentScan.Filter(Controller.class) })
public class SpringMvcConfiguration extends WebMvcConfigurerAdapter {
/**
* Allow the default servlet to serve static files from the webapp root.
*/
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
and Spring Security configured here:
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user")
.password("password")
.roles("ADMIN")
.authorities("ADMIN");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest()
.hasAuthority("ADMIN");
}
}
and some controller like this:
#Controller
public class SecuredController {
#RequestMapping(value = "/secure", method = RequestMethod.GET)
#ResponseBody
public String secured() {
return "you should not see this unless you provide authentication";
}
}
Everything starts up all right, the log tells me, that the controller is mapped...
[2014-10-01 20:21:29,538, INFO ] [main] mvc.method.annotation.RequestMappingHandlerMapping:197 - Mapped "{[/secure],methods=[GET],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public java.lang.String myapp.web.SecuredController.secured()
...and that security is in place as well...
[2014-10-01 20:21:30,298, INFO ] [main] gframework.security.web.DefaultSecurityFilterChain:28 - Creating filter chain: org.springframework.security.web.util.matcher.AnyRequestMatcher#1, [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter#352c308, org.springframework.security.web.context.SecurityContextPersistenceFilter#2af616d3, org.springframework.security.web.header.HeaderWriterFilter#1a2e2935, org.springframework.security.web.csrf.CsrfFilter#64f857e7, org.springframework.security.web.authentication.logout.LogoutFilter#bc57b40, org.springframework.security.web.savedrequest.RequestCacheAwareFilter#3deb2326, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter#7889a1ac, org.springframework.security.web.authentication.AnonymousAuthenticationFilter#7d373bcf, org.springframework.security.web.session.SessionManagementFilter#5922ae77, org.springframework.security.web.access.ExceptionTranslationFilter#7e1a1da6, org.springframework.security.web.access.intercept.FilterSecurityInterceptor#1051817b]
... but the /secure url of my controller is unconditionally reachable. What am I doing wrong?
ps. I want to avoid xml config
In order to integrate Spring Security with Spring MVC you have to use #EnableWebMvcSecurity annotation instead of #EnableWebSecurity in SecurityConfiguration class.
I figured, I had to move the initialization of the Spring Security configuration to the root context, not the dispatcher-servlet context, and add the following line where i configure the context of my embedded Jetty:
context.addFilter(new FilterHolder(new DelegatingFilterProxy("springSecurityFilterChain")), "/*", EnumSet.allOf(DispatcherType.class));
I'm trying to setup a Spring Security 3.2 project using Java Config and no XML at all.
I want to have an Access decision voter that supports both RoleHierarchyVoter and AclEntryVoters. This is the configuration I'm using:
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private AclEntryVoter aclUpdatePropertyVoter;
#Autowired
private AclEntryVoter aclDeletePropertyVoter;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.and()
.logout()
.deleteCookies("JSESSIONID")
.logoutSuccessUrl("/")
.and()
.authorizeRequests()
.accessDecisionManager(accessDecisionManager())
.antMatchers("/login", "/signup/email", "/logout", "/search", "/").permitAll()
.anyRequest().authenticated();
}
#Bean
public RoleHierarchyVoter roleVoter() {
RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
roleHierarchy.setHierarchy("ROLE_USER > ROLE_ANONYMOUS");
RoleHierarchyVoter roleHierarchyVoter = new RoleHierarchyVoter(roleHierarchy);
return roleHierarchyVoter;
}
#Bean
public AffirmativeBased accessDecisionManager() {
List<AccessDecisionVoter> decisionVoters = new ArrayList<>();
WebExpressionVoter webExpressionVoter = new WebExpressionVoter();
decisionVoters.add(webExpressionVoter);
decisionVoters.add(roleVoter());
decisionVoters.add(aclDeletePropertyVoter);
decisionVoters.add(aclUpdatePropertyVoter);
AffirmativeBased affirmativeBased = new AffirmativeBased(decisionVoters);
return affirmativeBased;
}
}
However, when the app gets initialized I get the following exception:
I get the exception:
java.lang.IllegalArgumentException: AccessDecisionManager does not support secure object class: class org.springframework.security.web.FilterInvocation
When debugging the code I can see that when AbstractAccessDecisionManager is called and the following code is executed:
public boolean supports(Class<?> clazz) {
for (AccessDecisionVoter voter : this.decisionVoters) {
if (!voter.supports(clazz)) {
return false;
}
}
return true;
}
RoleHierarchyVoter support FilterInvocation, however AclEntryVoters fail to pass it. What I'm doing wrong in the configuration? How can I set the project so that it supports both types of voters? Thanks a lot in advance
As you've observed, the acl voters don't support filter invocations as they are intended for checking secured methods, not web requests.
You should configure a separate AccessDecisionManager for use with your method security and add the acl voters to that.