我有一个旧的Web应用程序,我需要迁移到Vaadin .
在旧的应用程序中,有一个页面要求用户输入登录名和密码 .
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
被执行)时,我想
-
检查在文本字段
userName
和password
中输入的凭据,
如果凭据错误, -
将显示通知框
-
打开另一个UI(视图),如果它们是正确的 .
如何让我的Vaadin应用程序访问用于检查凭据的Tomcat机制(即我的Vaadin应用程序应该以与旧应用程序完全相同的方式执行凭据检查)?
什么代码允许我根据 context.xml
中指定的数据库检查用户名 x
和密码 y
是否有效?
Update 1 (05.11.2013): 我找到了如何使用基于域的身份验证的描述here .
但是我遇到了一个问题:
示例中的应用程序servlet扩展 com.vaadin.terminal.gwt.server.AbstractApplicationServlet
,这在我的Vaadin 7项目中不可用 .
@WebServlet(urlPatterns={"/ui/*", "/VAADIN/*"})
public class DemoAppServlet extends AbstractApplicationServlet {
Update 2 (05.11.2013 15:53):
我试图以最简单的方式实现身份验证:
1)使用BASIC认证机制 . 2)配置Web应用程序,以便 all 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>
但它不起作用:访问应用程序时会显示凭据对话框,但是当我输入正确的凭据并按“确定”时,将再次出现相同的对话框 .
2 回答
看起来你的一切都过于复杂 . 请找到以下现实解决方案 . 它用于Vaadin应用程序,只是工作 .
1. You need external login page
这是最简单的方法 . 如果需要,您可以轻松设置该页面的样式,以免破坏用户体验 .
像往常一样,您将拥有以下内容:
2. I would suggest to have external login failed page
基本上它只需要通知用户有错误 . 例如,它也可能表明要重新登录 .
3. Configure proper auth method
4. Do not forget to set session timeout
5. You are done, just test
我建议你从Vaadin中排除身份验证 . 将JSP页面保留为身份验证表单,并使用Servlet规范中的默认身份验证 .
如果您的代码中有可编程身份验证,则会为错误打开大门 . 而且,您的代码更复杂 . 更好地使用声明性安全性 . 在这种情况下,身份验证与应用程序分离您的应用程序更简单,安全性更受信任 .
看看网络研讨会http://www.youtube.com/watch?v=PNAo3ApWA-A整体非常有趣,但是如何从47分钟开始进行身份验证的示例 . 提供了两种解决方案:自定义代码和声明性安全性 .
看到网络研讨会后,我确信声明性安全性是正确的选择 .
声明性安全性需要在web.xml中进行一些调整 . 与纯Vaadin应用程序相比,并非所有请求都由VaadinServlet处理:默认情况下必须处理身份验证请求 . 无论如何,声明性安全性值得配置 .