本系列文章將以Apacke Wicket Example裡的範例來進行說明,Wicket的版本為1.5x。
首先,Auth/Roles套件實作了IAuthorizationStrategy介面;當授權策略(authorization strategy)安裝在安全性設定中(WebApplication#getSecuritySettings),Wicket將會自動檢查所有元件(component)是否具備可以初始化(instaintion)或是呈現畫面(render)的權限。
欲進行身份認證時,本身的web application必須繼承AuthenticatedWebApplication(此類別為抽象類別),同時要override裡面的三個methods:
1.newSession:回傳AuthenticatedWebSession的子類別(自訂的Session物件)。
2.getSignInPageClass:回傳登入頁面類別。
3.getWebSessionClass():回傳AbstractAuthenticatedWebSession的子類別。
為了要讓使用者在驗證過後,我們必須在application類別的init()中註冊授權策略(getSecuritySettings().setAuthorizationStrategy(new IAuthorizationStrategy(){...}),同時要override在IAuthorizationStrategy類別中的methods。
1.isInstantiationAuthorized:取得能否建立某項元件。
2.isActionAuthorized:取得能否執行某項行為。
-- 體驗範例程式 --
以下是SignInApplication.java程式碼:
package com.myapp.wicket;
import org.apache.wicket.Component;
import org.apache.wicket.RestartResponseAtInterceptPageException;
import org.apache.wicket.Session;
import org.apache.wicket.authorization.Action;
import org.apache.wicket.authorization.IAuthorizationStrategy;
import org.apache.wicket.authroles.authentication.AbstractAuthenticatedWebSession;
import org.apache.wicket.authroles.authentication.AuthenticatedWebApplication;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.request.Request;
import org.apache.wicket.request.Response;
import org.apache.wicket.request.component.IRequestableComponent;
/**
*
* @author Hsiao Shengche
* @version
*/
public class SignInApplication extends AuthenticatedWebApplication {
public SignInApplication() {
}
public Class getHomePage() {
return Home.class;
}
@Override
protected Class<? extends AbstractAuthenticatedWebSession> getWebSessionClass() {
return SignInSession.class;
}
@Override
public Session newSession(Request request, Response response) {
//回傳自訂的Session類別
return new SignInSession(request);
}
@Override
protected Class<? extends WebPage> getSignInPageClass() {
//回傳登入頁面
return SignIn.class;
}
@Override
protected void init(){
super.init();
//設定字元集
getMarkupSettings().setDefaultMarkupEncoding("UTF-8");
//註冊授權策略
getSecuritySettings().setAuthorizationStrategy(new IAuthorizationStrategy(){
@Override
public <T extends IRequestableComponent> boolean isInstantiationAuthorized(Class<T> type) {
//回傳能否建立元件(含頁面)
//檢查Home.html是否要驗證才能進入
//isAssignableFrom(type)->指的是傳入的元件是否就是我們要的元件
//意指我們只要檢查Home.html此元件而已(若知道runtime的類別,亦可使用instanceof)
if (Home.class.isAssignableFrom(type)){
//檢查是否已登入
if (((SignInSession)Session.get()).isSignedIn()){
//若已登入,則允許執行
return true;
}
//若沒有登入則要導向登入頁面
//throw new RestartResponseAtInterceptPageException(SignIn.class);
//介入目前的equest並導向其他頁面
throw new RestartResponseAtInterceptPageException(SignIn.class);
}
return true;
}
@Override
public boolean isActionAuthorized(Component cmpnt, Action action) {
//回傳是否允許執行某項元件的某個動作,目前先允許所有動作
return true;
}
});
}
}
接下來,我們要提供自訂的session類別,它必須繼承AuthenticatedWebSession,相同的它也是一個抽象類別。自訂session必須要override以下兩個methods:
1.authenticate:在此進行身份驗證,使用username及password。
2.getRoles:當使用者通過身份驗證後會呼叫此method,因此在此method中必須提供相對應的角色(roles)。
以下是SignInSession.java範例程式碼:
package com.myapp.wicket;
import org.apache.wicket.authroles.authentication.AuthenticatedWebSession;
import org.apache.wicket.authroles.authorization.strategies.role.Roles;
import org.apache.wicket.request.Request;
/**
*
* @author Hsiao Shengche
*/
public class SignInSession extends AuthenticatedWebSession {
//簡單的使用者
private String user;
public SignInSession(Request request) {
super(request);
}
@Override
public boolean authenticate(String username, String password) {
//進行身份驗證,預設帳密均為wicket
final String WICKET = "wicket";
if (user == null) {
// 檢查帳密
if (WICKET.equalsIgnoreCase(username) && WICKET.equalsIgnoreCase(password)) {
user = username;
}
}
//如果登入成功,那麼AuthenticationWebSession.isSignIn()就會回傳true
return user != null;
}
public String getUser() {
return user;
}
public void setUser(final String user) {
this.user = user;
}
@Override
public Roles getRoles() {
//此範例不提供角色
return null;
}
}
在這個範例中,首頁是Home.html,但它必須先經過身份驗證才能看到,因此系統會將未認證的使用者導向SignIn.html頁面進行輸入帳號、密碼並驗證的動作。
以下是SignIn.html的html:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns:wicket="http://wicket.apache.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>SignIn</title>
<link rel="stylesheet" type="text/css" href="style.css"/>
</head>
<body>
<wicket:extend>
<span wicket:id = "feedback"/>
<p>
<i>Username and password are both "wicket"</i>
</p>
<form wicket:id = "signInForm">
<table>
<tr>
<td align = "right">Username:</td>
<td>
<input wicket:id = "username" type = "text" value = "foo@goo.moo" size = "30"/>
</td>
</tr>
<tr>
<td align = "right">Password:</td>
<td>
<input wicket:id = "password" type = "password" value = "password" size="30"/>
</td>
</tr>
<tr>
<td></td>
<td>
<input type = "submit" value = "登入"/>
</td>
</tr>
</table>
</form>
</wicket:extend>
</body>
</html>
SignIn.java程式碼如下:
package com.myapp.wicket;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.PasswordTextField;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import org.apache.wicket.util.value.ValueMap;
/**
*
* @author Hsiao Shengche
*/
public final class SignIn extends BasePage {
public SignIn() {
super();
// Create feedback panel and add to page
add(new FeedbackPanel("feedback"));
// Add sign-in form to page
add(new SignInForm("signInForm"));
}
public SignIn(PageParameters params) {
//TODO: process page parameters
}
public final class SignInForm extends Form<Void> {
private static final String USERNAME = "username";
private static final String PASSWORD = "password";
// El-cheapo model for form
private final ValueMap properties = new ValueMap();
/**
* Constructor
*
* @param id id of the form component
*/
public SignInForm(final String id) {
super(id);
// Attach textfield components that edit properties map model
add(new TextField<String>(USERNAME, new PropertyModel<String>(properties, USERNAME)));
add(new PasswordTextField(PASSWORD, new PropertyModel<String>(properties, PASSWORD)));
}
@Override
public final void onSubmit() {
//按下送出鍵就進行驗證
SignInSession session = getMySession();
// 呼叫AuthenticatedWebSession.signIn(username,password)
// 會自動呼叫WebSession.authenticate(username,password)
if (session.signIn(getUsername(), getPassword())) {
if (!continueToOriginalDestination()) {
//導入首頁->表示已驗證通過
setResponsePage(getApplication().getHomePage());
}
} else {
// 設定錯誤訊息
String errmsg = getString("loginError", null, "登入失敗");
// Register the error message with the feedback panel
error(errmsg);
}
}
private String getPassword() {
return properties.getString(PASSWORD);
}
private String getUsername() {
return properties.getString(USERNAME);
}
private SignInSession getMySession() {
return (SignInSession) getSession();
}
}
}
SignOut.html則是登出頁面,按了它會執行SignOut.java並將Session設為invalide,意即取消此次Session所儲存的資料。
以下是SignOut.html內容:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns:wicket="http://wicket.apache.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>SignOut</title>
<link rel="stylesheet" type="text/css" href="style.css"/>
</head>
<body>
<wicket:extend>
<h2>Goodbye!</h2>
<wicket:link><a href="Home.html">首頁</a></wicket:link>
</wicket:extend>
</body>
</html>
以下是SignOut.java程式碼:
package com.myapp.wicket;
import org.apache.wicket.request.mapper.parameter.PageParameters;
/**
*
* @author Hsiao Shengche
*/
public final class SignOut extends BasePage {
/*
* 若要成功登出則要取消此建構子
public SignOut() {
super();
}
*
*/
public SignOut(PageParameters params) {
getSession().invalidate();
}
}
No comments:
Post a Comment