The great Spring Security Plugin is now available for Grails 3!
I will leave these blog posts up as a reference, but I would strongly suggest (as if you needed the suggestion) to use the Spring-Security plugin for Grails 3
Since Spring Security Core PluginUses:
- Grails Version: 3.0.0.M2
- Groovy Version: 2.4.1
- JVM Version: 1.7.0_51
Setting up Security:
Simply add the following to build.gradle in the dependencies:compile "org.springframework.boot:spring-boot-starter-security"This will cause ALL HTTP endpoints to require authorization and a random password to be generated each time you start up your app. Also, because Spring-Boot-Security-Starter logs the randomly generated password at level INFO, you need to add the following to your logback.groovy file.
//see http://logback.qos.ch/manual/groovy.html for more info logger('org.springframework.boot.autoconfigure.security', INFO)This is not sufficient for anything but a demo, so let's customize it a bit. Let's start with the easiest part, creating a fixed password. There are a few methods of setting a static password, but we'll concentrate on two 1) in the application.yml or 2) in a WebSecurityConfigurerAdapter Class.
In the Application.yml file
security: user: password: password
In a WebSecurityConfigurerAdapter Class
Using a WebSecurityConfigurerAdapter class, we can override the default implementation(s) used in spring-boot-starter-security.grails-app/init/simpleappwithsecurity/SecurityConfiguration.groovy
package simpleappwithsecurity import org.springframework.beans.factory.annotation.Autowired import org.springframework.context.annotation.Configuration import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; @Configuration @EnableWebSecurity class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth .inMemoryAuthentication() .withUser("user").password("pwd").roles("USER"); } }One important note, Grails does NOT know anything about the SecurityConfiguration class unless you do something to tell your Grails' app about the new class. The two easiest methods are to specify a bean in resources.groovy
grails-app/conf/spring/resources.groovy
import simpleappwithsecurity.SecurityConfiguration beans = { webSecurityConfiguration(SecurityConfiguration) }If you use this, you do not need the class annotations @Configuration and @EnableWebSecurity on the SecurityConfiguration class. Another method is to enable Spring's Component Scan on the Grails application in the Application.groovy file by adding @ComponentScan to the Application class, such as
grails-app/init/Application.groovy
... import org.springframework.context.annotation.ComponentScan; @ComponentScan class Application extends GrailsAutoConfiguration { ...I think this depends on how you view your application. If it is a Grails Application, using primarily Grails Plugins with Spring sprinkled in, then use the first method. If it is a Spring Boot application with Grails sprinkled in, use the latter method. For now, our app is a Grails app, so we'll use the bean definition in resources.groovy.
Securing specific URIs (or request maps)
Let's extend our example by adding pattern matches to our SecurityConfiguration class.grails-app/init/simpleappwithsecurity/SecurityConfiguration.groovy
... @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers('/admin/**').hasAnyRole('ADMIN') .antMatchers('/home/**').hasAnyRole('USER', 'ADMIN') .antMatchers('/').permitAll() .and() .formLogin().permitAll() .and() .logout().permitAll() } //<-- --="" .inmemoryauthentication="" .withuser="" auth="" code="" configureglobal="" end="" exception="" in="" of="" password="" previous="" public="" roles="" snippet="" throws="" user="" uthenticationmanagerbuilder="" utowired="" void=""> .and() .withUser('admin').password('admin').roles('ADMIN'); } ...-->Restarting the application now will allow you to see the index page, but require authentication when attempting to access /home or /admin controllers.