簡介 現在,我們必須在管理系統須要加入一些認證機制。幸運的是,Play有一個模組。就是所謂的Secure module。 Enabling the Secure module 啟用SECURE模組必須在yabe/conf/application.conf檔案新增以及重新啟動應用程式。 # Import the secure module
module.secure=${play.path}/modules/secure 重新啟動之後,Play就會載入該模組套件了。Secure模組配置一組預設的路徑,你可以簡單地在yabe/conf/routes檔案設定(或者我們也可以自定義路徑): # Import Secure routes
* / module:secure
Protecting the admin controllers 該模組提供了一個Controllers。Secure controller聲明所有需要的攔截器。當然,我們可以只要繼承該Controllers,但是因為Java僅單一繼承,這會有些問題。為了不直接繼承Secure controller,我們可以在管理介面上使用註解並運用@With annotation告訴Play調用相對應的攔截器會更好。 package controllers;
import play.*;
import play.mvc.*;
@With(Secure.class)
public class Posts extends CRUD {
} 在Comments, Users and Tags controllers也是一樣的做法。現在,如果你嚐試訪問任何管理介面,你都必須要經過登錄頁面: Customizing the authentication process 應用程式必須提供一個已實例化Controllers。Secure.Security自定義身份驗證的過程。通過我們自己建立的Class,將能精確指定用戶進行身份驗證。此時,建立一個方法在yabe/controllers/Security.java檔案並Override authenticate()方法: package controllers;
import models.*;
public class Security extends Secure.Security {
static boolean authenticate(String username, String password) {
return true;
}
} 正如我們已經有了User objects在Blog model,可以很容易地實現working version在該方法上。 static boolean authenticate(String username, String password) {
return User.connect(username, password) != null;
} 現在可以瀏覽http://localhost:9000/logout,你可以嘗試登入用戶從data.yml檔案中找尋使用者,例如:帳號密碼為bob@gmail.com/secret的這位使用者。 Refactoring the administration area 我們已經開始使用CRUD模組在管理者系統上,但是,它尚未得到很好的Blog UI介面。我們將開始在管理者系統上給予一個全新的介面。這個人可以給予其它作者權限來發表文章。並具有最大權限使用CRUD模組,此為超級使用者。讓我們為管理者系統建立一個Admin Controller: package controllers;
import play.*;
import play.mvc.*;
import java.util.*;
import models.*;
@With(Secure.class)
public class Admin extends Controller {
@Before
static void setConnectedUser() {
if(Security.isConnected()) {
User user = User.find("byEmail", Security.connected()).first();
renderArgs.put("user", user.fullname);
}
}
public static void index() {
render();
}
} 並定義路徑在yabe/conf/routes檔案中。 # Administration
GET /admin/? Admin.index
* /admin module:crud 現在將‘Log in to write something’ 加入超連結,該檔案位於yabe/app/views/main.html 模版。 ...
<ul id="tools">
<li>
<a href="@{Admin.index()}">Log in to write something</a>
</li>
</ul>
... 最後,為了讓這些程序運行起來我們要建立yabe/app/views/Admin/index.html模版。先從最簡單的開始: Welcome ${user}! 現在,進入Blog首頁,點擊 ‘Log in to write something’,你應該會前往新的管理者系統介面: 看來相當不錯!!但是,因為我們將在這幾頁操作管理介面,我們需要一個超級模版(super-template)。讓我們建立一個檔案在yabe/app/views/admin.html: <!DOCTYPE html>
<html>
<head>
<title>Administration</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
#{get 'moreStyles' /}
<link rel="stylesheet" type="text/css" media="screen"
href="@{'/public/stylesheets/main.css'}" />
<link rel="shortcut icon" type="image/png"
href="@{'/public/images/favicon.png'}" />
<script src="@{'/public/javascripts/jquery-1.3.2.min.js'}"></script>
<script src="@{'/public/javascripts/jquery.tools.min.js'}"></script>
</head>
<body id="admin">
<div id="header">
<div id="logo">
yabe. <span>administration</span>
</div>
<ul id="tools">
<li>
<a href="@{Secure.logout()}">Log out</a>
</li>
</ul>
</div>
<div id="main">
#{doLayout /}
</div>
<p id="footer">
Yabe is a (not so) powerful blog engine built with the
<a href="http://www.playframework.org">Play framework</a>
as a tutorial application.
</p>
</body>
</html> 正如你所看到的,你已經取代了登入超連結來調用Secure controller的登出 action所調用的secure module。現在,讓我們使用yabe/app/views/Admin/index.html模版並重新整理: #{extends 'admin.html' /}
Welcome ${user}! 如果你嘗試登出連結將會返回至登入頁面: 這是預設當secure module登出所處理的事件。但是,它很容易制定簡單地通過覆寫onDisconnected()方法在controllers.Security class: static void onDisconnected() {
Application.index();
} 你也可以同樣去做onAuthenticated()事件: static void onAuthenticated() {
Admin.index();
} Adding roles 其實,我們需要兩組管理者介面:一個是簡單的編輯器,另一個是超級管理者。正如你所看到User model有一個isAdmin欄位來定義用戶是否具有超級管理者權限。該Secure module不僅提供了身份驗證,也授權管理。這就是所謂的profiles。要建立一個Admin profiles, 你必須Override check()方法在controllers.Security class之中: static boolean check(String profile) {
if("admin".equals(profile)) {
return User.find("byEmail", connected()).<User>first().isAdmin;
}
return false;
} 現在,我們可以顯示出管理選單,如果用戶具有管理者角色的話。更新yabe/views/admin.html並整合選單在頂層: ...
<div id="main">
<ul id="adminMenu">
<li class="${request.controller == 'Admin' ? 'selected' : ''}">
<a href="@{Admin.index()}">My posts</a>
</li>
#{secure.check 'admin'}
<li class="${request.controller == 'Posts' ? 'selected' : ''}">
<a href="@{Posts.list()}">Posts</a>
</li>
<li class="${request.controller == 'Tags' ? 'selected' : ''}">
<a href="@{Tags.list()}">Tags</a>
</li>
<li class="${request.controller == 'Comments' ? 'selected' : ''}">
<a href="@{Comments.list()}">Comments</a>
</li>
<li class="${request.controller == 'Users' ? 'selected' : ''}">
<a href="@{Users.list()}">Users</a>
</li>
#{/secure.check}
</ul>
#{doLayout /}
</div>
... 注意,我們要知道如何使用 #{secure.check /} tag來顯示只有管理者才會出現的選單。 但是,這還不夠。如果使用者知道URL他仍然可後隨意訪問。我們必須保護該Controllers會更好。我們必須使用@Check annotation。例如,在Posts controllers上: package controllers;
import play.*;
import play.mvc.*;
@Check("admin")
@With(Secure.class)
public class Posts extends CRUD {
} 一樣的方式可以在Tags, Comments及Users controllers上運用。現在嘗試用一般用戶重新登入(如: jeff@gmail.com/secret)。你應該不會看到CRUD admin超連結才對。如果你嘗試強制訪問http://localhost:9000/admin/users 你應該會得到一個403回應。 Customizing the CRUD layout 這很有趣,但是當我們前往CRUD的管理者介面,我們失去了管理介面佈局。這是因為CRUD模組提供了自己的佈局。但是,我們一樣可以自定義佈局。必須使用以下的Play指令: play crud:ov --layout 你將會得到一組模版在yabe/app/views/CRUD/layout.html。讓我們來取代它的內容來建置我們自己的佈局: #{extends 'admin.html' /}
#{set 'moreStyles'}
<link rel="stylesheet" type="text/css" media="screen"
href="@{'/public/stylesheets/crud.css'}" />
#{/set}
<div id="crud">
#{if flash.success}
<div class="crudFlash flashSuccess">
${flash.success}
</div>
#{/if}
#{if flash.error || error}
<div class="crudFlash flashError">
${error ?: flash.error}
</div>
#{/if}
<div id="crudContent">
#{doLayout /}
</div>
</div> 正如你所看見的,我們運用crud.css及admin.html使用了get/set模版變數機制。現在,如果你嘗試運行CRUD的管理者介面,就會有管理者介面的佈局出現: Styling the login page 該管理者介面幾乎要一致的。最後,要設計登入頁面的CSS風格。我們可以簡單地自定義並覆寫預設的CSS: play secure:ov --css 我們保留了CSS,但是必須在最上層import main.css在yabe/public/stylesheets/secure.css: @import url(main.css);
... 並自定義登入畫面訊息,增加相關訊息於yabe/conf/messages檔案中: secure.username=Your email:
secure.password=Your password:
secure.signin=Log in now |