20130115-使用Grails Shiro Plugin實現身份驗證01


目標

  • 盡可能簡單的使用Grails Shiro Plugin實現身份驗證功能.

安裝

  • Grails版本:2.1.1
  • 約定:在代碼示例中,任何使用$開頭,說明這是一個shell命令
1 $ grails create-app shiro-example
2 $ cd shiro-example
  • shiro plugin最新的插件版本是1.1.4,可以使用grails install-plugin shiro安裝,但是這里使用最新的快照版本。不需要用shell安裝只需要在項目的BuildConfig.groovy中增加插件的引用即可
    plugins {
        runtime ":hibernate:$grailsVersion"
        runtime ":jquery:1.8.3"
        runtime ":resources:1.1.6" runtime ":shiro:1.2.0-SNAPSHOT"
  • 當我們修改了BuildConfig.groovy文件后,需要對系統進行重新編譯,修改才能生效
$ grails compile
  • 現在插件已經安裝好了,下一步建立一個初步的腳手架,執行這個shell后,系統會幫我們生成一系列的腳手架文件,這個--prefix=[包路徑]是可選項,如果使用包路徑,不要忘記最后面的那個"."
$ grails shiro-quick-start --prefix=com.example.
| Created file grails-app/domain/com/example/User.groovy
| Created file grails-app/domain/com/example/Role.groovy
| Created file grails-app/realms/com/example/DbRealm.groovy
| Created file grails-app/controllers/com/example/AuthController.groovy
| Created file grails-app/views/auth/login.gsp
| Created file grails-app/conf/com/example/SecurityFilters.groovy

 配置

Bootstrap.groovy

 1 import com.example.Role
 2 import com.example.User
 3 
 4 class BootStrap {
 5 
 6     def shiroSecurityService
 7 
 8     def init = { servletContext ->
 9         // Create the admin role
10         def adminRole = Role.findByName('ROLE_ADMIN') ?:
11                 new Role(name: 'ROLE_ADMIN').save(flush: true, failOnError: true)
12 
13         // Create the user role
14         def userRole = Role.findByName('ROLE_USER') ?:
15                 new Role(name: 'ROLE_USER').save(flush: true, failOnError: true)
16 
17         // Create an admin user
18         def adminUser = User.findByUsername('admin') ?:
19                 new User(username: "admin",
20                 passwordHash: shiroSecurityService.encodePassword('password'))
21                 .save(flush: true, failOnError: true)
22 
23         // Add roles to the admin user
24         assert adminUser.addToRoles(adminRole)
25         .addToRoles(userRole)
26         .save(flush: true, failOnError: true)
27 
28         // Create an standard user
29         def standardUser = User.findByUsername('joe') ?:
30                 new User(username: "joe",
31                 passwordHash: shiroSecurityService.encodePassword('password'))
32                 .save(flush: true, failOnError: true)
33 
34         // Add role to the standard user
35         assert standardUser.addToRoles(userRole)
36         .save(flush: true, failOnError: true)
37 
38     }
39     def destroy = {
40     }
41 }
  • 在代碼第6行,引入了shiro的安全服務,並使用服務的encodePassword方法進行加密
  • 在代碼第9到15行,新增admin和user兩個角色
  • 在代碼第17到21行,新增一個賬號為admin的用戶,並對password進行加密
  • 在代碼第23到26行,給admin用戶進行角色授權
  • 在代碼第28到36行,給user用戶進行角色授權

運行測試一下效果

$grails run-app
or
$grails -Dserver.port=8888 run-app

登錄http://localhost:8080/shiro-example,點com.example.AuthController控制器,系統彈出登錄窗口,輸入賬號和密碼后,系統返回主界面,什么都沒發生過。這是因為我們沒有需要驗證的界面,下面再增加一點東西

  • 新增一個控制器
$ grails create-controller com.example.Home
  • 給這個控制器增加三個action
 1 package com.example
 2 
 3 class HomeController {
 4 
 5     def index() {
 6         render "這個頁面不需要驗證"
 7     }
 8 
 9     def secured() {
10         render "這個頁面需要user角色才能訪問"
11     }
12 
13     def admin() {
14         render "這個頁面需要admin角色才能訪問"
15     }
16 }
  • 正如我們看到的,我可以分別登陸不同的視圖,特定的角色才能返回正常的結果
  • 如果權限不夠的用戶登錄到了相應頁面,系統提示“You do not have permission to access this page”
  • 如果我們現在運行,並訪問,不管登錄到index、secured還是admin,系統都會提示“You do not have permission to access this page”

現在,分別給不同的action進行授權,打開SecurityFilters.groovy,拷貝如下代碼

 1 package com.example
 2 
 3 /**
 4  * Generated by the Shiro plugin. This filters class protects all URLs
 5  * via access control by convention.
 6  */
 7 class SecurityFilters {
 8 
 9     /**
10      * Array of controller/action combinations which will be skipped from authentication
11      * if the controller and action names match. The action value can also be '*' if it
12      * encompasses all actions within the controller.
13      */
14     static nonAuthenticatedActions = [
15             [controller: 'home', action: 'index']
16     ]
17 
18     /**
19      * Array of controller/action combinations that will be authenticated against the user's
20      * role. The map also includes the roles which the controller/action pair will match
21      * against.
22      */
23     static authenticatedActions = [
24             [controller: 'home', action: 'secured', roles: ['ROLE_ADMIN', 'ROLE_USER']],
25             [controller: 'home', action: 'admin', roles: ['ROLE_ADMIN']]
26     ]
27 
28     def filters = {
29 
30         all(controller: '*', action: '*') {
31             before = {
32 
33                 // Determine if the controller/action belongs is not to be authenticated
34                 def needsAuth = !nonAuthenticatedActions.find {
35                     (it.controller == controllerName) &&
36                             ((it.action == '*') || (it.action == actionName))
37                 }
38 
39                 if (needsAuth) {
40 
41                     // Get the map within the authenticated actions which pertain to the current
42                     // controller and view.
43                     def authRoles = authenticatedActions.find {
44                         (it.controller == controllerName) &&
45                                 ((it.action == '*') || (it.action == actionName))
46                     }
47 
48                     if (authRoles) {
49 
50                         // Perform the access control for each of the roles provided in the authRoles
51                         accessControl {
52                             authRoles.roles.each { roleName ->
53                                 role(roleName)
54                             }
55                         }
56                     }
57 
58                     // Skip authentication if the authRoles was not found
59                     else {
60                         return true
61                     }
62                 }
63 
64                 // Skip authentication if no auth is needed
65                 else {
66                     return true
67                 }
68             }
69         }
70 
71     }
72 }
  • 代碼第14到16行,登記不需要授權的action
  • 代碼第23到26行,登記需要授權的action,並指定相應的角色

現在,大功告成,再使用不同的角色,訪問不同的頁面,應該可以得到不同的效果

http://localhost:8080/shiro-example/home/index : non

http://localhost:8080/shiro-example/home/secured : user,admin

http://localhost:8080/shiro-example/home/admin : admin


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM