作者: 伯特·貝克威思,貝弗利塔爾博特
版本: 1.2.7.3
1. 創建Grails應用程序
$ grails create-app bookstore
$ cd bookstore
2. 安裝該插件
$ grails install-plugin spring-security-core
3. 創建User和 Role 領域類。
$ grails s2-quickstart com.testapp User Role
You can choose your names for your domain classes and package; these arejust examples.
依據你的數據庫,有些領域類的命名可能會受到限制, 尤其是那些與安全相關的。在創建諸如 "User"或者 "Group"爲名的領域類之前, 請確認它們在你的數據庫中不是被保護的關鍵字。
腳本自動創建了User類:
package com.testapp
package test
class 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)
}
}
早期版本的插件沒有包括密碼加密邏輯的域類,但代碼很乾淨。
Role類也是腳本自動創建:
package com.testapp
class Role {
String authority
static mapping = {
cache true
}
static constraints = {
authority blank: false, unique: true
}
}
還創建了一個UserRole領域類來映射 many-to-many 連接類:
package com.testapp
import org.apache.commons.lang.builder.HashCodeBuilder
class UserRole implements Serializable {
User user
Role role
boolean equals(other) {
if (!(other instanceof UserRole)) {
returnfalse
}
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 whereuser.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)
}
staticboolean remove(User user, Role role, boolean flush = false) {
UserRole instance =UserRole.findByUserAndRole(user, role)
if (!instance) {
returnfalse
}
instance.delete(flush: flush)
true
}
static void removeAll(User user) {
executeUpdate 'DELETE FROMUserRole WHERE user=:user', [user: user]
}
static mapping = {
id composite: ['role', 'user']
version false
}
}
還自動創建了幾個 UI 控制器和 GSP頁面:
· grails-app/controllers/LoginController.groovy
· grails-app/controllers/LogoutController.groovy
· grails-app/views/auth.gsp
· grails-app/views/denied.gsp
腳本還編輯了grails-app/conf/Config.groovy ,爲生成的領域類添加了一些配置,請確認這些修改是正確的。
這些自動生成的文件並不是插件的一部分 –它們都是你的應用程序文件。它們幫助你開始,所以你可以按照自己的喜好去修改。它們包含了插件的最低需求。
插件不支持對所生成領域類的 CRUD 動作和 GSP頁面;spring-security-ui插件 會爲這些提供一個UI。現在你需要在grails-app/conf/BootStrap.groovy中預置一些用戶和角色 (參看第7步)。
4. 創建一個被role限制使用的控制器
$ grails create-controller com.testapp.Secure
這行命令在創建一個控制器類:grails-app/controllers/com/testapp/SecureController.groovy。添加一些輸出內容可以驗證控制器工作是否正常。
package com.testapp
class SecureController {
def index = {
render 'Secure access only'
}
}
5. 啓動服務
$ grails run-app
6. 導航到http://localhost:8080/bookstore/secure, 在進入secure頁面之前 你看不到登陸頁面。
7. 停止服務,編輯 grails-app/conf/BootStrap.groovy 文件,添加你需要的安全部件。
import com.testapp.Role
import com.testapp.User
import com.testapp.UserRole
class 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
}
}
在上述的BootStrap.groovy中需要注意一些事情:
· 本例中沒有使用傳統的GORMmany-to-many 映射User<->Role 關係; 插入了一個映射連接表UserRole類。 當多個用戶有一個或多個共同的角色時,這樣做對性能的優化比較明顯。
· 我們顯式刷新創建,因爲 BootStrap 沒有在事務和OpenSessionInView中運行。
8.編輯grails-app/controllers/SecureController.groovy 倒入註解類並應用註解限制訪問。
package com.testapp
import grails.plugins.springsecurity.Secured
class SecureController {
@Secured(['ROLE_ADMIN'])
def index = {
render 'Secure access only'
}
}
或者
package com.testapp
import grails.plugins.springsecurity.Secured
@Secured(['ROLE_ADMIN'])
class SecureController {
def index = {
render 'Secure access only'
}
}
你可以對控制器標註,也可以對其中的方法進行標註。在這裏你只有一個方法,所以標註在哪裏都可以。
9. 再次運行 grails run-app again 並導航到http://localhost:8080/bookstore/secure。
這一次,你可能會提前看到登錄頁面,用測試用戶的用戶名和密碼登錄,你隨後可能會重新看到secure頁面。
10. 測試Remember Me 功能
選中Remember Me 複選框,進入你測試的secure頁面,關閉瀏覽器再重新打開它。再次導航到secure 頁面。因爲有一個cookie 被保存,你可能不需要再次登錄。在任何時候要退出請導航到http://localhost:8080/bookstore/logout。
11.可選,爲user和role創建一個創建CRUD UI 。
運行grailsgenerate-all 生成控制器和視圖:
$ grails generate-all com.testapp.User
$ grails generate-all com.testapp.Role
用戶類處理密碼加密,對生成的控制器要求沒有發生變化。