我正在使用 vaadin 8 + tomcat 7。vaadin 网站有一个面包店演示应用程序。
具体来说,我对日志记录过程很感兴趣。有一个单独的 LoginHtmlServlet servlet,它以某种方式与 vaadin 应用程序本身一起工作,这是它的代码:
@WebServlet(asyncSupported = true, urlPatterns = LoginHtmlServlet.LOGIN_HTML)
public class LoginHtmlServlet extends HttpServlet implements HasLogger {
public static final String LOGIN_HTML = "/login.html";
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
serveLoginHtml(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
if (req.getAttribute("shiroLoginFailure") != null) {
try {
resp.sendRedirect(LOGIN_HTML + "?error");
return;
} catch (Exception e) {
getLogger().error("Failed to redirect to login error page", e);
}
}
serveLoginHtml(req, resp);
}
private void serveLoginHtml(HttpServletRequest request, HttpServletResponse response) throws IOException {
InputStream loginHtml = request.getServletContext().getResourceAsStream(LOGIN_HTML);
response.setCharacterEncoding("utf-8");
org.apache.commons.io.IOUtils.copy(loginHtml, response.getOutputStream());
}
}
还有一个 LoginHtmlServlet 引用的 login.html 页面:
<!DOCTYPE html>
<html>
<!--
Hint to Vaadin that if this page is ever sent back as response to a UIDL request, the user should be redirected.
Vaadin-Refresh: context://login.html
-->
<head>
<title>My Starter Project</title>
<meta charset="utf-8">
<link rel="shortcut icon" href="VAADIN/themes/apptheme/favicon.ico" />
<link rel="import" href="bower_components/vaadin-valo-theme/color.html">
<meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no">
<!-- Enable these to hide browser controls when app is started from homescreen:
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-capable" content="yes">
-->
<script type="text/javascript">
var init = function() {
if (window.location.search.indexOf("error")>0) {
document.body.className = "error";
}
}
</script>
<style>
@font-face {
font-family: "Open Sans";
src: url(VAADIN/themes/valo/fonts/open-sans/OpenSans-Light-webfont.woff) format("woff");
font-weight: 300;
font-style: normal;
}
@font-face {
font-family: "Open Sans";
src: url(VAADIN/themes/valo/fonts/open-sans/OpenSans-Semibold-webfont.woff) format("woff");
font-weight: 600;
font-style: normal;
}
html {
background: linear-gradient(145deg, #0755ba 30%, #e7f1fe 100%);
}
@media (min-width: 1000px) {
/* load on wide screens */
body {
background-color: transparent;
background-size: cover;
}
}
button {
background-color: #1676f4;
}
#logo {
display: inline-block;
width: 60px;
height: 60px;
border-radius: 100%;
background-size: contain;
background-repeat: no-repeat;
background-color: rgba(255,255,255,0.2);
box-shadow: 3px 3px 8px rgba(0,0,0,.2);
}
/* Layout */
*, *:before, *:after {
box-sizing: border-box;
}
html, body {
height: 100%;
font: 100 16px/1.55 "Open Sans", sans-serif;
margin: 0;
}
#info {
color: #fff;
text-align: center;
padding: 28px;
}
#form {
height: 100%;
display: flex;
background-color: #fff;
justify-content: center;
}
/* Responsive behaviour */
@media (max-width: 1000px) {
h2 {
display: none;
}
}
@media (min-width: 1001px) {
body {
display: flex;
align-items: center;
justify-content: center;
}
#logo {
width:96px;
height:96px;
}
#info, #form {
height: 450px;
box-shadow: 0 2px 3px rgba(0,0,0,.2);
}
#info {
background-color: rgba(255,255,255,.2);
width: 465px;
border-radius: 5px 0 0 5px;
}
#form {
width: 320px;
padding: 28px;
border-radius: 0 5px 5px 0;
}
}
/* Elements / components theme */
h1 {
font-size: 36px;
font-weight: 100;
}
h2 {
font-size: 28px;
font-weight: 100;
margin-bottom: 14px;
}
form {
max-width: 320px;
}
label {
font-size: 14px;
padding: 16px 0 5px 0;
display: inline-block;
}
input[type='text'],
input[type='password'] {
width: 100%;
-webkit-appearance: none;
-moz-appearance: none;
-ms-appearance: none;
-o-appearance: none;
appearance: none;
font: inherit;
font-size: 14px;
height: 37px;
border-radius: 4px;
padding: 4px 9px;
border: 1px solid rgba(0,0,0,.2);
}
button {
width:100%;
margin-top: 37px;
height: 37px;
border: 1px solid #666;
border-radius: 4px;
background-image: linear-gradient(to bottom,rgba(255,255,255,0.2) 2%, rgba(0,0,0,0.1) 98%);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), inset 0 -1px 0 rgba(0, 0, 0, 0.2), 0 2px 3px rgba(0, 0, 0, 0.05);
outline: none;
cursor: pointer;
color: #fff;
text-align: center;
position: relative;
font: inherit;
font-weight: 600;
}
#button-submit:focus:after {
box-shadow: 0 0 0 2px rgba(0,0,0,.5);
content: "";
position: absolute;
top: -2px;
right: -2px;
bottom: -2px;
left: -2px;
border-radius: inherit;
}
.error input {
display: block;
border-color: red;
}
.error form:after {
content: "The username and password you entered do not match our records. Please double-check and try again.";
display: block;
border: 1px solid red;
border-radius: 4px;
width: 100%;
margin-top: 16px;
font-size: 14px;
padding: 8px;
}
</style>
</head>
<body onload="init()">
<div id="form">
<form method="post" action="" id="theform">
<h2>Страница входа</h2>
<label id="login-label" for="login">Логин</label>
<input type="text" id="login" name="username" aria-labelledby="login-label" autofocus>
<label id="password-label" for="password">Пароль</label>
<input type="password" id="password" name="password" aria-labelledby="password-label">
<button id="button-submit" type="submit">Войти</button>
</form>
</div>
</body>
</html>
我特别感兴趣的是什么。Vaadin 版本 8 有一个 LoginForm,据推测,浏览器可以使用它来确定和保存登录/密码字段。它实际上只适用于 Firefox,这不适合我。使用面包店应用程序中提供的这种方法,保存登录名/密码没有问题。但是,在快速运行了整个演示项目之后,我并没有发现 LoginHtmlServlet 的使用位置和方式。我也没有找到任何信息。所以,一个具体的问题:您如何准确地同时使用 servlet 和 vaadin 项目,如何使用来自 vaadin 项目的附加 servlet。
一般来说,如何实现与演示项目中相同的登录?
演示项目使用 Shiro 进行身份验证。
文件夹
src\main\resources
中是shiro.ini
. 在其中shiro.loginURL=/login.html
。仅在此 url 中显示WebServlet
。urlPаtterns
也就是说,身份验证页面确定 Shiro(即第一次重定向到
localhost:8080/login.html
.)。它还检查用户/密码是否匹配。LoginHtmlServlet
根据 get/post,将页面写入响应流。如果授权失败 -->resp.sendRedirect(LOGIN_HTML + "?error");
在应用程序中使用多个 servlet 最好在这里描述:映射子路径