Spring Security Grails plugin. Quick start and some tips
Spring Security plugin is a fast and convenient solution for authorizing
user access. Almost every Grails web application uses it. In this
article I would like to provide a guide about how to apply this solution
quickly, and show you some tips that should be really useful for
beginners.
So let’s download the plugin.
grails install-plugin spring-security-core
Install output tells us "Next run the "s2-quickstart" script to
initialize Spring Security and create your domain classes.". If you
haven’t used this plugin before I strongly recommend you to run the
script. Classes that will be generated by the script will have some
properties and methods that are necessary or strongly recommended for
running the application powered by Spring Security. Actually, if you
know that in your application should be such feature as authorized user
access, you should run the script before constructing the domain model,
just trust my experience - this will save you a lot of time.
When you will run the script, it will ask you to run it with the
specification of the classes names that should be generated, so it could
generate domain User class, User’s Roles class and the User/Role
many-to-many join class. Also, script optionally offers to enter request
map class name, if you are beginner, let’s just move on, don’t worry
about the case if you will need it later, it’s easy to configure it by
yourself, we’ll get to that. Finally, let’s run the following command:
s2-quickstart com.sysgears.example User Role. Notice, that script also
generated controllers Login and Logout and the auth and denied GSP
pages. Auth is a user’s login page and denied is a page that will be
shown to user in case if he will try to access urls, to which he has no
access rights. The script will also add following lines to your
Config.groovy file:
If you want to look at all the properties that could be configured here
and their detailed description, please read
appropriate documentation section. Now let’s get to adding the
access control. There are three ways to authorize access with the Spring
Security tools. These ways are to use @Secured annotations, intercept
URL map and the request map. Brief description of the first two tools
usage you may find at one of my previous posts:
https://sysgears.com/articles/filtering-user-access-grails So also we
should talk about the request map. Basically it is the same tool as
intercept URL map. The only difference is that you may change or add
access configurations without the need of restarting the application,
and if you are not gonna use this feature, there is no need to use
request map. Anyway here is the example of usage. To use the request map
tool, in the Config.groovy file add the following code:
You will notice, that configuring is pretty similar to the intercept URL
map config type:
new SecurityMap(url: '/js/**', configAttribute: 'IS_AUTHENTICATED_ANONYMOUSLY').save(flush:true)
new SecurityMap(url: '/css/**', configAttribute: 'IS_AUTHENTICATED_ANONYMOUSLY').save(flush:true)
new SecurityMap(url: '/images/**', configAttribute: 'IS_AUTHENTICATED_ANONYMOUSLY').save(flush:true)
new SecurityMap(url: '/login/**', configAttribute: 'IS_AUTHENTICATED_ANONYMOUSLY').save(flush:true)
new SecurityMap(url: '/logout/**', configAttribute: 'IS_AUTHENTICATED_ANONYMOUSLY').save(flush:true)
new SecurityMap(url: '/favicon.ico', configAttribute: 'IS_AUTHENTICATED_ANONYMOUSLY').save(flush:true)
new SecurityMap(url: '/admin/**', configAttribute: 'ROLE_ADMIN').save(flush:true)
new SecurityMap(url: '/*/**', configAttribute: 'ROLE_ADMIN, ROLE_USER').save(flush:true)
Spring security plugin also has a bunch of helper tools that should be
really helpful for your app. Controllers and services will often use the
Spring Security Service. For example, one of the most common usages is
to get username of current user, it can be done this way:
springSecurityService.authentication.name Another common usage is to
execute the code depending on whether user logged in or not.
Another great helpers from the Spring Security plugin are taglibs. They
are used when you need to restrict the access to some information
directly at the GSP pages. In my applications I have a lot of this kind
of usages:
<sec:ifLoggedIn>You are logged in as ${user.username}</sec: ifLoggedIn>
<sec:ifAnyGrantedroles="ROLE_ADMIN">Some admin info</sec:ifAnyGranted><sec:ifNotLoggedIn><g:linkcontroller="login"action='index'>Login</g:link><g:linkcontroller="register"action='index'>Sign Up</g:link></sec:ifNotLoggedIn>
Sure, the text inside the tags is included to the page only if condition
specified in the tag is true. There are also a lot of stuff that will
help you to develop Spring Security powered application, for the full
information about, please read the
appropriate documentation section.
When you will get your configured app to work you may run into this
problem. When user will login to the application, he may receive an
error: "HTTP Status 404. The requested resource (/favicon.ico) is not
available." To fix this you should specify
'ISAUTHENTICATEDANONYMOUSLY' rights for the URL ‘/favicon.ico’.
Here is the detailed explanation of this issue.
The feature you may need to implement in your application immediately
without the detailed learning of the documentation is to use not only
username for user login. For example, it would be nice to give user the
ability to login using email. You may implement this feature this way:
create a service that will implement GrailsUserDetailsService interface
and include it to the Spring resources. Add the following code to the
conf/spring/resources.groovy:
classCustomUserDetailsServiceimplementsGrailsUserDetailsService{/** * Some Spring Security classes (e.g. RoleHierarchyVoter) expect at least one role, so * we give a user with no granted roles this one which gets past that restriction but * doesn't grant anything. */staticfinalListNO_ROLES=[newGrantedAuthorityImpl(SpringSecurityUtils.NO_ROLE)]UserDetailsloadUserByUsername(Stringusername,booleanloadRoles)throwsUsernameNotFoundException{returnloadUserByUsername(username)}UserDetailsloadUserByUsername(Stringusername)throwsUsernameNotFoundException{User.withTransaction{status->Useruser=User.findByUsernameOrEmail(username,username)if(!user){thrownewUsernameNotFoundException('User not found',username)}defauthorities=user.authorities.collect{newGrantedAuthorityImpl(it.authority)}returnnewGrailsUser(user.username,user.password,user.enabled,!user.accountExpired,!user.passwordExpired,!user.accountLocked,authorities?:NO_ROLES,user.id)}}}
Hope this quickstart guide was helpful for you, for more info please
read the
documentation.
No comments:
Post a Comment