既然咱们有一个管理面板,天然须要进行验证。幸运的是,Play已经提供了一个叫作Secure的模块来帮助咱们。javascript
在yabe/conf/application.conf
启动Secure模块,而后重启应用。css
# 导入secure模块 module.secure=${play.path}/modules/secure
在重启后,Play应该提示说模块已被加载。html
Secure模块提供一系列默认的路由。要导入这些路由,在/yabe/conf/routes
加入:java
# Import Secure routes * / module:secrue
这个模块提供了一个controllers.Secure
控制器,它定义了全部所需的拦截器。固然咱们能够继承这个控制器,可是Java只支持单继承,可能不能够这么作。jquery
除了直接继承Secure
控制器,咱们也能够给控制器加@With
注解来告诉Play启动对应的拦截器:segmentfault
package controllers; import play.*; import play.mvc.*; @With(Secure.class) public class Posts extends CRUD { }
一样处理Comments
,Users
和Tags
控制器。mvc
如今若是你想访问管理面板,就会跳转到登陆页面。app
不过,如今不管你往用户/密码框填什么,都会让你经过。布局
你能够用应用提供的controllers.Secure.Security
实例来自定义验证过程。经过继承自该类,咱们能够指定验证用户的方式。post
建立yabe/app/controllers/Security.java
,并重载authenticata()
方法:
package controllers; import models.*; public class Security extends Secure.Security { static boolean authenticate(String username, String password) { return true; } }
由于咱们已经在模型层实现了User对象,验证方法的实现就很简单了:
static boolean authenticate(String username, String password) { return User.connect(username, password) != null; }
如今前往http://localhost:9000/logout登出,而后尝试以initial-data.yml
中的任意用户登入,好比bob@gmail.com/secret
。
咱们经过CRUD模块开启了管理面板,但它跟博客的UI格格不入。因此咱们还须要实现另外一个管理面板。这个将给每一个做者发布本身的文章的权限。固然,原来的管理面板仍是能够留下来给超级管理员用。
让咱们建立一个Admin
控制器:
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
记住路由文件中的顺序是有确切含义的;排在前面的会比后面的优先匹配。因此Admin
的路由要放在映射到CRUD模块的路由的前面。不然,/admin/
会被映射到CRUD.index
而不是Admin.index
。
如今在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}!
如今,前往博客主页,点击“Log in to write something”连接,你应该到达新的管理面板:
好的开始!但由于管理面板将会有一系列新的页面,咱们须要定义一个父模板。建立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.4.2.min.js'}"></script> <script src="@{'/public/javascripts/jquery.tools-1.2.5.toolbox.expose.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>
如你所见,它像是前面用在博客引擎上的模板。这里替换了Log in连接成Log out,调用secure模块提供的Secure
控制器的logout
action。
如今就把它用到yabe/app/views/Admin/index.html
模板:
#{extends 'admin.html' /} Welcome ${user}!
刷新!
尝试下log out,它会让你从新登陆:
咱们是用secure模块的默认方法来处理登出。不过自定义也是十分简单的,重写controllers.Security
类中的onDisconnected()
方法便可:
static void onDisconnected() {
Application.index();
}
你能够一样重载onAuthenticated()
:
static void onAuthenticated() { Admin.index(); }
咱们有两个管理面板:一个用于编辑者,另外一个用于管理员。如你曾见,User
模型有一个isAdmin
成员,表示一个用户是否有管理员权限。
secure模块不只提供了authentication
,还支持authorization
。在secure模块中,这叫作 profiles
。要建立admin
身份(profile),你仅需重写controllers.Security
中的 check()
。
static boolean check(String profile) { if("admin".equals(profile)) { return User.find("byEmail", connected()).<User>first().isAdmin; } return false; }
若是用户具备管理员权限,咱们能够提供一个管理员菜单。更新app/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 /}
标签,只给admin
用户展现菜单。
可是咱们的CRUD部分依然处于危险之中!若是用户知道URL,他/她仍是能够访问它。咱们必须保护这些控制器。最简单的方法是使用@Check
注解。举个例子,对于Posts
控制器:
package controllers; import play.*; import play.mvc.*; @Check("admin") @With(Secure.class) public class Posts extends CRUD { }
一样处理Tags
,Comments
和Users
控制器。如今做为普通用户(好比``)登陆。你应该看不到CRUD管理员连接。若是试图访问http://localhost:9000/admin/u...,你会获得一个403 Forbidden响应。
当咱们使用基于CRUD的那个管理面板时,就没法使用管理布局了。由于CRUD模块提供了本身的布局。不过固然咱们能够重载掉它。使用Play命令:
play crud:ov --layout
你会获得一个/yabe/app/views/CRUD/layout.html
。来把它的内容替换掉,集成咱们的admin.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
并使用get/set模板变量机制来融合admin.html
。如今看下CRUD模块的管理面板,它应该跟管理布局结合在一块儿了:
管理面板的界面大致上已经完成了。最后要作的,是美化登陆界面。如常,从自定义默认的css开始吧。
play secure:ov --css
要想维持原来的css,咱们须要在顶部导入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