1

我有一个需要迁移到 Vaadin 的旧 Web 应用程序。

在旧应用程序中,有一个页面要求用户输入登录名和密码。

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>

这意味着在身份验证不成功的情况下,用户将被定向到 page 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. 检查在文本字段中输入的凭据,userName并且password
  2. 显示一个通知框,如果凭据错误并且
  3. 如果它们正确,则打开另一个 UI(视图)。

如何让我的 Vaadin 应用程序访问用于检查凭据的 Tomcat 机制(即,我的 Vaadin 应用程序应该以与旧应用程序完全相同的方式执行凭据检查)?

什么代码允许我根据指定的数据库检查用户名x和密码是否有效?ycontext.xml

更新 1 (05.11.2013):我在这里找到了关于如何使用基于领域的身份验证的描述

但是我遇到了一个问题:

示例中的应用程序 servlet extends com.vaadin.terminal.gwt.server.AbstractApplicationServlet,这在我的 Vaadin 7 项目中不可用。

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

更新 2 (05.11.2013 15:53):

我尝试以最简单的方式实现身份验证:

1) 使用 BASIC 认证机制。2) 配置 Web 应用程序,以便所有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>

但它不起作用:访问应用程序时会显示凭据对话框,但是当我输入正确的凭据并按“确定”时,再次出现相同的对话框。

4

2 回答 2

2

好像你把一切都复杂化了。请在下面找到现实生活中的解决方案。它用于 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.你已经完成了,只需测试

于 2013-11-06T15:28:06.053 回答
1

我建议您从 Vaadin 中排除身份验证。将 JSP 页面保留为身份验证表单,并使用 Servlet 规范中的默认身份验证。

如果您的代码中有可编程的身份验证,它就会为错误打开大门。此外,您的代码更复杂。更好地使用声明式安全性。在这种情况下,身份验证与应用程序分开。您的应用程序更简单,安全性更受信任。

看看网络研讨会http://www.youtube.com/watch?v=PNAO3ApWA-A整体很有趣,但是如何进行身份验证的示例从 47 分钟开始。提供了两种解决方案:自定义代码和声明性安全性。

在看到那个网络研讨会之后,我确信声明式安全是正确的选择。

声明式安全需要在 web.xml 中进行一些调整。与纯 Vaadin 应用程序相比,并非所有请求都由 VaadinServlet 处理:必须默认处理身份验证请求。无论如何,声明式安全值得配置工作。

于 2013-11-02T08:43:35.307 回答