2013-11-01 62 views
1

我有一箇舊的Web應用程序,我需要遷移到Vaadin。如何在Vaadin中執行j_security_check用戶憑證檢查?

在舊的應用程序有一個頁面,要求用戶的登錄名和密碼。

JSP頁面看起來是這樣的:

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru" lang="ru"> 

<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="utf-8"%> 
[...] 
<head> 
<title>Some product</title> 
    <link rel="stylesheet" type="text/css" href="<%=request.getContextPath()+"/css/styles.css"%>" /> 
</head> 
<body> 
<%@ include file="inc/main-navigation.jsp"%> 
    <form action="j_security_check" method="post" style="margin:0px"> 
     [...] 
     <input type="text" style="width:100%" name="j_username" /> 
     <input type="password" name="j_password" /> 
    </form> 
</body> 
</html> 

web.xml包含以下項目:

<login-config> 
    <auth-method>FORM</auth-method> 
    <realm-name>Some product</realm-name> 
    <form-login-config> 
     <form-login-page>/login.jsp</form-login-page> 
     <form-error-page>/login_fail.jsp</form-error-page> 
    </form-login-config> 
</login-config> 

這意味着,在認證不成功的情況下,用戶被引導到login_fail.jsp頁。

context.xml文件中,我找到了以下條目,從中我得出結論:在Tomcat中有一個內部機制,它從指定的數據庫中讀取正確的登錄名和密碼,並在沒有任何其他代碼的情況下執行檢查。

<Context path="/myapp"> 
    <Realm className="org.apache.catalina.realm.JDBCRealm" driverName="com.microsoft.sqlserver.jdbc.SQLServerDriver" 
     connectionURL="[...]" 
     userTable="[...]" userNameCol="user_name" userCredCol="user_pass" 
     userRoleTable="[...]" roleNameCol="role_name"/> 
</Context> 

在Vaadin應用程序中,我有一個包含文本字段和按鈕的UI。

public class BookkeepingView extends VerticalLayout implements View { 
    public BookkeepingView() 
    { 
     VerticalLayout contentPanel = new VerticalLayout(); 

     contentPanel.setStyleName("body"); 
     contentPanel.addComponent(getHeaderPanel()); 
     contentPanel.addComponent(getLoginPanel()); 
     contentPanel.addComponent(getFooterPanel()); 

     addComponent(contentPanel); 
    } 

    private Component getHeaderPanel() { 
     return createCustomLayoutPanel("main-navigation"); 
    } 

    private Component getFooterPanel() { 
     return createCustomLayoutPanel("copyright"); 
    } 

    private CustomLayout getLoginPanel() { 
     Panel panel = new Panel(); 
     panel.setSizeUndefined(); 
     addComponent(panel); 

     CustomLayout customLayoutPanel = new CustomLayout("login"); 

     final TextField userName = new TextField(); 
     customLayoutPanel.addComponent(userName, "j_username"); 

     final PasswordField password = new PasswordField(); 
     customLayoutPanel.addComponent(password, "j_password"); 

     final Button loginButton = new Button(I18n.l("bookkeeping_login_button")); 
     customLayoutPanel.addComponent(loginButton, "login"); 

     loginButton.addClickListener(new Button.ClickListener() { 
      @Override 
      public void buttonClick(Button.ClickEvent clickEvent) { 
       loginButtonPressed(); 
      } 
     }); 

     return customLayoutPanel; 
    } 

    private void loginButtonPressed() { 
     Notification.show("Login button pressed", Notification.Type.TRAY_NOTIFICATION); 
    } 

    private CustomLayout createCustomLayoutPanel(final String aHtmlFileName) { 
     Panel panel = new Panel(); 
     panel.setSizeUndefined(); 
     addComponent(panel); 

     CustomLayout customLayoutPanel = new CustomLayout(aHtmlFileName); 
     return customLayoutPanel; 
    } 


    @Override 
    public void enter(ViewChangeListener.ViewChangeEvent event) { 

    } 
} 

當用戶按下按鈕(執行方法loginButtonPressed),我想

  1. 檢查在文本字段userNamepassword輸入的憑據,
  2. 顯示一個通知框,如果憑據錯誤
  3. 打開另一個用戶界面(查看),如果他們是正確的。

