提交 9ecff4d3 编写于 作者: J jbarrez

ACT-696: Added login page + authentication check

上级 ab6cc11c
......@@ -23,14 +23,18 @@ import java.text.SimpleDateFormat;
public class Constants {
public static final String THEME = "activiti";
public static final String LOGIN_LAYOUT = "login";
// Locations in the general layout
public static final String LOCATION_LOGIN = "login-content";
public static final String LOCATION_CONTENT = "content";
public static final String LOCATION_SEARCH = "search";
public static final String LOCATION_MAIN_MENU = "main-menu";
public static final String LOCATION_HIDDEN = "hidden";
// Css styles
public static final String STYLE_LOGIN_PAGE = "login-general";
public static final String STYLE_SMALL_TEXTFIELD = "small";
public static final String STYLE_SEARCHBOX = "searchBox";
public static final String STYLE_LOGOUT_BUTTON = "logout";
......
......@@ -18,18 +18,14 @@ package org.activiti.explorer;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.identity.User;
import org.activiti.engine.impl.identity.Authentication;
import org.activiti.engine.impl.util.LogUtil;
import org.activiti.explorer.navigation.NavigationFragmentChangeListener;
import org.activiti.explorer.navigation.UriFragment;
import org.activiti.explorer.ui.MainLayout;
import com.vaadin.Application;
import com.vaadin.terminal.gwt.server.HttpServletRequestListener;
import com.vaadin.ui.Component;
import com.vaadin.ui.UriFragmentUtility;
import com.vaadin.ui.Window;
import com.vaadin.ui.Window.Notification;
......@@ -46,30 +42,12 @@ public class ExplorerApplication extends Application implements HttpServletReque
private static ThreadLocal<ExplorerApplication> current = new ThreadLocal<ExplorerApplication>();
protected Window mainWindow;
protected MainLayout mainLayout;
protected UriFragmentUtility uriFragmentUtility;
protected UriFragment currentUriFragment;
protected MainWindow mainWindow;
public void init() {
// Demo
setUser(ProcessEngines.getDefaultProcessEngine().getIdentityService()
.createUserQuery().userId("kermit").singleResult());
ProcessEngines.getDefaultProcessEngine().getIdentityService().setAuthenticatedUserId("kermit");
// Demo
// init window
mainWindow = new Window("Explorer - The Next generation");
this.mainWindow = new MainWindow();
setMainWindow(mainWindow);
setTheme(Constants.THEME);
// init general look and feel
mainLayout = new MainLayout(this);
mainWindow.setContent(mainLayout);
// init hidden components
initHiddenComponents();
mainWindow.showLoginPage();
}
/**
......@@ -95,7 +73,15 @@ public class ExplorerApplication extends Application implements HttpServletReque
}
public void switchView(Component component) {
mainLayout.addComponent(component, Constants.LOCATION_CONTENT);
mainWindow.switchView(component);
}
public void showLoginPage() {
mainWindow.showLoginPage();
}
public void showDefaultContent() {
mainWindow.showDefaultContent();
}
public User getLoggedInUser() {
......@@ -120,10 +106,15 @@ public class ExplorerApplication extends Application implements HttpServletReque
// Set current application object as thread-local to make it easy accessible
current.set(this);
// Set thread-local userid of logged in user (needed for Activiti user logic)
// Authentication: check if user is found, otherwise send to login page
User user = (User) getUser();
if (user != null) {
Authentication.setAuthenticatedUserId("kermit");
if (user == null) {
if (mainWindow != null && !mainWindow.isShowingLoginPage()) {
showLoginPage();
}
} else {
// Set thread-local userid of logged in user (needed for Activiti user logic)
Authentication.setAuthenticatedUserId(user.getId());
}
}
......@@ -135,42 +126,7 @@ public class ExplorerApplication extends Application implements HttpServletReque
// URL handling ---------------------------------------------------------------------------------
protected void initHiddenComponents() {
// Add the URI Fragent utility
uriFragmentUtility = new UriFragmentUtility();
mainLayout.addComponent(uriFragmentUtility, Constants.LOCATION_HIDDEN);
// Add listener to control page flow based on URI
uriFragmentUtility.addListener(new NavigationFragmentChangeListener());
}
public UriFragment getCurrentUriFragment() {
return currentUriFragment;
}
/**
* Sets the current {@link UriFragment}.
* Won't trigger navigation, just updates the URI fragment in the browser.
*/
public void setCurrentUriFragment(UriFragment fragment) {
this.currentUriFragment = fragment;
if(fragmentChanged(fragment)) {
if(fragment != null) {
uriFragmentUtility.setFragment(fragment.toString(), false);
} else {
uriFragmentUtility.setFragment("", false);
}
}
}
private boolean fragmentChanged(UriFragment fragment) {
String fragmentString = fragment.toString();
if(fragmentString == null) {
return uriFragmentUtility.getFragment() != null;
} else {
return !fragmentString.equals(uriFragmentUtility.getFragment());
}
mainWindow.setCurrentUriFragment(fragment);
}
}
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.activiti.explorer;
import org.activiti.explorer.navigation.NavigationFragmentChangeListener;
import org.activiti.explorer.navigation.UriFragment;
import org.activiti.explorer.ui.MainLayout;
import org.activiti.explorer.ui.login.LoginPage;
import com.vaadin.ui.Component;
import com.vaadin.ui.UriFragmentUtility;
import com.vaadin.ui.Window;
/**
* @author Joram Barrez
*/
public class MainWindow extends Window {
private static final long serialVersionUID = 1L;
protected MainLayout mainLayout;
protected UriFragmentUtility uriFragmentUtility;
protected UriFragment currentUriFragment;
protected boolean showingLoginPage;
public MainWindow() {
super("Explorer - The Next generation");
setTheme(Constants.THEME);
}
public void showLoginPage() {
showingLoginPage = true;
addStyleName(Constants.STYLE_LOGIN_PAGE);
setContent(new LoginPage());
}
public void showDefaultContent() {
showingLoginPage = false;
removeStyleName(Constants.STYLE_LOGIN_PAGE);
addStyleName("Default style"); // Bug: must set something or old style is not overwritten
// init general look and feel
mainLayout = new MainLayout();
setContent(mainLayout);
// init hidden components
initHiddenComponents();
}
// View handling
public void switchView(Component component) {
mainLayout.addComponent(component, Constants.LOCATION_CONTENT);
}
// URL handling
protected void initHiddenComponents() {
// Add the URI Fragent utility
uriFragmentUtility = new UriFragmentUtility();
mainLayout.addComponent(uriFragmentUtility, Constants.LOCATION_HIDDEN);
// Add listener to control page flow based on URI
uriFragmentUtility.addListener(new NavigationFragmentChangeListener());
}
public UriFragment getCurrentUriFragment() {
return currentUriFragment;
}
/**
* Sets the current {@link UriFragment}.
* Won't trigger navigation, just updates the URI fragment in the browser.
*/
public void setCurrentUriFragment(UriFragment fragment) {
this.currentUriFragment = fragment;
if(fragmentChanged(fragment)) {
if(fragment != null) {
uriFragmentUtility.setFragment(fragment.toString(), false);
} else {
uriFragmentUtility.setFragment("", false);
}
}
}
private boolean fragmentChanged(UriFragment fragment) {
String fragmentString = fragment.toString();
if(fragmentString == null) {
return uriFragmentUtility.getFragment() != null;
} else {
return !fragmentString.equals(uriFragmentUtility.getFragment());
}
}
public boolean isShowingLoginPage() {
return showingLoginPage;
}
}
......@@ -13,6 +13,7 @@
package org.activiti.explorer.ui;
import org.activiti.engine.identity.User;
import org.activiti.explorer.Constants;
import org.activiti.explorer.ExplorerApplication;
import org.activiti.explorer.Images;
......@@ -36,7 +37,7 @@ public class MainLayout extends CustomLayout {
protected MainMenuBar mainMenuBar;
public MainLayout(ExplorerApplication explorerApplication) {
public MainLayout() {
super(Constants.THEME);
setSizeFull();
......@@ -61,14 +62,15 @@ public class MainLayout extends CustomLayout {
logoutGrid.setStyleName(Constants.STYLE_LOGOUT_BUTTON);
// User name + link to profile
Button userButton = new Button("Kermit The Frog");
final User user = ExplorerApplication.getCurrent().getLoggedInUser();
Button userButton = new Button(user.getFirstName() + " " + user.getLastName());
userButton.setIcon(Images.USER);
userButton.addStyleName(Constants.STYLE_USER_LABEL);
userButton.addStyleName(Reindeer.BUTTON_LINK);
userButton.addListener(new ClickListener() {
public void buttonClick(ClickEvent event) {
ExplorerApplication.getCurrent().switchView(new ProfilePage("kermit"));
ExplorerApplication.getCurrent().switchView(new ProfilePage(user.getId()));
}
});
......
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.activiti.explorer.ui.login;
import org.activiti.explorer.Constants;
import com.vaadin.ui.LoginForm;
/**
* @author Joram Barrez
*/
public class CustomLoginForm extends LoginForm {
private static final long serialVersionUID = 1L;
protected String usernameCaption;
protected String passwordCaption;
protected String submitCaption;
protected static final String STYLE_LOGIN_FIELD = "login-field";
protected static final String STYLE_LOGIN_FIELD_CAPTION = "login-field-caption";
protected static final String STYLE_LOGIN_BUTTON = "login-button";
public CustomLoginForm() {
usernameCaption = "User ID";
passwordCaption = "Password";
submitCaption = "Log in";
}
// Hack-alert !! See explanation at http://vaadin.com/book/-/page/components.loginform.html
protected byte[] getLoginHTML() {
// Application URI needed for submitting form
String appUri = getApplication().getURL().toString()
+ getWindow().getName() + "/";
String x, h, b; // XML header, HTML head and body
x = "<!DOCTYPE html PUBLIC \"-//W3C//DTD "
+ "XHTML 1.0 Transitional//EN\" "
+ "\"http://www.w3.org/TR/xhtml1/"
+ "DTD/xhtml1-transitional.dtd\">\n";
h = "<head><script type='text/javascript'>"
+ "var setTarget = function() {"
+ " var uri = '" + appUri + "loginHandler';"
+ " var f = document.getElementById('loginf');"
+ " document.forms[0].action = uri;"
+ " document.forms[0].username.focus();"
+ "};"
+ ""
+ "var styles = window.parent.document.styleSheets;"
+ "for(var j = 0; j < styles.length; j++) {\n"
+ " if(styles[j].href) {"
+ " var stylesheet = document.createElement('link');\n"
+ " stylesheet.setAttribute('rel', 'stylesheet');\n"
+ " stylesheet.setAttribute('type', 'text/css');\n"
+ " stylesheet.setAttribute('href', styles[j].href);\n"
+ " document.getElementsByTagName('head')[0]"
+ " .appendChild(stylesheet);\n"
+ " }"
+ "}\n"
+ "function submitOnEnter(e) {"
+ " var keycode = e.keyCode || e.which;"
+ " if (keycode == 13) {document.forms[0].submit();}"
+ "}\n"
+ "</script>"
+ "</head>";
b = "<body onload='setTarget();'"
+ " class='" + Constants.STYLE_LOGIN_PAGE + "'>" // todo
+ "<div>"
+ "<iframe name='logintarget' style='width:0;height:0;"
+ "border:0;margin:0;padding:0;'></iframe>"
+ "<form id='loginf' target='logintarget'"
+ " onkeypress='submitOnEnter(event)'"
+ " method='post'>"
+ "<table>"
+ "<tr><td class='" + STYLE_LOGIN_FIELD_CAPTION + "'>" + usernameCaption + "</td>"
+ "<td><input class='" + STYLE_LOGIN_FIELD +"' type='text' name='username'></td></tr>"
+ "<tr><td class='" + STYLE_LOGIN_FIELD_CAPTION + "'>" + passwordCaption + "</td>"
+ " <td><input class='" + STYLE_LOGIN_FIELD + "'"
+ " type='password'"
+ " name='password'></td></tr>"
+ "</table>"
+ "<div>"
+ "<div onclick='document.forms[0].submit();'"
+ " tabindex='0' class='" + STYLE_LOGIN_BUTTON + "' role='button'>"
+ "<span>" + submitCaption + "</span>"
+ "</span></div></div></form></div></body>";
return (x + "<html>" + h + b + "</html>").getBytes();
}
}
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.activiti.explorer.ui.login;
import org.activiti.engine.IdentityService;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.identity.User;
import org.activiti.explorer.Constants;
import org.activiti.explorer.ExplorerApplication;
import com.vaadin.ui.CustomLayout;
import com.vaadin.ui.LoginForm.LoginEvent;
import com.vaadin.ui.LoginForm.LoginListener;
/**
* @author Joram Barrez
*/
public class LoginPage extends CustomLayout {
private static final long serialVersionUID = 1L;
protected IdentityService identityService = ProcessEngines.getDefaultProcessEngine().getIdentityService();
public LoginPage() {
super(Constants.LOGIN_LAYOUT); // Layout is defined in /activiti/login.html + styles.css
addStyleName(Constants.STYLE_LOGIN_PAGE);
initUi();
}
protected void initUi() {
// Login form is an atypical Vaadin component, since we want browsers to fill the password fields
CustomLoginForm loginForm = new CustomLoginForm();
addComponent(loginForm, Constants.LOCATION_LOGIN);
// Login listener
loginForm.addListener(new ActivitiLoginListener());
}
protected void refreshUi() {
// Quick and dirty 'refresh'
removeAllComponents();
initUi();
}
class ActivitiLoginListener implements LoginListener {
private static final long serialVersionUID = 1L;
public void onLogin(LoginEvent event) {
String userName = event.getLoginParameter("username"); // see the input field names in CustomLoginForm
String password = event.getLoginParameter("password"); // see the input field names in CustomLoginForm
boolean success = identityService.checkPassword(userName, password);
if (success) {
User user = identityService.createUserQuery().userId(userName).singleResult();
ExplorerApplication.getCurrent().setUser(user);
ExplorerApplication.getCurrent().showDefaultContent();
} else {
refreshUi();
ExplorerApplication.getCurrent().showErrorNotification("Could not log you in", "Invalid user id and/or password");
}
}
}
}
<div class="login-general">
<div id="login-central-components">
<div id="login-logo">
<img src="../img/explorer-logo.png">
</div>
<div id="login-content" location="login-content">
</div>
</div>
<div id="login-background"></div>
</div>
@import url(../reindeer/styles.css);
/* -----
Login
----- */
/* General backrgound and font settings */
.login-general {
color: white; /* color of text */
font-family: Helvetica, Arial, sans-serif;
background: #1b7ec3; /* non-white part of page */
font-size: 16px;
font-weight: bold;
}
#login-content {
height: 200px;
}
/* white part of background */
#login-background {
position: absolute;
top: 0;
left: 0;
background: white;
height: 250px;
width: 100%;
border-bottom: solid 3px #a9b3ba; /* gray-blueish horitzontal line in the middle */
}
#login-central-components {
margin: 0 0 0 -185px;
width: 370px;
text-align: center;
position: absolute;
left: 50%;
z-index: 1;
}
#login-logo {
height: 130px;
padding-top: 140px;
}
/* Text fields of input form */
input.login-field {
font-size: 16px;
height:40px;
width: 250px;
margin-left: 10px;
padding-left: 7px; /* To start the typing of the text a bit to the right */
float: right;
background: white;
border: solid 1px transparent;
margin-bottom: 2px;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
}
.login-field-caption {
line-height: 200%
}
/* 'Log in' Button */
.login-button {
text-align: center;
line-height: 200%;
float: right;
width: 80px;
height: 30px;
margin-top: 5px;
color: white;
font-size: 14px;
background-color: #55ba49;
border: solid 1px transparent;
font-weight: bold;
letter-spacing: 1px;
cursor: pointer;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
}
.login-button:hover {
background-color: #86e379;
}
/* ----------
Main layout
----------- */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册