The final mile: Upgrade to Grails 2.4.3 and use Spring Security REST plugin
After I wrote down this series of Create a restful application with AngularJS and Grails, I have received some feedback from my blogspot and mail. I decide to update this sample to the latest Grails and use the Spring Security REST plugin instead of my customized solution, it is more powerful and flexible.Upgrade to Grails 2.4.3
-
Update the Grails version to 2.4.3, which is the newest when I wrote this. You can change the value in application.properties file directly or using
grails
command to complete the work.
grails set-grails-version 2.4.3
- Please read the Upgrading from Grails 2.3 section of the official reference document to update dependencies manually. Note: The
upgrade
command was removed in Grails 2.4, currently this manual approach is the only way to upgrade your application to the latest 2.4.x. -
Make sure all things are done well. Run the application via command line.
grails run-app
Configure Spring Security REST Plugin
Spring Security REST plugin is an extension of Spring Security plugin which allow you create stateless, token-based authentication for your REST API.-
Open
BuildConfig.groovy
file, and add Spring Security REST Plugin in theplugins
section.
compile ":spring-security-rest:1.4.0", { excludes: 'spring-security-core' }
-
Add the basic configuration in the
Config.groovy
file.
//Config for Spring Security REST plugin //login grails.plugin.springsecurity.rest.login.active=true grails.plugin.springsecurity.rest.login.endpointUrl="/api/login" grails.plugin.springsecurity.rest.login.failureStatusCode=401 grails.plugin.springsecurity.rest.login.useJsonCredentials=true grails.plugin.springsecurity.rest.login.usernamePropertyName='username' grails.plugin.springsecurity.rest.login.passwordPropertyName='password' //logout grails.plugin.springsecurity.rest.logout.endpointUrl='/api/logout' //token generation grails.plugin.springsecurity.rest.token.generation.useSecureRandom=true grails.plugin.springsecurity.rest.token.generation.useUUID=false //token storage // use memcached. //grails.plugin.springsecurity.rest.token.storage.useMemcached false //grails.plugin.springsecurity.rest.token.storage.memcached.hosts localhost:11211 //grails.plugin.springsecurity.rest.token.storage.memcached.username '' //grails.plugin.springsecurity.rest.token.storage.memcached.password '' //grails.plugin.springsecurity.rest.token.storage.memcached.expiration 3600 //use GROM //grails.plugin.springsecurity.rest.token.storage.useGorm false //grails.plugin.springsecurity.rest.token.storage.gorm.tokenDomainClassName null //grails.plugin.springsecurity.rest.token.storage.gorm.tokenValuePropertyName tokenValue //grails.plugin.springsecurity.rest.token.storage.gorm.usernamePropertyName username //class AuthenticationToken { // // String tokenValue // String username //} //use cache as storage grails.plugin.springsecurity.rest.token.storage.useGrailsCache=true grails.plugin.springsecurity.rest.token.storage.grailsCacheName='xauth-token' //token rendering grails.plugin.springsecurity.rest.token.rendering.usernamePropertyName='username' grails.plugin.springsecurity.rest.token.rendering.authoritiesPropertyName='roles' grails.plugin.springsecurity.rest.token.rendering.tokenPropertyName='token' //token validate grails.plugin.springsecurity.rest.token.validation.useBearerToken = true //if disable 'Bearer', you can configure a custom header. //grails.plugin.springsecurity.rest.token.validation.useBearerToken = false //grails.plugin.springsecurity.rest.token.rendering.tokenPropertyName access_token //grails.plugin.springsecurity.rest.token.validation.headerName = 'x-auth-token' grails.plugin.springsecurity.rest.token.validation.active=true grails.plugin.springsecurity.rest.token.validation.endpointUrl='/api/validate' grails{ plugin{ springsecurity{ filterChain{ chainMap = [ '/api/guest/**': 'anonymousAuthenticationFilter,restTokenValidationFilter,restExceptionTranslationFilter,filterInvocationInterceptor', '/api/**': 'JOINED_FILTERS,-exceptionTranslationFilter,-authenticationProcessingFilter,-securityContextPersistenceFilter', // Stateless chain '/**': 'JOINED_FILTERS,-restTokenValidationFilter,-restExceptionTranslationFilter' // Traditional chain ] } rest { token { validation { enableAnonymousAccess = true } } } } } }
Configure CORS
By default there is a CORS plugin included as a dependency of Spring security REST Plugin.Of course, you can declare it in
BuildConfig.groovy
file explicitly.runtime ":cors:1.1.6"Add the following configuration in
Config.groovy
file.//cors config. cors.enabled=true cors.url.pattern = '/api/*' cors.headers=[ 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Credentials': true, 'Access-Control-Allow-Headers': 'origin, authorization, accept, content-type, x-requested-with', 'Access-Control-Allow-Methods': 'GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS', 'Access-Control-Max-Age': 3600 ]
Update frontend codes
Due to the modification of the backend codes, you could have to change the authentication in the frontend codes.Change the login code fragment in the
app.js
file.$http.post(apiUrl+'/login', {username: username, password: password}) .success(function(user){ console.log('logged in successfully!') $rootScope.user = user; $http.defaults.headers.common['Authorization'] = 'Bearer '+user.token; $cookieStore.put('user', user); $rootScope.$broadcast('event:loginConfirmed'); });
Run the project
-
I have committed the codes into my github account. Clone it into your system.
git clone https://github.com/hantsy/angularjs-grails-sample
-
Run the backend application. Go to the
server
folder, and execute the following command to start up the Grails application which works as a REST producer.
grails run-app
-
Run the frontend application. Go to the
client
folder, and run the following to serve the frontend application.
node scripts\web-server.js
- Open your favorite browser and navigate http://localhost:8000/app.
评论