grails 之 Spring Security Core Plugin 使用
2012-09-01 10:33
573 查看
Spring Security Core Plugin是Spring的一个强大的权限控制插件,Secure your applications using the powerful Spring Security library quickly and easily
官方插件地址:http://www.grails.org/plugin/spring-security-core
官方使用手册:http://grails-plugins.github.com/grails-spring-security-core/docs/manual/
在grails项目中插入Spring Security Core Plugin。
这时系统就会自动插入插件,插入插件后就可开始配置使用spring security Core插件了
详细使用如下,原文地址:http://grails-plugins.github.com/grails-spring-security-core/docs/manual/guide/23%20Tutorials.html#23.1%20Using%20Controller%20Annotations%20to%20Secure%20URLs
You can choose your names for your domain classes and package; these are just examples.
Depending on your database, some domain class names might not be valid, especially those relating to security. Before you create names like "User" or "Group", make sure they are not reserved keywords in your database.
The script creates this User class:
Earlier versions of the plugin didn't include password encryption logic in the domain class, but it makes the code a lot cleaner.
and this Role class:
and a domain class that maps the many-to-many join class,
It also creates some UI controllers and GSPs:
The script has edited
These generated files are not part of the plugin - these are your application files. They are examples to get you started, so you can edit them as you please. They contain the minimum needed for the plugin.
The plugin has no support for CRUD actions and GSPs for your domain classes; the
(See step 7.)
This command creates
Some things to note about the preceding
The example does not use a traditional GORM many-to-many mapping for the User<->Role relationship; instead you are mapping the join table with the
This performance optimization helps significantly when many users have one or more common roles.
We explicitly flushed the creates because
You can annotate the entire controller or individual actions. In this case you have only one action, so you can do either.
This time, you should be presented with the login page. Log in with the username and password you used for the test user, and you should again be able to see the secure page.
Check the checkbox, and once you've tested the secure page, close your browser and reopen it. Navigate again the the secure page. Because a is cookie stored, you should not need to log in again. Logout at any time by navigating to http://localhost:8080/bookstore/logout.
Run grails generate-all for the domain classes:
Since the User domain class handles password encryption, there are no changes required in the generated controllers.
In this tutorial we'll discuss the general steps required to migrate from the Acegi plugin to the Spring Security Core plugin. A lot of the material here comes from an
email that Lubos Pochman sent to the User mailing list documenting the steps he took to upgrade from the Acegi plugin.
This isn't a standard step-by-step tutorial since every application is different and the steps required will vary from project to project. Instead these are guidelines and things to keep in mind. You should also readSection
2 and Section 3.
The first thing to do is uninstall the Acegi plugin
and install Spring Security Core
If this were a new project the next step would be to run the s2-quickstart script
but you wouldn't do this for an existing project where you already have a User and Role class, so it's a good idea to work through thebookstore
tutorial and use the files generated in that project. The files that the script generates are
Migrate any changes you made in
and overwrite your files with those. Do the same for
your project.
You can use the standard Grails
Security UI plugin.
The utility service in Spring Security Core is
removed; use
and
One significant change between the plugins is that the
has a reference to the domain class instance. This was intended to make it easy to access User class data that's not available in the
due to being a disconnected Hibernate object. Instead
use this instead:
The Acegi plugin uses a standard Grails many-to-many relationship (i.e. using
between User and Role but this will have performance problems if you have many users. Spring Security Core also uses a many-to-many relationship but maps the join table as a domain class instead of using collections. In the Acegi plugin you would grant a role
to a user using
and remove the grant with
In Spring Security Core you use the helper methods in
and
which directly insert or delete rows in the User/Role join table.
Configuration settings are now stored in
environment-specific security settings. Migrate settings from
summary for the new names.
In particular it's important that the following properties be configured (replace class and package names to match your domain classes):
Delete
The
Consider using SpEL
expressions since they're a lot more powerful and expressive than simple role names.
tag names now start with 'if' instead of 'is', and the
so for example change
use
use
在Grails项目的Config.groovy中配置如下配置
到这一步,基础建设基本完成了,接下来可以开始建设对应的controller进行权限访问了。
对用的controller代码
LoginControoler
auth.gsp
LoginOutControoler
官方插件地址:http://www.grails.org/plugin/spring-security-core
官方使用手册:http://grails-plugins.github.com/grails-spring-security-core/docs/manual/
在grails项目中插入Spring Security Core Plugin。
grails install-plugin spring-security-core如果你使用intellij IDEA的话就可以很简单的插入插件了,如下图
这时系统就会自动插入插件,插入插件后就可开始配置使用spring security Core插件了
详细使用如下,原文地址:http://grails-plugins.github.com/grails-spring-security-core/docs/manual/guide/23%20Tutorials.html#23.1%20Using%20Controller%20Annotations%20to%20Secure%20URLs
23 Tutorials
23.1 Using Controller Annotations to Secure URLs
1. Create your Grails application.
$ grails create-app bookstore $ cd bookstore
2. Install the plugin.
$ grails install-plugin spring-security-core
3. Create the User and Role domain classes.
$ grails s2-quickstart com.testapp User Role
You can choose your names for your domain classes and package; these are just examples.
Depending on your database, some domain class names might not be valid, especially those relating to security. Before you create names like "User" or "Group", make sure they are not reserved keywords in your database.
The script creates this User class:
package com.testapppackage testclass User { transient springSecurityService String username String password boolean enabled boolean accountExpired boolean accountLocked boolean passwordExpired static constraints = { username blank: false, unique: true password blank: false } static mapping = { password column: '`password`' } Set<Role> getAuthorities() { UserRole.findAllByUser(this).collect { it.role } as Set } def beforeInsert() { encodePassword() } def beforeUpdate() { if (isDirty('password')) { encodePassword() } } protected void encodePassword() { password = springSecurityService.encodePassword(password) } }
Earlier versions of the plugin didn't include password encryption logic in the domain class, but it makes the code a lot cleaner.
and this Role class:
package com.testappclass Role { String authority static mapping = { cache true } static constraints = { authority blank: false, unique: true } }
and a domain class that maps the many-to-many join class,
UserRole:
package com.testappimport org.apache.commons.lang.builder.HashCodeBuilderclass UserRole implements Serializable { User user Role role boolean equals(other) { if (!(other instanceof UserRole)) { return false } other.user?.id == user?.id && other.role?.id == role?.id } int hashCode() { def builder = new HashCodeBuilder() if (user) builder.append(user.id) if (role) builder.append(role.id) builder.toHashCode() } static UserRole get(long userId, long roleId) { find 'from UserRole where user.id=:userId and role.id=:roleId', [userId: userId, roleId: roleId] } static UserRole create(User user, Role role, boolean flush = false) { new UserRole(user: user, role: role).save(flush: flush, insert: true) } static boolean remove(User user, Role role, boolean flush = false) { UserRole instance = UserRole.findByUserAndRole(user, role) if (!instance) { return false } instance.delete(flush: flush) true } static void removeAll(User user) { executeUpdate 'DELETE FROM UserRole WHERE user=:user', [user: user] } static mapping = { id composite: ['role', 'user'] version false } }
It also creates some UI controllers and GSPs:
grails-app/controllers/LoginController.groovy
grails-app/controllers/LogoutController.groovy
grails-app/views/auth.gsp
grails-app/views/denied.gsp
The script has edited
grails-app/conf/Config.groovyand added the configuration for your domain classes. Make sure that the changes are correct.
These generated files are not part of the plugin - these are your application files. They are examples to get you started, so you can edit them as you please. They contain the minimum needed for the plugin.
The plugin has no support for CRUD actions and GSPs for your domain classes; the
spring-security-uiplugin will supply a UI for those. So for now you will create roles and users in
grails-app/conf/BootStrap.groovy.
(See step 7.)
4. Create a controller that will be restricted by role.
$ grails create-controller com.testapp.Secure
This command creates
grails-app/controllers/com/testapp/ SecureController.groovy. Add some output so you can verify that things are working:
package com.testappclass SecureController { def index = { render 'Secure access only' } }
5. Start the server.
$ grails run-app
6. Before you secure the page, navigate to http://localhost:8080/bookstore/secure to verify that you can see the page without being logged
in.
7. Shut down the app (using CTRL-C) and edit grails-app/conf/BootStrap.groovy to add the security objects that you need.
import com.testapp.Role import com.testapp.User import com.testapp.UserRoleclass BootStrap { def init = { servletContext -> def adminRole = new Role(authority: 'ROLE_ADMIN').save(flush: true) def userRole = new Role(authority: 'ROLE_USER').save(flush: true) def testUser = new User(username: 'me', enabled: true, password: 'password') testUser.save(flush: true) UserRole.create testUser, adminRole, true assert User.count() == 1 assert Role.count() == 2 assert UserRole.count() == 1 } }
Some things to note about the preceding
BootStrap.groovy:
The example does not use a traditional GORM many-to-many mapping for the User<->Role relationship; instead you are mapping the join table with the
UserRoleclass.
This performance optimization helps significantly when many users have one or more common roles.
We explicitly flushed the creates because
BootStrapdoes not run in a transaction or OpenSessionInView.
8. Edit grails-app/controllers/SecureController.groovy to import the annotation class and apply the annotation to restrict access.
package com.testappimport grails.plugins.springsecurity.Securedclass SecureController { @Secured(['ROLE_ADMIN']) def index = { render 'Secure access only' } }
You can annotate the entire controller or individual actions. In this case you have only one action, so you can do either.
9. Run grails run-app again and navigate to http://localhost:8080/bookstore/secure.
This time, you should be presented with the login page. Log in with the username and password you used for the test user, and you should again be able to see the secure page.
10. Test the Remember Me functionality.
Check the checkbox, and once you've tested the secure page, close your browser and reopen it. Navigate again the the secure page. Because a is cookie stored, you should not need to log in again. Logout at any time by navigating to http://localhost:8080/bookstore/logout.
11. Optionally, create a CRUD UI to work with users and roles.
Run grails generate-all for the domain classes:
$ grails generate-all com.testapp.User
$ grails generate-all com.testapp.Role
Since the User domain class handles password encryption, there are no changes required in the generated controllers.
23.2 Migration From the Acegi Plugin
In this tutorial we'll discuss the general steps required to migrate from the Acegi plugin to the Spring Security Core plugin. A lot of the material here comes from anemail that Lubos Pochman sent to the User mailing list documenting the steps he took to upgrade from the Acegi plugin.
This isn't a standard step-by-step tutorial since every application is different and the steps required will vary from project to project. Instead these are guidelines and things to keep in mind. You should also readSection
2 and Section 3.
The first thing to do is uninstall the Acegi plugin
$ grails uninstall-plugin acegi
and install Spring Security Core
$ grails install-plugin spring-security-core
If this were a new project the next step would be to run the s2-quickstart script
but you wouldn't do this for an existing project where you already have a User and Role class, so it's a good idea to work through thebookstore
tutorial and use the files generated in that project. The files that the script generates are
grails-app/domain/com/testapp/User.groovy
grails-app/domain/com/testapp/Role.groovy
grails-app/domain/com/testapp/UserRole.groovy
grails-app/controllers/LoginController.groovy
grails-app/controllers/LogoutController.groovy
grails-app/views/login/auth.gsp
grails-app/views/login/denied.gsp
Migrate any changes you made in
LoginController.groovy,
LogoutController.groovy,
auth.gspand
denied.gsp,
and overwrite your files with those. Do the same for
User.groovyand
Role.groovy, and move
UserRole.groovyinto
your project.
User and Role UI
You can use the standard Grails generate-allscript to create a UI to manage Users and Roles as described in the previous tutorial, or for a more complete solution use the Spring
Security UI plugin.
authenticateService
The utility service in Spring Security Core is SpringSecurityService, so you need to replace
def authenticateServicewith
def springSecurityService. Many of the methods have the same names and signatures but there are some differences:
principal()was renamed to
getPrincipal()
ifAllGranted(),
ifNotGranted(), and
ifAnyGranted()were
removed; use
org.codehaus.groovy.grails.plugins.springsecurity. SpringSecurityUtils.ifAllGranted(),
ifNotGranted(),
and
ifAnyGranted()instead
getSecurityConfig()was removed, use
SpringSecurityUtils.getSecurityConfig()instead
One significant change between the plugins is that the
UserDetailsimplementation (
GrailsUser) no longer
has a reference to the domain class instance. This was intended to make it easy to access User class data that's not available in the
Principalbut it has frustrating side effects
due to being a disconnected Hibernate object. Instead
GrailsUserstores the user's id so you can conveniently retrieve the instance when needed. So instead of
def user = authenticateService.userDomain() user = User.get(user.id)
use this instead:
def user = User.get(springSecurityService.principal.id)
Role granting
The Acegi plugin uses a standard Grails many-to-many relationship (i.e. using hasManyand
belongsTo)
between User and Role but this will have performance problems if you have many users. Spring Security Core also uses a many-to-many relationship but maps the join table as a domain class instead of using collections. In the Acegi plugin you would grant a role
to a user using
Role role = … User user = … role.addToPeople(user)
and remove the grant with
Role role = … User user = … role.removeFromPeople(user)
In Spring Security Core you use the helper methods in
UserRole
Role role = … User user = … UserRole.create user, role
and
Role role = … User user = … UserRole.remove user, role
which directly insert or delete rows in the User/Role join table.
SecurityConfig.groovy
Configuration settings are now stored in grails-app/conf/Config.groovyalong with the rest of the application configuration. The primary motiviation for this change is to easily support
environment-specific security settings. Migrate settings from
SecurityConfig.groovyto
Config.groovy(see this
summary for the new names.
In particular it's important that the following properties be configured (replace class and package names to match your domain classes):
grails. plugins. springsecurity. userLookup. userDomainClassName = 'com.yourcompany.yourapp.User' grails. plugins. springsecurity. userLookup. authorityJoinClassName = 'com.yourcompany.yourapp.UserRole' grails. plugins. springsecurity. authority. className = 'com.yourcompany.yourapp.Role'
Delete
SecurityConfig.groovywhen you're finished.
Controller annotations
The Securedannotation changed from
org.codehaus.groovy.grails.plugins. springsecurity.Securedto
grails.plugins.springsecurity.Secured.
Consider using SpEL
expressions since they're a lot more powerful and expressive than simple role names.
Security tags
tag names now start with 'if' instead of 'is', and the roleattribute changed to
roles,
so for example change
<g:ifAnyGranted role='...'>to
<sec:ifAnyGranted roles='...'>
use
<sec:username/>instead of
<g:loggedInUserInfo(field:'username')}/>-
use
<sec:loggedInUserInfo>to render other
GrailsUserattributes
在Grails项目的Config.groovy中配置如下配置
grails { plugins { springsecurity { active = true userLookup.userDomainClassName = "com.testapp.User" authority.className = "com.testapp.Role" } } }
到这一步,基础建设基本完成了,接下来可以开始建设对应的controller进行权限访问了。
对用的controller代码
LoginControoler
def auth = { nocache response if (isLoggedIn()) { redirect uri: '/' return } String view = 'auth' String postUrl = "${request.contextPath}${SpringSecurityUtils.securityConfig.apf.filterProcessesUrl}" render view: view, model: [postUrl: postUrl] }
auth.gsp
<form action='${postUrl}' method='POST' id='loginForm' class='cssform'> <p> <label class="required" for="j_username">用户名:</label><br/> <input type='text' class='text_' name='j_username' id='j_username' value='${request.remoteUser}'/> </p> <p> <label class="required" for="j_password">密码:</label><br/> <input type='password' class='text_' name='j_password' id='j_password'/> </p> <p> </p> <p> <table width="100%" border="0" cellspacing="0" cellpadding="0"> <tr> <td width="100%"><input type="submit" value="登录"/></td> </tr> </table> </p> </form>
LoginOutControoler
def denied = { // TODO put any pre-logout code here redirect(uri: '/j_spring_security_logout') }
相关文章推荐
- Grails 之 Acegi Plugin 转移到Spring Security Core Plugin
- grails之spring-security-core自定义加密方式
- Spring-Security-core插件使用教程
- Spring Security Core Plugin - 5. 配置到安全URL的请求映射
- Spring-Security-core插件使用教程
- Grails, spring-security-core plugin:使用email登录
- red hat linux使用yum 出现Loaded plugins: rhnplugin, security
- dbunit-spring-test和maven-dbunit-plugin使用
- SpringBoot + Spring Security 基本使用及个性化登录配置详解
- Spring security 命名空间的使用
- spring boot中使用security样例抛异常,Circular view path跳转失败
- 手把手教你使用spring cloud+dotnet core搭建微服务架构:服务治理(-)
- [C#] .NET Core/Standard 1.X 项目中如何使用XmlIgnoreAttribute等标准范围外的内容,兼谈如何解决“violation of security transparency rules failed”(违反安全透明规则失败)异常
- Struts2和Spring整合时使用Struts-plugin的注意点
- 使用Spring-Security进行登录控制的session问题
- Spring boot 使用restful风格的spring security login
- org.springframework.jdbc.core.JdbcTemplate 使用注意事项
- 详解使用Spring Security OAuth 实现OAuth 2.0 授权
- Spring3学习笔记之(spring core之DI配置使用2)
- 使用Spring-security3.0 框架