我該如何讓我的Vaadin應用程序訪問Tomcat檢查憑據的機制(即我的Vaadin應用程序應該以與舊應用程序完全相同的方式執行憑據檢查)?

什麼樣的代碼允許我根據context.xml中指定的數據庫檢查用戶名是否爲x和密碼y

更新1(05.11.2013):我找到了如何使用基於領域認證的說明here

但我遇到了一個問題:

例子中的應用程序servlet擴展com.vaadin.terminal.gwt.server.AbstractApplicationServlet,這是不是可以在我的Vaadin 7項目。

@WebServlet(urlPatterns={"/ui/*", "/VAADIN/*"}) 
public class DemoAppServlet extends AbstractApplicationServlet { 

更新2(2013年5月11日15點53分):

我試圖實現最簡單的方式驗證:

1)使用基本身份驗證機制。 2)配置網絡應用程序,以便全部 Vaadin頁面要求用戶登錄。

爲了實現這一點,我添加以下片段web.xml

<servlet-mapping> 
    <servlet-name>VaadinDemoApp</servlet-name> 
    <url-pattern>/*</url-pattern> 
</servlet-mapping> 
<security-constraint> 
    <display-name>VaadinDemoApplicationConstraint</display-name> 
    <web-resource-collection> 
     <web-resource-name>Vaadin application</web-resource-name> 
     <url-pattern>/*</url-pattern> 
    </web-resource-collection> 
    <auth-constraint> 
     <role-name>admin</role-name> 
     <role-name>viewer</role-name> 
    </auth-constraint> 
</security-constraint> 
<login-config> 
    <auth-method>BASIC</auth-method> 
    <realm-name>Protected page</realm-name> 
</login-config> 
<security-role> 
    <role-name>admin</role-name> 
</security-role> 

<security-role> 
    <role-name>viewer</role-name> 
</security-role> 

但它不工作:憑據對話框在訪問應用程序的顯示,但是當我輸入正確的憑據和按「確定」,同樣的對話框再次出現。

+0

德米特里,你是否設法解決你的問題? –

+0

是的。我現在正在使用Apache Shiro。它允許使用來自Apache Tomcat領域的數據庫中的數據。 –

回答

1

我建議你從Vaadin中排除驗證。將JSP頁面保存爲認證表單,並使用來自Servlet規範的默認認證。

如果您在代碼中具有可編程身份驗證功能,它會爲錯誤打開大門。而且,你的代碼更復雜。更好地使用聲明性安全性。在這種情況下,認證與應用程序分離。您的應用程序更簡單,安全性更可信。

在網絡研討會上看看http://www.youtube.com/watch?v=PNAo3ApWA-A整體非常有趣,但是如何使認證從47分鐘開始。這兩種解決方案都提供:自定義代碼和聲明式安全性。

看到網絡研討會後,我確定聲明性安全是正確的選擇。

聲明性安全需要在web.xml中進行一些調整。與純Vaardin應用程序相比,並非所有請求都由VaadinServlet處理:身份驗證請求必須默認處理。無論如何,聲明式安全值得配置。

1

看起來你似乎過於複雜的一切。請在下面找到真實的解決方案。它用於Vaadin應用程序,並且工作簡單。

1.你需要外部登錄頁面

這是最簡單的方法。如果你願意,你可以輕鬆地設置該頁面的樣式,以免打破用戶體驗。

<link rel="stylesheet" type="text/css" href="VAADIN/themes/reindeer/styles.css"> 
... 
<div class="v-app v-theme-reindeer"> 

像往常一樣,將具備以下條件:

<form id="login" method="post" action="j_security_check" > 

<input name="j_username" type="text"> 
<input name="j_password" type="text"> 

2.我建議有外部登錄失敗

基本上它只是需要通知有一些用戶頁面錯誤。例如,它也可能建議重新登錄。

3.配置適當的身份驗證方法

<login-config> 
    <auth-method>FORM</auth-method> 
    <form-login-config> 
     <form-login-page>/VAADIN/loginPage.html</form-login-page> 
     <form-error-page>/VAADIN/loginFailed.html</form-error-page> 
    </form-login-config> 
</login-config> 

4.不要忘記設置會話超時

<session-config> 
    <session-timeout>60</session-timeout> 
</session-config> 

5.你完成了,只是測試