Grails Part 5 - Adding Basic Security
Click here to view the full tutorial
Continuing series: Developing a Grails Web Application.
Tutorial will: walk through steps of creating a robust Grails web application.
Application name:
The Goal: To track and record persons addresses.
A useful command
As in the springsource blog, we will create domain classes with names: SecUser and SecRole.
Also generated:
There are three ways you can configure security.
The Rules:
1. Any authenticated user has access to the Person Index
2. Only Admin's can create/update/delete Persons or Addresses
To enable, set the securityConfigType and add interceptUrlMap Configurations to the
Optional security configurations:
Now configure two users; one with admin privilege and, one with default user privilege.
We are going to use the security tag lib, to hide edit/create options on the
To view a list of tags and their explanations see the Grails SecurityTagLib Documentation.
Go ahead and open up the view
Wrap the Create New Person link like so:
And now the table data containing the options column, along with the button group:
My
And the denied.gsp:
The application is now setup with basic spring security.
You can find a list of additional plugins with advanced configurations, on the spring security plugin page.
Click here to view the full tutorial
Tutorial will: walk through steps of creating a robust Grails web application.
Application name:
grails-mongo-demo
The Goal: To track and record persons addresses.
This application will use the Grails Framework to develop a web application using:View Project on Github
1.MongoDB
2.Spring Security
3.Apache CXF
4.Jetty Web Server
5.
Maven build integration=> Removed upon Request
Previous Post: Grails Part 4 - Enhanced UI Design w/ tw Bootstrap
These Instructions Will Walk Through:
- Configuring Spring Security Plugin
- Adding static URL maps
- Bootstrapping in security data
- SecurityTagLib - Conditionally display gsp content
- Configure Security Pages with Twitter Bootstrap UI
$ git clone https://github.com/keaplogik/grails-mongodb-demo.git
$ cd grails-mongodb-demo/
$ git checkout v1.0
1. Configuring Spring Security Plugin
To start, ensure you have the spring-security-core plugin installed. If not, add it to your POM if using maven, otherwise add it to the dependency list of theBuildConfig
class. If following along, with the grails-mongodb-demo, you will already have it installed.A useful command
s2-quickstart
is built into the security plugin. It generates the controllers to handle authentication, as well the domain classes you'll need to store user information. As in the springsource blog, we will create domain classes with names: SecUser and SecRole.
Also generated:
-
SecUserSecRole
- links users to roles. LoginController
LogoutController
- Associated login/logout views
$ grails s2-quickstart org.mycompany SecUser SecRole
The application now needs to specify mappings to the login/logout controllers. Add the following to the configuration class UrlMappings
: "/login/$action?"(controller: "login")
"/logout/$action?"(controller: "logout")
You can take a controller-centric approach and annotate the actions; work with static URL rules in Config.groovy; or define runtime rules in the database using request maps.
Consult the springsource blog post Simplified Spring Security with Grails for more information.
2. Adding static URL maps
For the grails-mongodb-demo, we will secure the application using static URL rules.The Rules:
1. Any authenticated user has access to the Person Index
2. Only Admin's can create/update/delete Persons or Addresses
To enable, set the securityConfigType and add interceptUrlMap Configurations to the
Config.groovy
class:grails.plugins.springsecurity.securityConfigType = 'InterceptUrlMap'
grails.plugins.springsecurity.interceptUrlMap = [
'/person/index': ['ROLE_USER, ROLE_ADMIN, IS_AUTHENTICATED_FULLY'],
'/person/**': ['ROLE_ADMIN'],
'/address/**': ['ROLE_ADMIN'],
'/js/**': ['IS_AUTHENTICATED_ANONYMOUSLY'],
'/css/**': ['IS_AUTHENTICATED_ANONYMOUSLY'],
'/images/**': ['IS_AUTHENTICATED_ANONYMOUSLY'],
'/*': ['IS_AUTHENTICATED_FULLY'],
'/login/**': ['IS_AUTHENTICATED_ANONYMOUSLY'],
'/logout/**': ['IS_AUTHENTICATED_ANONYMOUSLY']
]
grails.plugins.springsecurity.password.algorithm='SHA-512' //pw encryption algorithm
grails.plugins.springsecurity.portMapper.httpPort = "8080" //port map for http
grails.plugins.springsecurity.portMapper.httpsPort = "8443" //port map for https
grails.plugins.springsecurity.rejectIfNoRule = true //force authentication if no rule exists
3. Bootstrap in security data
Our application needs to determine who has access to what URL. Because of this, we need to create a set of rules. They only need to be created once on application start, so lets useBootstrap
to create them.class BootStrap {
def init = {
...
def userRole = SecRole.findByAuthority('ROLE_USER') ?: new SecRole(authority: 'ROLE_USER').save(failOnError: true)
def adminRole = SecRole.findByAuthority('ROLE_ADMIN') ?: new SecRole(authority: 'ROLE_ADMIN').save(failOnError: true)
...
}
}
- Admin User {u/p}: {admin/admin}
- Default User {u/p}: {guest/guest}
Bootstrap.init{...}
, add persistence for the default users : //add an admin and default user
def adminUser = SecUser.findByUsername('admin') ?: new SecUser(
username: 'admin',
password: 'admin',
enabled: true).save(failOnError: true)
def basicUser = SecUser.findByUsername('guest') ?: new SecUser(
username: 'guest',
password: 'guest', //pw encoded by security plugin
enabled: true).save(failOnError: true)
if (!adminUser.authorities.contains(adminRole)) {
SecUserSecRole.create adminUser, adminRole
}
if (!basicUser.authorities.contains(userRole)) {
SecUserSecRole.create basicUser, userRole
}
4. SecurityTagLib - Conditionally display gsp content
The security tags are part of thesec
namespace, and can be used in your gsp's. Heres an example:<sec:ifLoggedIn>
<p>Your Logged in!</p>
</sec:ifLoggedIn>
person/index
page. Specifically the condition will check if a user has the role: ROLE_ADMIN: <sec:ifAllGranted roles="ROLE_ADMIN">hide this stuff</sec:ifAllGranted>
Go ahead and open up the view
grails-mongodb-demo/grails-app/views/person/index.gsp
.Wrap the Create New Person link like so:
<sec:ifAllGranted roles="ROLE_ADMIN">
<g:link class="btn btn-block btn-link" action="create">
Create New Person
</g:link>
</sec:ifAllGranted>
<sec:ifAllGranted roles="ROLE_ADMIN">
<th>Options</th>
</sec:ifAllGranted>
...
<sec:ifAllGranted roles="ROLE_ADMIN">
<td><g:link class="btn btn-small btn-inverse" controller="address"
action="edit" id="${address.id}">
<i class="icon-edit icon-white"></i>
</g:link>
</td>
...
<sec:ifAllGranted roles="ROLE_ADMIN">
<div class="btn-group">
<g:link class="btn btn-primary" action="edit" id="${person.id}">
<i class="icon-edit icon-white"></i>Edit
</g:link>
</div>
</sec:ifAllGranted>
</sec:ifAllGranted>
5. Configure Security Pages with Bootstrap UI
We want to give the user an option to log out from any screen. Let's use a static navbar in our/layouts/main.gsp
:<body>
<div class="navbar navbar-static-top">
<div class="navbar-inner">
<div class="container">
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<g:link class="brand" uri="/">Address Tracker</g:link>
<div class="nav-collapse">
<ul class="nav pull-right">
<sec:ifLoggedIn>
<li>
<g:link controller="logout" action="index">Logout</g:link>
</li>
</sec:ifLoggedIn>
</ul>
</div>
</div>
</div>
</div>
<g:layoutBody/>
...
auth.gsp
page configured with twitter bootstrap is below, but you can modify yours however.<html>
<head>
<meta name='layout' content='main'/>
<r:require modules="bootstrap"/>
<title><g:message code="springSecurity.login.title"/></title>
</head>
<body>
<div class='container'>
<g:if test='${flash.message}'>
<div class='alert alert-error'>${flash.message}</div>
</g:if>
<div class="row span12">
<legend><g:message code="springSecurity.login.header"/></legend>
<div class="span6">
<form action='${postUrl}' method='POST' id='loginForm' class='form-horizontal' autocomplete='off'>
<div class="control-group">
<label class="control-label" for='username'><g:message code="springSecurity.login.username.label"/>:</label>
<div class="controls">
<input type='text' class='text_' name='j_username' id='username'/>
</div>
</div>
<div class="control-group">
<label class="control-label" for='password'><g:message code="springSecurity.login.password.label"/>:</label>
<div class="controls">
<input type='password' class='text_' name='j_password' id='password'/>
</div>
</div>
<div class="control-group" id="remember_me_holder">
<div class="controls">
<label class="checkbox" for='remember_me'><g:message code="springSecurity.login.remember.me.label"/>
<input type='checkbox' name='${rememberMeParameter}' id='remember_me'
<g:if test='${hasCookie}'>checked='checked'</g:if>/>
</label>
<input class="btn btn-primary" type='submit' id="submit" value='${message(code: "springSecurity.login.button")}'/>
</div>
</div>
</form>
</div>
<div class="span4">
<div class="">
<dl class="dl-horizontal">
<dt>Admin User (u/p):</dt>
<dd>admin/admin</dd>
</dl>
<dl class="dl-horizontal">
<dt>Guest User (u/p):</dt>
<dd>guest/guest</dd>
</dl>
</div>
</div>
</div>
</div>
</body>
</html>
<head>
<meta name='layout' content='main' />
<r:require modules="bootstrap"/>
<title><g:message code="springSecurity.denied.title" /></title>
</head>
<body>
<div class='container'>
<div class='alert alert-block alert-error'>
<g:message code="springSecurity.denied.message" />
<br/><br/>
<g:link class="btn btn-inverse" uri="/">Return Home</g:link>
</div>
</div>
</body>
You can find a list of additional plugins with advanced configurations, on the spring security plugin page.
Click here to view the full tutorial
When a service is exposed as soap by using cxf, can that be secured in a way?
ReplyDelete